Borrow visibility from __fundamental_type_info for generated fundamental type infos
authorThomas Anderson <thomasanderson@google.com>
Tue, 24 Jul 2018 00:43:47 +0000 (00:43 +0000)
committerThomas Anderson <thomasanderson@google.com>
Tue, 24 Jul 2018 00:43:47 +0000 (00:43 +0000)
This is necessary so the clang gives hidden visibility to fundamental types when
-fvisibility=hidden is passed. Fixes
https://bugs.llvm.org/show_bug.cgi?id=35066

Differential Revision: https://reviews.llvm.org/D49109

llvm-svn: 337788

clang/lib/CodeGen/ItaniumCXXABI.cpp
clang/test/CodeGenCXX/rtti-fundamental.cpp

index d156ffa..16fdd1c 100644 (file)
@@ -31,6 +31,7 @@
 #include "clang/AST/StmtCXX.h"
 #include "llvm/IR/CallSite.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Value.h"
@@ -181,8 +182,7 @@ public:
   emitTerminateForUnexpectedException(CodeGenFunction &CGF,
                                       llvm::Value *Exn) override;
 
-  void EmitFundamentalRTTIDescriptor(QualType Type, bool DLLExport);
-  void EmitFundamentalRTTIDescriptors(bool DLLExport);
+  void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD);
   llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
   CatchTypeInfo
   getAddrOfCXXCatchHandlerType(QualType Ty,
@@ -1613,7 +1613,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
       isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
       cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
       DC->getParent()->isTranslationUnit())
-    EmitFundamentalRTTIDescriptors(RD->hasAttr<DLLExportAttr>());
+    EmitFundamentalRTTIDescriptors(RD);
 
   if (!VTable->isDeclarationForLinker())
     CGM.EmitVTableTypeMetadata(VTable, VTLayout);
@@ -2698,12 +2698,16 @@ public:
     BCTI_Public = 0x2
   };
 
+  /// BuildTypeInfo - Build the RTTI type info struct for the given type, or
+  /// link to an existing RTTI descriptor if one already exists.
+  llvm::Constant *BuildTypeInfo(QualType Ty);
+
   /// BuildTypeInfo - Build the RTTI type info struct for the given type.
-  ///
-  /// \param Force - true to force the creation of this RTTI value
-  /// \param DLLExport - true to mark the RTTI value as DLLExport
-  llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false,
-                                bool DLLExport = false);
+  llvm::Constant *BuildTypeInfo(
+      QualType Ty,
+      llvm::GlobalVariable::LinkageTypes Linkage,
+      llvm::GlobalValue::VisibilityTypes Visibility,
+      llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
 };
 }
 
@@ -3172,8 +3176,7 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
   llvm_unreachable("Invalid linkage!");
 }
 
-llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
-                                                  bool DLLExport) {
+llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
   // We want to operate on the canonical type.
   Ty = Ty.getCanonicalType();
 
@@ -3191,17 +3194,41 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
   }
 
   // Check if there is already an external RTTI descriptor for this type.
-  bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
-  if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))
+  if (IsStandardLibraryRTTIDescriptor(Ty) ||
+      ShouldUseExternalRTTIDescriptor(CGM, Ty))
     return GetAddrOfExternalRTTIDescriptor(Ty);
 
   // Emit the standard library with external linkage.
-  llvm::GlobalVariable::LinkageTypes Linkage;
-  if (IsStdLib)
-    Linkage = llvm::GlobalValue::ExternalLinkage;
+  llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);
+
+  // Give the type_info object and name the formal visibility of the
+  // type itself.
+  llvm::GlobalValue::VisibilityTypes llvmVisibility;
+  if (llvm::GlobalValue::isLocalLinkage(Linkage))
+    // If the linkage is local, only default visibility makes sense.
+    llvmVisibility = llvm::GlobalValue::DefaultVisibility;
+  else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) ==
+           ItaniumCXXABI::RUK_NonUniqueHidden)
+    llvmVisibility = llvm::GlobalValue::HiddenVisibility;
   else
-    Linkage = getTypeInfoLinkage(CGM, Ty);
+    llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
+
+  llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
+      llvm::GlobalValue::DefaultStorageClass;
+  if (CGM.getTriple().isWindowsItaniumEnvironment()) {
+    auto RD = Ty->getAsCXXRecordDecl();
+    if (RD && RD->hasAttr<DLLExportAttr>())
+      DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
+  }
 
