Don't try to emit the vtable for a class just because we're emitting a

virtual function from it.

Fixes PR7241.

llvm-svn: 105345
This commit is contained in:
John McCall 2010-06-02 21:22:02 +00:00
parent f2dffcef82
commit 6a7f9f5c8f
4 changed files with 46 additions and 24 deletions

View File

@ -2745,7 +2745,7 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
const CXXRecordDecl *RD = MD->getParent(); const CXXRecordDecl *RD = MD->getParent();
// Compute VTable related info for this class. // Compute VTable related info for this class.
ComputeVTableRelatedInformation(RD); ComputeVTableRelatedInformation(RD, false);
ThunksMapTy::const_iterator I = Thunks.find(MD); ThunksMapTy::const_iterator I = Thunks.find(MD);
if (I == Thunks.end()) { if (I == Thunks.end()) {
@ -2758,24 +2758,30 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
EmitThunk(GD, ThunkInfoVector[I]); EmitThunk(GD, ThunkInfoVector[I]);
} }
void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
uint64_t *&LayoutData = VTableLayoutMap[RD]; bool RequireVTable) {
VTableLayoutData &Entry = VTableLayoutMap[RD];
// Check if we've computed this information before.
if (LayoutData)
return;
// We may need to generate a definition for this vtable. // We may need to generate a definition for this vtable.
if (RequireVTable && !Entry.getInt()) {
if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) && if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) &&
RD->getTemplateSpecializationKind() RD->getTemplateSpecializationKind()
!= TSK_ExplicitInstantiationDeclaration) != TSK_ExplicitInstantiationDeclaration)
CGM.DeferredVTables.push_back(RD); CGM.DeferredVTables.push_back(RD);
Entry.setInt(true);
}
// Check if we've computed this information before.
if (Entry.getPointer())
return;
VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD); VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD);
// Add the VTable layout. // Add the VTable layout.
uint64_t NumVTableComponents = Builder.getNumVTableComponents(); 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. // Store the number of components.
LayoutData[0] = NumVTableComponents; LayoutData[0] = NumVTableComponents;
@ -2990,7 +2996,7 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
CGM.getMangleContext().mangleCXXVTable(RD, OutName); CGM.getMangleContext().mangleCXXVTable(RD, OutName);
llvm::StringRef Name = OutName.str(); llvm::StringRef Name = OutName.str();
ComputeVTableRelatedInformation(RD); ComputeVTableRelatedInformation(RD, true);
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
llvm::ArrayType *ArrayType = llvm::ArrayType *ArrayType =

View File

@ -208,7 +208,11 @@ class CodeGenVTables {
/// Thunks - Contains all thunks that a given method decl will need. /// Thunks - Contains all thunks that a given method decl will need.
ThunksMapTy Thunks; 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. /// VTableLayoutMap - Stores the vtable layout for all record decls.
/// The layout is stored as an array of 64-bit integers, where the first /// 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 { uint64_t getNumVTableComponents(const CXXRecordDecl *RD) const {
assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!"); 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 { const uint64_t *getVTableComponentsData(const CXXRecordDecl *RD) const {
assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!"); 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]; return &Components[1];
} }
@ -275,7 +279,8 @@ class CodeGenVTables {
/// ComputeVTableRelatedInformation - Compute and store all vtable related /// ComputeVTableRelatedInformation - Compute and store all vtable related
/// information (vtable layout, vbase offset offsets, thunks etc) for the /// information (vtable layout, vbase offset offsets, thunks etc) for the
/// given record decl. /// given record decl.
void ComputeVTableRelatedInformation(const CXXRecordDecl *RD); void ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
bool VTableRequired);
/// CreateVTableInitializer - Create a vtable initializer for the given record /// CreateVTableInitializer - Create a vtable initializer for the given record
/// decl. /// decl.

View File

@ -234,6 +234,18 @@ namespace Test8 {
void C::bar(NonPOD var) {} 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 ****/ /**** The following has to go at the end of the file ****/
// This is from Test5: // This is from Test5:

View File

@ -27,6 +27,11 @@ int main() {
// CHECK: call void @_ZN13basic_istreamIcED2Ev // CHECK: call void @_ZN13basic_istreamIcED2Ev
// CHECK: } // 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 // basic_iostream's deleting dtor calls its complete dtor, then
// operator delete(). // operator delete().
// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev // CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev
@ -44,9 +49,3 @@ int main() {
// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED0Ev // CHECK: define linkonce_odr void @_ZN13basic_istreamIcED0Ev
// CHECK: call void @_ZN13basic_istreamIcED1Ev // CHECK: call void @_ZN13basic_istreamIcED1Ev
// CHECK: call void @_ZdlPv // CHECK: call void @_ZdlPv
// basic_istream's base dtor is a no-op.
// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev
// CHECK-NOT: call
// CHECK: }