aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2009-11-18 21:51:29 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2009-11-18 21:51:29 +0000
commita165da09c0313309d2d4dda42d0b2d4096a372a1 (patch)
treed5bc75ea831ac85f2866c1b083c300fe00d5a77f
parent1ce9cf06b6618b5a1e9d96995f914f48fe92bec6 (diff)
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
-rw-r--r--lib/Sema/Sema.h1
-rw-r--r--lib/Sema/SemaDecl.cpp40
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp2
-rw-r--r--test/SemaCXX/abstract.cpp17
4 files changed, 42 insertions, 18 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index a13ffc54da..6a2b6d971b 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -567,6 +567,7 @@ public:
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 57c101bd32..c2c048b3cf 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2486,6 +2486,26 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
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 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
- 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 7e618cd4fa..deb7ff0ccc 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -869,6 +869,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
!Method->getFriendObjectKind())
Owner->addDecl(Method);
+ SemaRef.AddOverriddenMethods(Record, Method);
+
return Method;
}
diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp
index 42b8d7febe..3db607a365 100644
--- a/test/SemaCXX/abstract.cpp
+++ b/test/SemaCXX/abstract.cpp
@@ -138,3 +138,20 @@ namespace PR5222 {
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;
+}