+  return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass);
+}
+
+llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
+      QualType Ty,
+      llvm::GlobalVariable::LinkageTypes Linkage,
+      llvm::GlobalValue::VisibilityTypes Visibility,
+      llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
   // Add the vtable pointer.
   BuildVTablePointer(cast<Type>(Ty));
 
@@ -3315,7 +3342,11 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
 
   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
 
+  SmallString<256> Name;
+  llvm::raw_svector_ostream Out(Name);
+  CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
   llvm::Module &M = CGM.getModule();
+  llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
   llvm::GlobalVariable *GV =
       new llvm::GlobalVariable(M, Init->getType(),
                                /*Constant=*/true, Linkage, Init, Name);
@@ -3347,40 +3378,14 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
   // All of this is to say that it's important that both the type_info
   // object and the type_info name be uniqued when weakly emitted.
 
-  // Give the type_info object and name the formal visibility of the
-  // type itself.
-  llvm::GlobalValue::VisibilityTypes llvmVisibility;
-  if (llvm::GlobalValue::isLocalLinkage(Linkage))
-    // If the linkage is local, only default visibility makes sense.
-    llvmVisibility = llvm::GlobalValue::DefaultVisibility;
-  else if (RTTIUniqueness == ItaniumCXXABI::RUK_NonUniqueHidden)
-    llvmVisibility = llvm::GlobalValue::HiddenVisibility;
-  else
-    llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
-
-  TypeName->setVisibility(llvmVisibility);
+  TypeName->setVisibility(Visibility);
   CGM.setDSOLocal(TypeName);
 
-  GV->setVisibility(llvmVisibility);
+  GV->setVisibility(Visibility);
   CGM.setDSOLocal(GV);
 
-  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>() &&
-               ShouldUseExternalRTTIDescriptor(CGM, Ty)) {
-      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);
-    }
-  }
+  TypeName->setDLLStorageClass(DLLStorageClass);
+  GV->setDLLStorageClass(DLLStorageClass);
 
   return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
 }
@@ -3655,18 +3660,7 @@ llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
   return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
 }
 
