forked from OSchip/llvm-project
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:
parent
f2dffcef82
commit
6a7f9f5c8f
|
@ -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 =
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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: }
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue