]> granicus.if.org Git - clang/commitdiff
Emit weak vtables of non-template classes with hidden visibility.
authorJohn McCall <rjmccall@apple.com>
Tue, 3 Aug 2010 07:24:12 +0000 (07:24 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 3 Aug 2010 07:24:12 +0000 (07:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110107 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVTables.cpp
test/CodeGenCXX/key-function-vtable.cpp
test/CodeGenCXX/virt-template-vtable.cpp
test/CodeGenCXX/vtable-key-function.cpp
test/CodeGenCXX/vtable-linkage.cpp

index f597a1338cd8b3367c6053f55dce02f379ccb17c..052a6fdca3689d153968e4ac4450ee71b4536eb8 100644 (file)
@@ -2926,6 +2926,22 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
   
   // Set the right visibility.
   CGM.setGlobalVisibility(VTable, RD);
+
+  // It's okay to have multiple copies of a vtable, so don't make the
+  // dynamic linker unique them.  Suppress this optimization if it's
+  // possible that there might be unresolved references elsewhere,
+  // which can happen if
+  //   - there's a key function and the vtable is getting emitted weak
+  //     anyway for whatever reason
+  //   - there might be an explicit instantiation declaration somewhere,
+  //     i.e. if it's a template at all
+  if (Linkage == llvm::GlobalVariable::WeakODRLinkage &&
+      VTable->getVisibility() == llvm::GlobalVariable::DefaultVisibility &&
+      !RD->hasAttr<VisibilityAttr>() &&
+      RD->getTemplateSpecializationKind() == TSK_Undeclared &&
+      !CGM.Context.getKeyFunction(RD)) {
+    VTable->setVisibility(llvm::GlobalVariable::HiddenVisibility);
+  }
 }
 
 llvm::GlobalVariable *
index 1cfeb0c5022d0d9c813325acd9d7da170f99b3d4..e71fba692f8e5eae9805ef2db4d3c64ac7d31c84 100644 (file)
@@ -12,11 +12,11 @@ testb *testbvar = new testb;
 struct testc { virtual void a(); };
 inline void testc::a() {}
 
-// Key functions with inline specifier (PR5705)
+// Functions with inline specifier are not key functions (PR5705)
 struct testd { inline virtual void a(); };
 void testd::a() {}
 
-// Key functions with inline specifier (PR5705)
+// Functions with inline specifier are not key functions (PR5705)
 struct teste { inline virtual void a(); };
 teste *testevar = new teste;
 
@@ -47,5 +47,5 @@ void use_X1(X1 *x1) { x1->f(); }
 // CHECK: @_ZTV5testa = constant [3 x i8*] [i8* null
 // CHECK: @_ZTV5testc = weak_odr constant [3 x i8*] [i8* null
 // CHECK: @_ZTVN12_GLOBAL__N_15testgE = internal constant [3 x i8*] [i8* null
-// CHECK: @_ZTV5teste = weak_odr constant [3 x i8*] [i8* null
-// CHECK: @_ZTV5testb = weak_odr constant [3 x i8*] [i8* null
+// CHECK: @_ZTV5teste = weak_odr hidden constant [3 x i8*] [i8* null
+// CHECK: @_ZTV5testb = weak_odr hidden constant [3 x i8*] [i8* null
index b968f38c826364ac5456a7f9398b4a7db7f4e6de..b9558283127605d5195c59271bc4a98dcc1d01f3 100644 (file)
@@ -10,4 +10,13 @@ class B : A<int> {
 };
 B::B() {}
 
+template class A<long>;
+
+extern template class A<short>;
+template class A<short>;
+
+
+// CHECK: @_ZTV1B = weak_odr hidden constant
+// CHECK: @_ZTV1AIlE = weak_odr constant
+// CHECK: @_ZTV1AIsE = weak_odr constant
 // CHECK: @_ZTV1AIiE = weak_odr constant
index 97a546f8c932c6c464fc6ca0972f99e82e54e7cd..bdcab230c6f032c7788626917df4e7bb3c49f872 100644 (file)
@@ -9,7 +9,7 @@ struct A {
 
 // A does not have a key function, so the first constructor we emit should
 // cause the vtable to be defined (without assertions.)
-// CHECK: @_ZTVN6PR56971AE = weak_odr constant
+// CHECK: @_ZTVN6PR56971AE = weak_odr hidden constant
 A::A() { }
 A::A(int) { }
 }
index b3b68703c6d31e90ca34f52d01c18fbd95b1ee2b..a4808d0b761fd2ceb4b5462144e16382977bc24f 100644 (file)
@@ -95,8 +95,9 @@ void use_F(F<char> &fc) {
 // has external linkage.
 // CHECK-1: @_ZTV1B = external constant
 
-// C has no key function, so its vtable should have weak_odr linkage.
-// CHECK-2: @_ZTV1C = weak_odr constant
+// C has no key function, so its vtable should have weak_odr linkage
+// and hidden visibility (rdar://problem/7523229).
+// CHECK-2: @_ZTV1C = weak_odr hidden constant
 // CHECK-2: @_ZTS1C = weak_odr constant
 // CHECK-2: @_ZTI1C = weak_odr constant