]> granicus.if.org Git - clang/commitdiff
MS ABI: Get linkage of RTTI data correct
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 3 Jul 2014 05:51:27 +0000 (05:51 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 3 Jul 2014 05:51:27 +0000 (05:51 +0000)
The Itanium rules are not appropriate for the MS ABI.  RTTI data is
_never_ imported and thus is never available_externally.  It is either
internal (if the type's linkage is internal) or linkonce_odr.

This also means that classes which inherit from dllimport'd bases force
their translation unit to duplicate the entirety of the RTTI data of
that base.

Interestingly, the complete object locator can never be referenced by
translation units which import the class.

This fixes PR20106.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@212256 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/MicrosoftRTTI.cpp
test/CodeGenCXX/dllimport-rtti.cpp [new file with mode: 0644]

index 776a1612623b65627459ea75d029f9b2434e89b8..f539bfba4a0f5a16aef4c69f8d021eb5b1cead8e 100644 (file)
@@ -230,6 +230,20 @@ uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent,
   return NumBases;
 }
 
+static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) {
+  switch (Ty->getLinkage()) {
+  case NoLinkage:
+  case InternalLinkage:
+  case UniqueExternalLinkage:
+    return llvm::GlobalValue::InternalLinkage;
+
+  case VisibleNoLinkage:
+  case ExternalLinkage:
+    return llvm::GlobalValue::LinkOnceODRLinkage;
+  }
+  llvm_unreachable("Invalid linkage!");
+}
+
 /// \brief An ephemeral helper class for building MS RTTI types.  It caches some
 /// calls to the module and information about the most derived class in a
 /// hierarchy.
@@ -242,7 +256,8 @@ struct MSRTTIBuilder {
 
   MSRTTIBuilder(CodeGenModule &CGM, const CXXRecordDecl *RD)
       : CGM(CGM), Context(CGM.getContext()), VMContext(CGM.getLLVMContext()),
-        Module(CGM.getModule()), RD(RD), Linkage(CGM.getVTableLinkage(RD)),
+        Module(CGM.getModule()), RD(RD),
+        Linkage(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))),
         Mangler(
             cast<MicrosoftMangleContext>(CGM.getCXXABI().getMangleContext())) {}
 
@@ -499,7 +514,7 @@ llvm::Constant *CodeGenModule::getMSTypeDescriptor(QualType Type) {
   return llvm::ConstantExpr::getBitCast(
       new llvm::GlobalVariable(
           getModule(), TypeDescriptorType, /*Constant=*/false,
-          getTypeInfoLinkage(Type),
+          getLinkageForRTTI(Type),
           llvm::ConstantStruct::get(TypeDescriptorType, Fields),
           MangledName.c_str()),
       Int8PtrTy);
diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp
new file mode 100644 (file)
index 0000000..7ed7dad
--- /dev/null
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s | FileCheck %s
+
+struct __declspec(dllimport) S {
+  virtual void f();
+} s;
+// CHECK-DAG: @"\01??_7S@@6B@" = available_externally dllimport
+// CHECK-DAG: @"\01??_R0?AUS@@@8" = linkonce_odr
+// CHECK-DAG: @"\01??_R1A@?0A@EA@S@@8" = linkonce_odr
+// CHECK-DAG: @"\01??_R2S@@8" = linkonce_odr
+// CHECK-DAG: @"\01??_R3S@@8" = linkonce_odr
+
+struct U : S {
+} u;