From d2c47bde3bc0c0debd8a9728781d3375efe22bc5 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Mon, 11 Oct 2010 03:25:57 +0000 Subject: [PATCH] Make sure the VTables for template instantiations are emitted even if the key function doesn't have a body. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116186 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGRTTI.cpp | 16 +++++----------- lib/CodeGen/CGVTables.cpp | 25 ++++++++++++++++++++++--- lib/CodeGen/CGVTables.h | 11 +++-------- test/CodeGenCXX/vtable-linkage.cpp | 15 +++++++++++++++ 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index e98d0e8cea..60c3a5f84b 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -270,8 +270,9 @@ static bool IsStandardLibraryRTTIDescriptor(QualType Ty) { /// the given type exists somewhere else, and that we should not emit the type /// information in this translation unit. Assumes that it is not a /// standard-library type. -static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context, - QualType Ty) { +static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) { + ASTContext &Context = CGM.getContext(); + // If RTTI is disabled, don't consider key functions. if (!Context.getLangOptions().RTTI) return false; @@ -283,13 +284,7 @@ static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context, if (!RD->isDynamicClass()) return false; - // Get the key function. - const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); - if (KeyFunction && !KeyFunction->hasBody()) { - // The class has a key function, but it is not defined in this translation - // unit, so we should use the external descriptor for it. - return true; - } + return !CGM.getVTables().ShouldEmitVTableInThisTU(RD); } return false; @@ -528,8 +523,7 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { // Check if there is already an external RTTI descriptor for this type. bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty); - if (!Force && - (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty))) + if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty))) return GetAddrOfExternalRTTIDescriptor(Ty); // Emit the standard library with external linkage. diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index bed4670f7f..e1ed98cdf5 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -2336,6 +2336,27 @@ void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) { NumVirtualFunctionPointers[RD] = CurrentIndex; } +bool CodeGenVTables::ShouldEmitVTableInThisTU(const CXXRecordDecl *RD) { + assert(RD->isDynamicClass() && "Non dynamic classes have no VTable."); + + TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind(); + if (TSK == TSK_ExplicitInstantiationDeclaration) + return false; + + const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD); + if (!KeyFunction) + return true; + + // Itanium C++ ABI, 5.2.6 Instantiated Templates: + // An instantiation of a class template requires: + // - In the object where instantiated, the virtual table... + if (TSK == TSK_ImplicitInstantiation || + TSK == TSK_ExplicitInstantiationDefinition) + return true; + + return KeyFunction->hasBody(); +} + uint64_t CodeGenVTables::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) { llvm::DenseMap::iterator I = NumVirtualFunctionPointers.find(RD); @@ -2703,9 +2724,7 @@ void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD, // We may need to generate a definition for this vtable. if (RequireVTable && !Entry.getInt()) { - if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) && - RD->getTemplateSpecializationKind() - != TSK_ExplicitInstantiationDeclaration) + if (ShouldEmitVTableInThisTU(RD)) CGM.DeferredVTables.push_back(RD); Entry.setInt(true); diff --git a/lib/CodeGen/CGVTables.h b/lib/CodeGen/CGVTables.h index abcafd6c9c..1d2e8c1e04 100644 --- a/lib/CodeGen/CGVTables.h +++ b/lib/CodeGen/CGVTables.h @@ -295,14 +295,9 @@ public: CodeGenVTables(CodeGenModule &CGM) : CGM(CGM) { } - // isKeyFunctionInAnotherTU - True if this record has a key function and it is - // in another translation unit. - static bool isKeyFunctionInAnotherTU(ASTContext &Context, - const CXXRecordDecl *RD) { - assert (RD->isDynamicClass() && "Non dynamic classes have no key."); - const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); - return KeyFunction && !KeyFunction->hasBody(); - } + /// \brief True if the VTable of this record must be emitted in the + /// translation unit. + bool ShouldEmitVTableInThisTU(const CXXRecordDecl *RD); /// needsVTTParameter - Return whether the given global decl needs a VTT /// parameter, which it does if it's a base constructor or destructor with diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index cf988d1312..265126882a 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -197,3 +197,18 @@ void G::f1() {} template void G::f0() {} void G_f0() { new G(); } + +// RUN: FileCheck --check-prefix=CHECK-H %s < %t + +// H has a key function without a body but it's a template instantiation +// so its VTable must be emmitted. +// CHECK-H: @_ZTV1HIiE = weak_odr constant +template +class H { +public: + virtual ~H(); +}; + +void use_H() { + H h; +} -- 2.40.0