]> granicus.if.org Git - clang/commitdiff
CodeGen: export typeinfo and typeinfo name on itanium
authorSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 2 Dec 2016 22:46:18 +0000 (22:46 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 2 Dec 2016 22:46:18 +0000 (22:46 +0000)
When a C++ record is marked with dllexport mark both the typeinfo and the
typeinfo name as being exported.  Handle dllimport as the inverse.  This applies
to the itanium environment and not the MinGW environment.

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

lib/CodeGen/ItaniumCXXABI.cpp
test/CodeGenCXX/windows-itanium-type-info.cpp

index 088454647c7cfe945c80a6c7284a5edbfd664a29..48d47d2359919b0102fbe22d9eaf47d9b79c6753 100644 (file)
@@ -2911,16 +2911,18 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
 
   case VisibleNoLinkage:
   case ExternalLinkage:
-    if (!CGM.getLangOpts().RTTI) {
-      // RTTI is not enabled, which means that this type info struct is going
-      // to be used for exception handling. Give it linkonce_odr linkage.
+    // RTTI is not enabled, which means that this type info struct is going
+    // to be used for exception handling. Give it linkonce_odr linkage.
+    if (!CGM.getLangOpts().RTTI)
       return llvm::GlobalValue::LinkOnceODRLinkage;
-    }
 
     if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
       const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
       if (RD->hasAttr<WeakAttr>())
         return llvm::GlobalValue::WeakODRLinkage;
+      if (CGM.getTriple().isWindowsItaniumEnvironment())
+        if (RD->hasAttr<DLLImportAttr>())
+          return llvm::GlobalValue::ExternalLinkage;
       if (RD->isDynamicClass()) {
         llvm::GlobalValue::LinkageTypes LT = CGM.getVTableLinkage(RD);
         // MinGW won't export the RTTI information when there is a key function.
@@ -3122,10 +3124,26 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
     llvmVisibility = llvm::GlobalValue::HiddenVisibility;
   else
     llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
+
   TypeName->setVisibility(llvmVisibility);
   GV->setVisibility(llvmVisibility);
-  if (DLLExport)
-    GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+
+  if (CGM.getTriple().isWindowsItaniumEnvironment()) {
+    auto RD = Ty->getAsCXXRecordDecl();
+    if (DLLExport || (RD && RD->hasAttr<DLLExportAttr>())) {
+      TypeName->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+      GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+    } else if (RD && RD->hasAttr<DLLImportAttr>()) {
+      TypeName->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+      GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+
+      // Because the typename and the typeinfo are DLL import, convert them to
+      // declarations rather than definitions.  The initializers still need to
+      // be constructed to calculate the type for the declarations.
+      TypeName->setInitializer(nullptr);
+      GV->setInitializer(nullptr);
+    }
+  }
 
   return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
 }
index 206e7c3e2f90599eb54618b56c47e863455e2374..ecc227d5b63c4f3a10910c03adf4e244ecde0d89 100644 (file)
@@ -9,5 +9,24 @@ public:
 __fundamental_type_info::~__fundamental_type_info() {}
 }
 
-// CHECK: @_ZTIi = dllexport constant
+struct __declspec(dllimport) base {
+  virtual void method();
+};
+struct __declspec(dllexport) derived : base {
+  virtual ~derived();
+};
+derived::~derived() {
+  method();
+}
+
+// CHECK-DAG: @_ZTIi = dllexport constant
+// CHECK-DAG: @_ZTSi = dllexport constant
+
+// CHECK-DAG: @_ZTI7derived = dllexport constant
+// CHECK-DAG: @_ZTS7derived = dllexport constant
+// CHECK-DAG: @_ZTV7derived = dllexport unnamed_addr constant
+
+// CHECK-DAG: @_ZTI4base = external dllimport constant
+// CHECK-DAG: @_ZTS4base = external dllimport constant
+// CHECK-NOT: @_ZTV4base = external dllimport constant