]> granicus.if.org Git - clang/commitdiff
Delay codegen of vtables when handling implicit instantiations.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 10 Mar 2010 02:19:29 +0000 (02:19 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 10 Mar 2010 02:19:29 +0000 (02:19 +0000)
This fixes PR6474.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98123 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVtable.cpp
lib/CodeGen/CGVtable.h
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/Sema/SemaDeclCXX.cpp
test/CodeGenCXX/virtual-base-destructor-call.cpp
test/SemaTemplate/virtual-member-functions.cpp

index 932bd079e93f6d12b811d606ed12dffff1938ece..a77a28ccdd80c9de80ec294bf575b3754d471f78 100644 (file)
@@ -3405,7 +3405,22 @@ void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
   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 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
       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);
 }
-
index 6ccb011985fd62bb29cf801f09425290a7be9883..57220d9d5af5ec1c3f09a80b8e28f113ee18b7d6 100644 (file)
@@ -173,15 +173,7 @@ private:
   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 @@ public:
   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
index d6a56dad0ba576db6a101f8f623f259c41e6fda9..c67948d27f085e37eac6ccef4893eb876e3917ed 100644 (file)
@@ -488,7 +488,15 @@ void CodeGenModule::EmitDeferred() {
   // 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();
 
index c86f8b45bcddf024ec0318e04028e9c796165025..40dc5638898175b4a68e160912c0ca20e744cc49 100644 (file)
@@ -451,7 +451,9 @@ public:
   /// 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.
index a89f355147fcc3420ee84b225c735cb5fb5c94ad..79cab15e69128c66de5b84010d5086e65c058876 100644 (file)
@@ -5902,10 +5902,13 @@ void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc,
 
   // 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);
 }
 
index b6e85e208b154671199076f6c70fc318ccd7e6a7..7de9dd2a608595de2487d95ac51f121c1114f477 100644 (file)
@@ -22,6 +22,11 @@ int main() {
 //  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 @@ int main() {
 //  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
index 58ac08c0b21b1935a3e89aea7d8fd0301a5defe1..8df808d2569a554f765acebe02e80b6977e8510c 100644 (file)
@@ -14,7 +14,7 @@ template<class T> int A<T>::a(T x) {
 }
 
 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 @@ T *HasOutOfLineKey<T>::f(float *fp) {
   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;