summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2016-02-10 17:40:47 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2016-02-10 17:40:47 +0000
commitf813c829dd9e628b456e9df9826bba69f7224a92 (patch)
tree28c2f40f6c164563b24eb33fa1379e9ab6c2f731
parent222af3db18686a08f455b6a5132de5a98d0273f4 (diff)
downloadclang-f813c829dd9e628b456e9df9826bba69f7224a92.tar.gz
[MS ABI] Never reference dllimport'd vtables
Referencing a dllimported vtable is impossible in a constexpr constructor. It would be friendlier to C++ programmers if we synthesized a copy of the vftable which referenced imported virtual functions. This would let us initialize the object in a way which preserves both the intent to import functionality from another DLL while also making constexpr work. Differential Revision: http://reviews.llvm.org/D17061 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@260388 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/MicrosoftMangle.cpp5
-rw-r--r--lib/AST/VTableBuilder.cpp1
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp15
-rw-r--r--test/CodeGenCXX/dllimport-rtti.cpp3
-rw-r--r--test/CodeGenCXX/dllimport.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-vftables.cpp7
6 files changed, 21 insertions, 12 deletions
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 0634319cbd..930cf00d9e 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/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/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index bae018652f..b728b27918 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -2548,7 +2548,6 @@ public:
// 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;
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 0664381b44..f47b120a90 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/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/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp
index 071ce278a5..4baee50fcf 100644
--- a/test/CodeGenCXX/dllimport-rtti.cpp
+++ b/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/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp
index b9c850b8b8..e336bfb692 100644
--- a/test/CodeGenCXX/dllimport.cpp
+++ b/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/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp
index f32bff09a8..d94c9c1a90 100644
--- a/test/CodeGenCXX/microsoft-abi-vftables.cpp
+++ b/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();