]> granicus.if.org Git - clang/commitdiff
Don't try to emit the vtable for a class just because we're emitting a
authorJohn McCall <rjmccall@apple.com>
Wed, 2 Jun 2010 21:22:02 +0000 (21:22 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 2 Jun 2010 21:22:02 +0000 (21:22 +0000)
virtual function from it.

Fixes PR7241.

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

lib/CodeGen/CGVTables.cpp
lib/CodeGen/CGVTables.h
test/CodeGenCXX/thunks.cpp
test/CodeGenCXX/virtual-base-destructor-call.cpp

index 81e80cc26e514838271a6cb06dd158d83bbdad7f..1aa9a11fc10ba227a7c2ba381a8584caef72d491 100644 (file)
@@ -2745,7 +2745,7 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
   const CXXRecordDecl *RD = MD->getParent();
   
   // Compute VTable related info for this class.
-  ComputeVTableRelatedInformation(RD);
+  ComputeVTableRelatedInformation(RD, false);
   
   ThunksMapTy::const_iterator I = Thunks.find(MD);
   if (I == Thunks.end()) {
@@ -2758,24 +2758,30 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
     EmitThunk(GD, ThunkInfoVector[I]);
 }
 
-void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
-  uint64_t *&LayoutData = VTableLayoutMap[RD];
+void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
+                                                     bool RequireVTable) {
+  VTableLayoutData &Entry = VTableLayoutMap[RD];
+
+  // We may need to generate a definition for this vtable.
+  if (RequireVTable && !Entry.getInt()) {
+    if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) &&
+        RD->getTemplateSpecializationKind()
+          != TSK_ExplicitInstantiationDeclaration)
+      CGM.DeferredVTables.push_back(RD);
+
+    Entry.setInt(true);
+  }
   
   // Check if we've computed this information before.
-  if (LayoutData)
+  if (Entry.getPointer())
     return;
 
-  // We may need to generate a definition for this vtable.
-  if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) &&
-      RD->getTemplateSpecializationKind()
-                                      != TSK_ExplicitInstantiationDeclaration)
-    CGM.DeferredVTables.push_back(RD);
-
   VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD);
 
   // Add the VTable layout.
   uint64_t NumVTableComponents = Builder.getNumVTableComponents();
-  LayoutData = new uint64_t[NumVTableComponents + 1];
+  uint64_t *LayoutData = new uint64_t[NumVTableComponents + 1];
+  Entry.setPointer(LayoutData);
 
   // Store the number of components.
   LayoutData[0] = NumVTableComponents;
@@ -2990,7 +2996,7 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
   CGM.getMangleContext().mangleCXXVTable(RD, OutName);
   llvm::StringRef Name = OutName.str();
 
-  ComputeVTableRelatedInformation(RD);
+  ComputeVTableRelatedInformation(RD, true);
   
   const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
   llvm::ArrayType *ArrayType = 
index e55377f2fa2fe32acc602f8ae87b9f14940c5d4f..4c790f92abc067e19a5db218a8c5c93ee088d435 100644 (file)
@@ -207,8 +207,12 @@ class CodeGenVTables {
   
   /// Thunks - Contains all thunks that a given method decl will need.
   ThunksMapTy Thunks;
-  
-  typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t *> VTableLayoutMapTy;
+
+  // The layout entry and a bool indicating whether we've actually emitted
+  // the vtable.
+  typedef llvm::PointerIntPair<uint64_t *, 1, bool> VTableLayoutData;
+  typedef llvm::DenseMap<const CXXRecordDecl *, VTableLayoutData>
+    VTableLayoutMapTy;
   
   /// VTableLayoutMap - Stores the vtable layout for all record decls.
   /// The layout is stored as an array of 64-bit integers, where the first
@@ -237,13 +241,13 @@ class CodeGenVTables {
   uint64_t getNumVTableComponents(const CXXRecordDecl *RD) const {
     assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!");
     
-    return VTableLayoutMap.lookup(RD)[0];
+    return VTableLayoutMap.lookup(RD).getPointer()[0];
   }
 
   const uint64_t *getVTableComponentsData(const CXXRecordDecl *RD) const {
     assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!");
 
-    uint64_t *Components = VTableLayoutMap.lookup(RD);
+    uint64_t *Components = VTableLayoutMap.lookup(RD).getPointer();
     return &Components[1];
   }
 
@@ -275,7 +279,8 @@ class CodeGenVTables {
   /// ComputeVTableRelatedInformation - Compute and store all vtable related
   /// information (vtable layout, vbase offset offsets, thunks etc) for the
   /// given record decl.
-  void ComputeVTableRelatedInformation(const CXXRecordDecl *RD);
+  void ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
+                                       bool VTableRequired);
 
   /// CreateVTableInitializer - Create a vtable initializer for the given record
   /// decl.
index 79ca709f470da397833213df09f5c26b8a95bf76..1de576128a11d2a7832d5e57a1283fa2a98fca64 100644 (file)
@@ -234,6 +234,18 @@ namespace Test8 {
   void C::bar(NonPOD var) {}
 }
 
+// PR7241: Emitting thunks for a method shouldn't require the vtable for
+// that class to be emitted.
+namespace Test9 {
+  struct A { virtual ~A() { } };
+  struct B : A { virtual void test() const {} };
+  struct C : B { C(); ~C(); };
+  struct D : C { D() {} };
+  void test() {
+    D d;
+  }
+}
+
 /**** The following has to go at the end of the file ****/
 
 // This is from Test5:
index 22c49a089d0d2ba33c5159c7c7e4b7686fab73d4..4618a03b9d3f617f2ccfc20b410974508dde10bb 100644 (file)
@@ -27,6 +27,11 @@ int main() {
 //  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
+//  CHECK: }
+
 // basic_iostream's deleting dtor calls its complete dtor, then
 // operator delete().
 //  CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev
@@ -44,9 +49,3 @@ int main() {
 //  CHECK: define linkonce_odr void @_ZN13basic_istreamIcED0Ev
 //  CHECK: call void @_ZN13basic_istreamIcED1Ev
 //  CHECK: call void @_ZdlPv
-
-// basic_istream's base dtor is a no-op.
-//  CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev
-//  CHECK-NOT: call
-//  CHECK: }
-