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;
+}