Emit standard-library RTTI with external linkage, not weak_odr.

Apply hidden visibility to most RTTI;  libstdc++ does not rely on exact
pointer equality for the type info (just the type info names).  Apply
the same optimization to RTTI that we do to vtables.

Fixes PR5962.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110192 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
index 1cca977..0724fdf 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -244,11 +244,9 @@
   return TypeInfoIsInStandardLibrary(BuiltinTy);
 }
 
-/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
-/// the given type exists somewhere else, and that we should not emit the type
-/// information in this translation unit.
-static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context,
-                                            QualType Ty) {
+/// IsStandardLibraryRTTIDescriptor - Returns whether the type
+/// information for the given type exists in the standard library.
+static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
   // Type info for builtin types is defined in the standard library.
   if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
     return TypeInfoIsInStandardLibrary(BuiltinTy);
@@ -258,6 +256,15 @@
   if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
     return TypeInfoIsInStandardLibrary(PointerTy);
 
+  return false;
+}
+
+/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
+/// the given type exists somewhere else, and that we should not emit the type
+/// information in this translation unit.  Assumes that it is not a
+/// standard-library type.
+static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context,
+                                            QualType Ty) {
   // If RTTI is disabled, don't consider key functions.
   if (!Context.getLangOptions().RTTI) return false;
 
@@ -456,8 +463,7 @@
   Fields.push_back(VTable);
 }
 
-llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty,
-                                           bool Force) {
+llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
   // We want to operate on the canonical type.
   Ty = CGM.getContext().getCanonicalType(Ty);
 
@@ -469,19 +475,26 @@
   llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
   if (OldGV && !OldGV->isDeclaration())
     return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy);
-  
+
   // Check if there is already an external RTTI descriptor for this type.
-  if (!Force && ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty))
+  bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
+  if (!Force &&
+      (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty)))
     return GetAddrOfExternalRTTIDescriptor(Ty);
 
-  llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(Ty);
+  // Emit the standard library with external linkage.
+  llvm::GlobalVariable::LinkageTypes Linkage;
+  if (IsStdLib)
+    Linkage = llvm::GlobalValue::ExternalLinkage;
+  else
+    Linkage = getTypeInfoLinkage(Ty);
 
   // Add the vtable pointer.
   BuildVTablePointer(cast<Type>(Ty));
   
   // And the name.
   Fields.push_back(BuildName(Ty, DecideHidden(Ty), Linkage));
-  
+
   switch (Ty->getTypeClass()) {
   default: assert(false && "Unhandled type class!");
 
@@ -551,7 +564,15 @@
     OldGV->replaceAllUsesWith(NewPtr);
     OldGV->eraseFromParent();
   }
-    
+
+  // GCC only relies on the uniqueness of the type names, not the
+  // type_infos themselves, so we can emit these as hidden symbols.
+  if (const RecordType *RT = dyn_cast<RecordType>(Ty))
+    CGM.setTypeVisibility(GV, cast<CXXRecordDecl>(RT->getDecl()),
+                          /*ForRTTI*/ true);
+  else if (Linkage == llvm::GlobalValue::WeakODRLinkage)
+    GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+  
   return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
 }