]> granicus.if.org Git - clang/commitdiff
Track overriding methods when instantiating a template class. Fixes PR5550.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Wed, 18 Nov 2009 21:51:29 +0000 (21:51 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Wed, 18 Nov 2009 21:51:29 +0000 (21:51 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89248 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaCXX/abstract.cpp

index a13ffc54da341256094aef208c9fc15a3bf40b29..6a2b6d971bc132bbd511d9a30b861130deae0ae3 100644 (file)
@@ -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,
index 57c101bd32ce5d9fa927fa89eda7cf1e0f642d05..c2c048b3cf8f68fddafbc2ecc828ca84aa02e2a1 100644 (file)
@@ -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()) {
index 7e618cd4faeaec249d17756361a203ebfc74b469..deb7ff0ccc685bbf7006e7765ee1288f2d83ba44 100644 (file)
@@ -869,6 +869,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
       !Method->getFriendObjectKind())
     Owner->addDecl(Method);
 
+  SemaRef.AddOverriddenMethods(Record, Method);
+
   return Method;
 }
 
index 42b8d7febe655a4c245413f586c5388588d101c9..3db607a365c095ec8643dcdda7846228e81f912a 100644 (file)
@@ -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;
+}