From: Reid Kleckner Date: Tue, 21 Jun 2016 18:39:55 +0000 (+0000) Subject: [MS] Don't expect vftables to be provided for extern template instantiations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=818861df9ea3353f1d4a8d14d65b118b490b2f47;p=clang [MS] Don't expect vftables to be provided for extern template instantiations MSVC doesn't provide them. PR28223 I left behind the machinery in case we want to resurrect available_externally vftable emission to support devirtualization. Reviewers: majnemer Differential Revision: http://reviews.llvm.org/D21544 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@273296 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp index e43acc4de7..640fbf47ae 100644 --- a/lib/AST/VTableBuilder.cpp +++ b/lib/AST/VTableBuilder.cpp @@ -2545,14 +2545,13 @@ public: MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)), WhichVFPtr(*Which), Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) { - // Only include the RTTI component if we know that we will provide a - // definition of the vftable. We always provide the definition of - // dllimported classes. + // Provide the RTTI component if RTTIData is enabled. If the vftable would + // be available externally, we should not provide the RTTI componenent. It + // is currently impossible to get available externally vftables with either + // dllimport or extern template instantiations, but eventually we may add a + // flag to support additional devirtualization that needs this. if (Context.getLangOpts().RTTIData) - if (MostDerivedClass->hasAttr() || - MostDerivedClass->getTemplateSpecializationKind() != - TSK_ExplicitInstantiationDeclaration) - HasRTTIComponent = true; + HasRTTIComponent = true; LayoutVFTable(); diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 38461446de..da9b742187 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -794,6 +794,10 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { return DiscardableODRLinkage; case TSK_ExplicitInstantiationDeclaration: + // Explicit instantiations in MSVC do not provide vtables, so we must emit + // our own. + if (getTarget().getCXXABI().isMicrosoft()) + return DiscardableODRLinkage; return shouldEmitAvailableExternallyVTable(*this, RD) ? llvm::GlobalVariable::AvailableExternallyLinkage : llvm::GlobalVariable::ExternalLinkage; @@ -839,9 +843,9 @@ CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) { bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) { assert(RD->isDynamicClass() && "Non-dynamic classes have no VTable."); - // We always synthesize vtables on the import side regardless of whether or - // not it is an explicit instantiation declaration. - if (CGM.getTarget().getCXXABI().isMicrosoft() && RD->hasAttr()) + // We always synthesize vtables if they are needed in the MS ABI. MSVC doesn't + // emit them even if there is an explicit template instantiation. + if (CGM.getTarget().getCXXABI().isMicrosoft()) return false; // If we have an explicit instantiation declaration (and not a diff --git a/test/CodeGenCXX/microsoft-abi-vbtables.cpp b/test/CodeGenCXX/microsoft-abi-vbtables.cpp index 9cce6f8698..df06894238 100644 --- a/test/CodeGenCXX/microsoft-abi-vbtables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vbtables.cpp @@ -537,5 +537,5 @@ template struct B : virtual A { extern template class B; template B::B(); -// CHECK-DAG: @"\01??_8?$B@H@Test30@@7B@" = external unnamed_addr constant [2 x i32]{{$}} +// CHECK-DAG: @"\01??_8?$B@H@Test30@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 4], comdat } diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp index d94c9c1a90..0c9b58bbb4 100644 --- a/test/CodeGenCXX/microsoft-abi-vftables.cpp +++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp @@ -33,7 +33,7 @@ struct __declspec(dllexport) V { namespace { struct W { - virtual ~W(); + virtual ~W() {} } w; } // RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4W@?A@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)] @@ -49,5 +49,7 @@ template struct Y : virtual X { extern template class Y; template Y::Y(); -// RTTI-DAG: @"\01??_7?$Y@H@@6B@" = external unnamed_addr constant [1 x i8*] -// NO-RTTI-DAG: @"\01??_7?$Y@H@@6B@" = external unnamed_addr constant [1 x i8*] +// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$Y@H@@6B@" to i8*), i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)], comdat($"\01??_7?$Y@H@@6B@") +// RTTI-DAG: @"\01??_7?$Y@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_Y]], i32 0, i32 1) + +// NO-RTTI-DAG: @"\01??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)], comdat