RTTI symbols for visible local types may need weak linkage.

Previously, we would always emit them with internal linkage,
but with hidden visibility when the function was hidden, which
is an illegal combination, which could lead LLVM to actually
emit them as strong hidden symbols with hilarious results.

rdar://16265084

llvm-svn: 203503
diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp
index 455ee97..8851209 100644
--- a/clang/lib/CodeGen/CGRTTI.cpp
+++ b/clang/lib/CodeGen/CGRTTI.cpp
@@ -332,11 +332,11 @@
   
   switch (Ty->getLinkage()) {
   case NoLinkage:
-  case VisibleNoLinkage:
   case InternalLinkage:
   case UniqueExternalLinkage:
     return llvm::GlobalValue::InternalLinkage;
 
+  case VisibleNoLinkage:
   case ExternalLinkage:
     if (!CGM.getLangOpts().RTTI) {
       // RTTI is not enabled, which means that this type info struct is going
diff --git a/clang/test/CodeGenCXX/rtti-linkage.cpp b/clang/test/CodeGenCXX/rtti-linkage.cpp
index 3eaf133..1484b99 100644
--- a/clang/test/CodeGenCXX/rtti-linkage.cpp
+++ b/clang/test/CodeGenCXX/rtti-linkage.cpp
@@ -8,6 +8,14 @@
 // CHECK-WITH-HIDDEN: @_ZTS2T4 = linkonce_odr hidden constant 
 // CHECK-WITH-HIDDEN: @_ZTI2T4 = linkonce_odr hidden constant 
 // CHECK-WITH-HIDDEN: @_ZTIPK2T4 = linkonce_odr hidden constant 
+// CHECK-WITH-HIDDEN: @_ZTSZ2t5vE1A = internal constant
+// CHECK-WITH-HIDDEN: @_ZTIZ2t5vE1A = internal constant
+// CHECK-WITH-HIDDEN: @_ZTSPZ2t7vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTSZ2t7vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTIZ2t7vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTIPZ2t7vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTSZ2t6vE1A = linkonce_odr hidden constant
+// CHECK-WITH-HIDDEN: @_ZTIZ2t6vE1A = linkonce_odr hidden constant
 
 // CHECK: _ZTSP1C = internal constant
 // CHECK: _ZTS1C = internal constant
@@ -48,9 +56,17 @@
 // CHECK: _ZTI1TILj0EE = linkonce_odr constant
 // CHECK: _ZTI1TILj1EE = weak_odr constant
 // CHECK: _ZTI1TILj2EE = external constant
+// CHECK: _ZTSZ2t5vE1A = internal constant
+// CHECK: _ZTIZ2t5vE1A = internal constant
 // CHECK: _ZTS1B = constant
 // CHECK: _ZTI1B = constant
 // CHECK: _ZTS1F = linkonce_odr constant
+// CHECK: _ZTSPZ2t7vE1A = linkonce_odr constant
+// CHECK: _ZTSZ2t7vE1A = linkonce_odr constant
+// CHECK: _ZTIZ2t7vE1A = linkonce_odr constant
+// CHECK: _ZTIPZ2t7vE1A = linkonce_odr constant
+// CHECK: _ZTSZ2t6vE1A = linkonce_odr constant
+// CHECK: _ZTIZ2t6vE1A = linkonce_odr constant
 
 // CHECK: _ZTIN12_GLOBAL__N_11DE to
 
@@ -138,3 +154,25 @@
 void t4(const T4 *ptr) {
   const void *value = &typeid(ptr);
 }
+
+// rdar://16265084
+void t5() {
+  struct A {};
+  const void *value = &typeid(A);
+}
+
+inline void t6() {
+  struct A {};
+  const void *value = &typeid(A);
+}
+void t6_helper() {
+  t6();
+}
+
+inline void t7() {
+  struct A {};
+  const void *value = &typeid(A*);
+}
+void t7_helper() {
+  t7();
+}