Track overriding methods when instantiating a template class. Fixes PR5550.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89248 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index a13ffc5..6a2b6d9 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -567,6 +567,7 @@
MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition,
bool &Redeclaration);
+ void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
bool IsExplicitSpecialization,
bool &Redeclaration,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 57c101b..c2c048b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2486,6 +2486,26 @@
return false;
}
+/// AddOverriddenMethods - See if a method overrides any in the base classes,
+/// and if so, check that it's a valid override and remember it.
+void Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
+ // Look for virtual methods in base classes that this method might override.
+ CXXBasePaths Paths;
+ FindOverriddenMethodData Data;
+ Data.Method = MD;
+ Data.S = this;
+ if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) {
+ for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
+ E = Paths.found_decls_end(); I != E; ++I) {
+ if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
+ if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
+ !CheckOverridingFunctionExceptionSpec(MD, OldMD))
+ MD->addOverriddenMethod(OldMD);
+ }
+ }
+ }
+}
+
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, DeclaratorInfo *DInfo,
@@ -2746,24 +2766,8 @@
}
- if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) {
- // Look for virtual methods in base classes that this method might override.
- CXXBasePaths Paths;
- FindOverriddenMethodData Data;
- Data.Method = NewMD;
- Data.S = this;
- if (cast<CXXRecordDecl>(DC)->lookupInBases(&FindOverriddenMethod, &Data,
- Paths)) {
- for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
- E = Paths.found_decls_end(); I != E; ++I) {
- if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
- if (!CheckOverridingFunctionReturnType(NewMD, OldMD) &&
- !CheckOverridingFunctionExceptionSpec(NewMD, OldMD))
- NewMD->addOverriddenMethod(OldMD);
- }
- }
- }
- }
+ if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
+ AddOverriddenMethods(cast<CXXRecordDecl>(DC), NewMD);
if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) &&
!CurContext->isRecord()) {
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 7e618cd..deb7ff0 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -869,6 +869,8 @@
!Method->getFriendObjectKind())
Owner->addDecl(Method);
+ SemaRef.AddOverriddenMethods(Record, Method);
+
return Method;
}
diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp
index 42b8d7f..3db607a 100644
--- a/test/SemaCXX/abstract.cpp
+++ b/test/SemaCXX/abstract.cpp
@@ -138,3 +138,20 @@
C c;
}
+
+// PR5550 - instantiating template didn't track overridden methods
+namespace PR5550 {
+ struct A {
+ virtual void a() = 0;
+ virtual void b() = 0;
+ };
+ template<typename T> struct B : public A {
+ virtual void b();
+ virtual void c() = 0;
+ };
+ struct C : public B<int> {
+ virtual void a();
+ virtual void c();
+ };
+ C x;
+}