diff options
-rw-r--r-- | clang/lib/AST/MicrosoftMangle.cpp | 5 | ||||
-rw-r--r-- | clang/lib/AST/VTableBuilder.cpp | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 15 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/PR26569.cpp | 17 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/dllimport-rtti.cpp | 3 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/dllimport.cpp | 2 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-vftables.cpp | 7 |
8 files changed, 51 insertions, 17 deletions
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 0634319cbd1..930cf00d9e3 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2599,7 +2599,10 @@ void MicrosoftMangleContextImpl::mangleCXXVFTable( // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class> // is always '6' for vftables. MicrosoftCXXNameMangler Mangler(*this, Out); - Mangler.getStream() << "\01??_7"; + if (Derived->hasAttr<DLLImportAttr>()) + Mangler.getStream() << "\01??_S"; + else + Mangler.getStream() << "\01??_7"; Mangler.mangleName(Derived); Mangler.getStream() << "6B"; // '6' for vftable, 'B' for const. for (const CXXRecordDecl *RD : BasePath) diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index bae018652f9..e43acc4de78 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -2416,7 +2416,7 @@ private: MethodVFTableLocationsTy MethodVFTableLocations; /// \brief Does this class have an RTTI component? - bool HasRTTIComponent; + bool HasRTTIComponent = false; /// MethodInfo - Contains information about a method in a vtable. /// (Used for computing 'this' pointer adjustment thunks. @@ -2546,11 +2546,13 @@ public: WhichVFPtr(*Which), Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) { // Only include the RTTI component if we know that we will provide a - // definition of the vftable. - HasRTTIComponent = Context.getLangOpts().RTTIData && - !MostDerivedClass->hasAttr<DLLImportAttr>() && - MostDerivedClass->getTemplateSpecializationKind() != - TSK_ExplicitInstantiationDeclaration; + // definition of the vftable. We always provide the definition of + // dllimported classes. + if (Context.getLangOpts().RTTIData) + if (MostDerivedClass->hasAttr<DLLImportAttr>() || + MostDerivedClass->getTemplateSpecializationKind() != + TSK_ExplicitInstantiationDeclaration) + HasRTTIComponent = true; LayoutVFTable(); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 620e9223b2e..e96a8120207 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -838,6 +838,11 @@ 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<DLLImportAttr>()) + return false; + // If we have an explicit instantiation declaration (and not a // definition), the vtable is defined elsewhere. TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind(); diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 2870a91dd5f..2567aa92f25 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1673,7 +1673,16 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, SmallString<256> VFTableName; mangleVFTableName(getMangleContext(), RD, VFPtr, VFTableName); - llvm::GlobalValue::LinkageTypes VFTableLinkage = CGM.getVTableLinkage(RD); + // Classes marked __declspec(dllimport) need vftables generated on the + // import-side in order to support features like constexpr. No other + // translation unit relies on the emission of the local vftable, translation + // units are expected to generate them as needed. + // + // Because of this unique behavior, we maintain this logic here instead of + // getVTableLinkage. + llvm::GlobalValue::LinkageTypes VFTableLinkage = + RD->hasAttr<DLLImportAttr>() ? llvm::GlobalValue::LinkOnceODRLinkage + : CGM.getVTableLinkage(RD); bool VFTableComesFromAnotherTU = llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) || llvm::GlobalValue::isExternalLinkage(VFTableLinkage); @@ -1746,9 +1755,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, if (C) VTable->setComdat(C); - if (RD->hasAttr<DLLImportAttr>()) - VFTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - else if (RD->hasAttr<DLLExportAttr>()) + if (RD->hasAttr<DLLExportAttr>()) VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); VFTablesMap[ID] = VFTable; diff --git a/clang/test/CodeGenCXX/PR26569.cpp b/clang/test/CodeGenCXX/PR26569.cpp new file mode 100644 index 00000000000..666a6466aa4 --- /dev/null +++ b/clang/test/CodeGenCXX/PR26569.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-llvm -O1 -disable-llvm-optzns %s -o - | FileCheck %s + +class A { + virtual void m_fn1(); +}; +template <typename> +class B : A {}; + +extern template class __declspec(dllimport) B<int>; +class __declspec(dllexport) C : B<int> {}; + +// CHECK: @[[VTABLE_C:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4C@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)] +// CHECK: @[[VTABLE_B:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4?$B@H@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_S?$B@H@@6B@") +// CHECK: @[[VTABLE_A:.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_7A@@6B@") +// CHECK: @"\01??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_C]], i32 0, i32 1) +// CHECK: @"\01??_S?$B@H@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_B]], i32 0, i32 1) +// CHECK: @"\01??_7A@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_A]], i32 0, i32 1) diff --git a/clang/test/CodeGenCXX/dllimport-rtti.cpp b/clang/test/CodeGenCXX/dllimport-rtti.cpp index 071ce278a5b..4baee50fcff 100644 --- a/clang/test/CodeGenCXX/dllimport-rtti.cpp +++ b/clang/test/CodeGenCXX/dllimport-rtti.cpp @@ -4,7 +4,8 @@ struct __declspec(dllimport) S { virtual void f() {} } s; -// MSVC-DAG: @"\01??_7S@@6B@" = available_externally dllimport +// MSVC: [[VF_S:.*]] = private unnamed_addr constant [2 x i8*] +// MSVC-DAG: @"\01??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VF_S]], i32 0, i32 1) // MSVC-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr // MSVC-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr // MSVC-DAG: @"\01??_R2S@@8" = linkonce_odr diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp index b9c850b8b87..e336bfb6924 100644 --- a/clang/test/CodeGenCXX/dllimport.cpp +++ b/clang/test/CodeGenCXX/dllimport.cpp @@ -614,7 +614,7 @@ USEMEMFUNC(V, foo) struct __declspec(dllimport) W { virtual void foo() {} }; USECLASS(W) // vftable: -// MO1-DAG: @"\01??_7W@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] +// MO1-DAG: @"\01??_SW@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)] // GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)] struct __declspec(dllimport) KeyFuncClass { diff --git a/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp b/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp index f32bff09a8a..d94c9c1a909 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp @@ -4,8 +4,6 @@ // RTTI-DAG: $"\01??_7S@@6B@" = comdat largest // RTTI-DAG: $"\01??_7V@@6B@" = comdat largest -// RTTI-NOT: @"\01??_R4U@@6B@" - struct S { virtual ~S(); } s; @@ -19,9 +17,10 @@ struct __declspec(dllimport) U { virtual ~U(); } u; -// RTTI-DAG: @"\01??_7U@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] +// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant [2 x i8*] [i8* bitcast ({{.*}} @"\01??_R4U@@6B@" to i8*), i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] +// RTTI-DAG: @"\01??_SU@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* [[VTABLE_U]], i32 0, i32 1) -// NO-RTTI-DAG: @"\01??_7U@@6B@" = available_externally dllimport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] +// NO-RTTI-DAG: @"\01??_SU@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)] struct __declspec(dllexport) V { virtual ~V(); |