-void ItaniumCXXABI::EmitFundamentalRTTIDescriptor(QualType Type,
-                                                  bool DLLExport) {
-  QualType PointerType = getContext().getPointerType(Type);
-  QualType PointerTypeConst = getContext().getPointerType(Type.withConst());
-  ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, /*Force=*/true, DLLExport);
-  ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, /*Force=*/true,
-                                          DLLExport);
-  ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, /*Force=*/true,
-                                          DLLExport);
-}
-
-void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(bool DLLExport) {
+void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
   // Types added here must also be added to TypeInfoIsInStandardLibrary.
   QualType FundamentalTypes[] = {
       getContext().VoidTy,             getContext().NullPtrTy,
@@ -3683,8 +3677,21 @@ void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(bool DLLExport) {
       getContext().Char8Ty,            getContext().Char16Ty,
       getContext().Char32Ty
   };
-  for (const QualType &FundamentalType : FundamentalTypes)
-    EmitFundamentalRTTIDescriptor(FundamentalType, DLLExport);
+  llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
+      RD->hasAttr<DLLExportAttr>()
+      ? llvm::GlobalValue::DLLExportStorageClass
+      : llvm::GlobalValue::DefaultStorageClass;
+  llvm::GlobalValue::VisibilityTypes Visibility =
+      CodeGenModule::GetLLVMVisibility(RD->getVisibility());
+  for (const QualType &FundamentalType : FundamentalTypes) {
+    QualType PointerType = getContext().getPointerType(FundamentalType);
+    QualType PointerTypeConst = getContext().getPointerType(
+        FundamentalType.withConst());
+    for (QualType Type : {FundamentalType, PointerType, PointerTypeConst})
+      ItaniumRTTIBuilder(*this).BuildTypeInfo(
+          Type, llvm::GlobalValue::ExternalLinkage,
+          Visibility, DLLStorageClass);
+  }
 }
 
 /// What sort of uniqueness rules should we use for the RTTI for the
index a0ad80d..d0e5890 100644 (file)
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -fvisibility hidden -o - | FileCheck %s -check-prefix=CHECK-HIDDEN
 
 #include <typeinfo>
 
@@ -16,116 +17,184 @@ namespace __cxxabiv1 {
 
 // void
 // CHECK: @_ZTIv = constant
+// CHECK-HIDDEN: @_ZTIv = hidden constant
 // CHECK: @_ZTIPv = constant
+// CHECK-HIDDEN: @_ZTIPv = hidden constant
 // CHECK: @_ZTIPKv = constant
+// CHECK-HIDDEN: @_ZTIPKv = hidden constant
 
 // std::nullptr_t
 // CHECK: @_ZTIDn = constant
+// CHECK-HIDDEN: @_ZTIDn = hidden constant
 // CHECK: @_ZTIPDn = constant
+// CHECK-HIDDEN: @_ZTIPDn = hidden constant
 // CHECK: @_ZTIPKDn = constant
+// CHECK-HIDDEN: @_ZTIPKDn = hidden constant
 
 // bool
 // CHECK: @_ZTIb = constant
+// CHECK-HIDDEN: @_ZTIb = hidden constant
 // CHECK: @_ZTIPb = constant
+// CHECK-HIDDEN: @_ZTIPb = hidden constant
 // CHECK: @_ZTIPKb = constant
+// CHECK-HIDDEN: @_ZTIPKb = hidden constant
 
 // wchar_t
 // CHECK: @_ZTIw = constant
+// CHECK-HIDDEN: @_ZTIw = hidden constant
 // CHECK: @_ZTIPw = constant
+// CHECK-HIDDEN: @_ZTIPw = hidden constant
 // CHECK: @_ZTIPKw = constant
+// CHECK-HIDDEN: @_ZTIPKw = hidden constant
 
 // char
 // CHECK: @_ZTIc = constant
+// CHECK-HIDDEN: @_ZTIc = hidden constant
 // CHECK: @_ZTIPc = constant
+// CHECK-HIDDEN: @_ZTIPc = hidden constant
 // CHECK: @_ZTIPKc = constant
+// CHECK-HIDDEN: @_ZTIPKc = hidden constant
 
 // unsigned char
 // CHECK: @_ZTIh = constant
+// CHECK-HIDDEN: @_ZTIh = hidden constant
 // CHECK: @_ZTIPh = constant
+// CHECK-HIDDEN: @_ZTIPh = hidden constant
 // CHECK: @_ZTIPKh = constant
+// CHECK-HIDDEN: @_ZTIPKh = hidden constant
 
 // signed char
 // CHECK: @_ZTIa = constant
+// CHECK-HIDDEN: @_ZTIa = hidden constant
 // CHECK: @_ZTIPa = constant
+// CHECK-HIDDEN: @_ZTIPa = hidden constant
 // CHECK: @_ZTIPKa = constant
+// CHECK-HIDDEN: @_ZTIPKa = hidden constant
 
 // short
 // CHECK: @_ZTIs = constant
+// CHECK-HIDDEN: @_ZTIs = hidden constant
 // CHECK: @_ZTIPs = constant
+// CHECK-HIDDEN: @_ZTIPs = hidden constant
 // CHECK: @_ZTIPKs = constant
+// CHECK-HIDDEN: @_ZTIPKs = hidden constant
 
 // unsigned short
 // CHECK: @_ZTIt = constant
+// CHECK-HIDDEN: @_ZTIt = hidden constant
 // CHECK: @_ZTIPt = constant
+// CHECK-HIDDEN: @_ZTIPt = hidden constant
 // CHECK: @_ZTIPKt = constant
+// CHECK-HIDDEN: @_ZTIPKt = hidden constant
 
 // int
 // CHECK: @_ZTIi = constant
+// CHECK-HIDDEN: @_ZTIi = hidden constant
 // CHECK: @_ZTIPi = constant
+// CHECK-HIDDEN: @_ZTIPi = hidden constant
 // CHECK: @_ZTIPKi = constant
+// CHECK-HIDDEN: @_ZTIPKi = hidden constant
 
 // unsigned int
 // CHECK: @_ZTIj = constant
+// CHECK-HIDDEN: @_ZTIj = hidden constant
 // CHECK: @_ZTIPj = constant
+// CHECK-HIDDEN: @_ZTIPj = hidden constant
 // CHECK: @_ZTIPKj = constant
+// CHECK-HIDDEN: @_ZTIPKj = hidden constant
 
 // long
 // CHECK: @_ZTIl = constant
+// CHECK-HIDDEN: @_ZTIl = hidden constant
 // CHECK: @_ZTIPl = constant
+// CHECK-HIDDEN: @_ZTIPl = hidden constant
 // CHECK: @_ZTIPKl = constant
+// CHECK-HIDDEN: @_ZTIPKl = hidden constant
 
 // unsigned long
 // CHECK: @_ZTIm = constant
+// CHECK-HIDDEN: @_ZTIm = hidden constant
 // CHECK: @_ZTIPm = constant
+// CHECK-HIDDEN: @_ZTIPm = hidden constant
 // CHECK: @_ZTIPKm = constant
+// CHECK-HIDDEN: @_ZTIPKm = hidden constant
 
 // long long
 // CHECK: @_ZTIx = constant
+// CHECK-HIDDEN: @_ZTIx = hidden constant
 // CHECK: @_ZTIPx = constant
+// CHECK-HIDDEN: @_ZTIPx = hidden constant
 // CHECK: @_ZTIPKx = constant
+// CHECK-HIDDEN: @_ZTIPKx = hidden constant
 
 // unsigned long long
 // CHECK: @_ZTIy = constant
+// CHECK-HIDDEN: @_ZTIy = hidden constant
 // CHECK: @_ZTIPy = constant
+// CHECK-HIDDEN: @_ZTIPy = hidden constant
 // CHECK: @_ZTIPKy = constant
+// CHECK-HIDDEN: @_ZTIPKy = hidden constant
 
 // __int128
 // CHECK: @_ZTIn = constant
+// CHECK-HIDDEN: @_ZTIn = hidden constant
 // CHECK: @_ZTIPn = constant
+// CHECK-HIDDEN: @_ZTIPn = hidden constant
 // CHECK: @_ZTIPKn = constant
+// CHECK-HIDDEN: @_ZTIPKn = hidden constant
 
 // unsigned __int128
 // CHECK: @_ZTIo = constant
+// CHECK-HIDDEN: @_ZTIo = hidden constant
 // CHECK: @_ZTIPo = constant
+// CHECK-HIDDEN: @_ZTIPo = hidden constant
 // CHECK: @_ZTIPKo = constant
+// CHECK-HIDDEN: @_ZTIPKo = hidden constant
 
 // half
 // CHECK: @_ZTIDh = constant
+// CHECK-HIDDEN: @_ZTIDh = hidden constant
 // CHECK: @_ZTIPDh = constant
+// CHECK-HIDDEN: @_ZTIPDh = hidden constant
 // CHECK: @_ZTIPKDh = constant
+// CHECK-HIDDEN: @_ZTIPKDh = hidden constant
 
 // float
 // CHECK: @_ZTIf = constant
+// CHECK-HIDDEN: @_ZTIf = hidden constant
 // CHECK: @_ZTIPf = constant
+// CHECK-HIDDEN: @_ZTIPf = hidden constant
 // CHECK: @_ZTIPKf = constant
+// CHECK-HIDDEN: @_ZTIPKf = hidden constant
 
 // double
 // CHECK: @_ZTId = constant
+// CHECK-HIDDEN: @_ZTId = hidden constant
 // CHECK: @_ZTIPd = constant
+// CHECK-HIDDEN: @_ZTIPd = hidden constant
 // CHECK: @_ZTIPKd = constant
+// CHECK-HIDDEN: @_ZTIPKd = hidden constant
 
 // long double
 // CHECK: @_ZTIe = constant
+// CHECK-HIDDEN: @_ZTIe = hidden constant
 // CHECK: @_ZTIPe = constant
+// CHECK-HIDDEN: @_ZTIPe = hidden constant
 // CHECK: @_ZTIPKe = constant
+// CHECK-HIDDEN: @_ZTIPKe = hidden constant
 
 // char16_t
 // CHECK: @_ZTIDs = constant
+// CHECK-HIDDEN: @_ZTIDs = hidden constant
 // CHECK: @_ZTIPDs = constant
+// CHECK-HIDDEN: @_ZTIPDs = hidden constant
 // CHECK: @_ZTIPKDs = constant
+// CHECK-HIDDEN: @_ZTIPKDs = hidden constant
 
 // char32_t
 // CHECK: @_ZTIDi = constant
+// CHECK-HIDDEN: @_ZTIDi = hidden constant
 // CHECK: @_ZTIPDi = constant
+// CHECK-HIDDEN: @_ZTIPDi = hidden constant
 // CHECK: @_ZTIPKDi = constant
-
+// CHECK-HIDDEN: @_ZTIPKDi = hidden constant