Delay codegen of vtables when handling implicit instantiations.

This fixes PR6474.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98123 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 932bd07..a77a28c 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -3405,7 +3405,22 @@
   Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0,
                           /*IsVirtual=*/false,
                           AddressPoints);
-  GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);  
+  GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
+
+  for (CXXRecordDecl::method_iterator i = RD->method_begin(),
+	 e = RD->method_end(); i != e; ++i) {
+    if (!(*i)->isVirtual())
+      continue;
+    if(!(*i)->hasInlineBody() && !(*i)->isImplicit())
+      continue;
+
+    if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
+      CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
+      CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
+    } else {
+      CGM.BuildThunksForVirtual(GlobalDecl(*i));
+    }
+  }
 }
 
 llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
@@ -3438,19 +3453,12 @@
       return;
   }
 
-  // Emit the data.
-  GenerateClassData(CGM.getVtableLinkage(RD), RD);
+  if (Vtables.count(RD))
+    return;
 
-  for (CXXRecordDecl::method_iterator i = RD->method_begin(),
-       e = RD->method_end(); i != e; ++i) {
-    if ((*i)->isVirtual() && ((*i)->hasInlineBody() || (*i)->isImplicit())) {
-      if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(*i)) {
-        CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Complete));
-        CGM.BuildThunksForVirtual(GlobalDecl(DD, Dtor_Deleting));
-      } else {
-        CGM.BuildThunksForVirtual(GlobalDecl(*i));
-      }
-    }
-  }
+  TemplateSpecializationKind kind = RD->getTemplateSpecializationKind();
+  if (kind == TSK_ImplicitInstantiation)
+    CGM.DeferredVtables.push_back(RD);
+  else
+    GenerateClassData(CGM.getVtableLinkage(RD), RD);
 }
-
diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h
index 6ccb011..57220d9 100644
--- a/lib/CodeGen/CGVtable.h
+++ b/lib/CodeGen/CGVtable.h
@@ -173,15 +173,7 @@
   uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
   
   void ComputeMethodVtableIndices(const CXXRecordDecl *RD);
-  
-  /// GenerateClassData - Generate all the class data requires to be generated
-  /// upon definition of a KeyFunction.  This includes the vtable, the
-  /// rtti data structure and the VTT.
-  /// 
-  /// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT.
-  void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
-                         const CXXRecordDecl *RD);
- 
+   
   llvm::GlobalVariable *
   GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
                  bool GenerateDefinition, const CXXRecordDecl *LayoutClass, 
@@ -245,6 +237,14 @@
   llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD);
   
   void MaybeEmitVtable(GlobalDecl GD);
+
+  /// GenerateClassData - Generate all the class data requires to be generated
+  /// upon definition of a KeyFunction.  This includes the vtable, the
+  /// rtti data structure and the VTT.
+  ///
+  /// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT.
+  void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
+                         const CXXRecordDecl *RD);
 };
 
 } // end namespace CodeGen
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index d6a56da..c67948d 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -488,7 +488,15 @@
   // Emit code for any potentially referenced deferred decls.  Since a
   // previously unused static decl may become used during the generation of code
   // for a static function, iterate until no  changes are made.
-  while (!DeferredDeclsToEmit.empty()) {
+
+  while (!DeferredDeclsToEmit.empty() || !DeferredVtables.empty()) {
+    if (!DeferredVtables.empty()) {
+      const CXXRecordDecl *RD = DeferredVtables.back();
+      DeferredVtables.pop_back();
+      getVtableInfo().GenerateClassData(getVtableLinkage(RD), RD);
+      continue;
+    }
+
     GlobalDecl D = DeferredDeclsToEmit.back();
     DeferredDeclsToEmit.pop_back();
 
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index c86f8b4..40dc563 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -451,7 +451,9 @@
   /// GetTargetTypeStoreSize - Return the store size, in character units, of
   /// the given LLVM type.
   CharUnits GetTargetTypeStoreSize(const llvm::Type *Ty) const;
-  
+
+  std::vector<const CXXRecordDecl*> DeferredVtables;
+
 private:
   /// UniqueMangledName - Unique a name by (if necessary) inserting it into the
   /// MangledNames string map.
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a89f355..79cab15 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5902,10 +5902,13 @@
 
   // We will need to mark all of the virtual members as referenced to build the
   // vtable.
-  // We actually call MarkVirtualMembersReferenced instead of adding to
-  // ClassesWithUnmarkedVirtualMembers because this marking is needed by
-  // codegen that will happend before we finish parsing the file.
-  if (needsVtable(MD, Context))
+  if (!needsVtable(MD, Context))
+    return;
+
+  TemplateSpecializationKind kind = RD->getTemplateSpecializationKind();
+  if (kind == TSK_ImplicitInstantiation)
+    ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc));
+  else
     MarkVirtualMembersReferenced(Loc, RD);
 }
 
diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp
index b6e85e2..7de9dd2 100644
--- a/test/CodeGenCXX/virtual-base-destructor-call.cpp
+++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp
@@ -22,6 +22,11 @@
 //  CHECK: call void @_ZN14basic_iostreamIcED2Ev
 //  CHECK: call void @_ZN9basic_iosD2Ev
 
+// basic_iostream's base dtor calls its non-virtual base dtor.
+//  CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED2Ev
+//  CHECK: call void @_ZN13basic_istreamIcED2Ev
+//  CHECK: }
+
 // basic_iostream's deleting dtor calls its complete dtor, then
 // operator delete().
 //  CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev
@@ -40,11 +45,6 @@
 //  CHECK: call void @_ZN13basic_istreamIcED1Ev
 //  CHECK: call void @_ZdlPv
 
-// basic_iostream's base dtor calls its non-virtual base dtor.
-//  CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED2Ev
-//  CHECK: call void @_ZN13basic_istreamIcED2Ev
-//  CHECK: }
-
 // basic_istream's base dtor is a no-op.
 //  CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev
 //  CHECK-NOT: call
diff --git a/test/SemaTemplate/virtual-member-functions.cpp b/test/SemaTemplate/virtual-member-functions.cpp
index 58ac08c..8df808d 100644
--- a/test/SemaTemplate/virtual-member-functions.cpp
+++ b/test/SemaTemplate/virtual-member-functions.cpp
@@ -14,7 +14,7 @@
 }
 
 void f(A<int> x) {
-  x.anchor(); // expected-note{{in instantiation of member function 'PR5557::A<int>::anchor' requested here}}
+  x.anchor();
 }
 
 template<typename T>
@@ -52,4 +52,4 @@
   return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}}
 }
 
-HasOutOfLineKey<int> out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::HasOutOfLineKey' requested here}}
+HasOutOfLineKey<int> out_of_line;