aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGVTables.cpp36
-rw-r--r--test/CodeGenCXX/mangle-subst-std.cpp6
-rw-r--r--test/CodeGenCXX/virt-template-vtable.cpp2
-rw-r--r--test/CodeGenCXX/vtable-linkage.cpp16
4 files changed, 42 insertions, 18 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 052a6fdca3..9cb64c6d5b 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -2929,18 +2929,34 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
// 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
+ // possible that there might be unresolved references elsewhere
+ // which can only be resolved by this emission.
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);
+ !RD->hasAttr<VisibilityAttr>()) {
+ switch (RD->getTemplateSpecializationKind()) {
+
+ // Every use of a non-template or explicitly-specialized class's
+ // vtable has to emit it.
+ case TSK_ExplicitSpecialization:
+ case TSK_Undeclared:
+ // Implicit instantiations can ignore the possibility of an
+ // explicit instantiation declaration because there necessarily
+ // must be an EI definition somewhere with default visibility.
+ case TSK_ImplicitInstantiation:
+ // If there's a key function, there may be translation units
+ // that don't have the key function's definition.
+ if (!CGM.Context.getKeyFunction(RD))
+ // Otherwise, drop the visibility to hidden.
+ VTable->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ break;
+
+ // We have to disable the optimization if this is an EI definition
+ // because there might be EI declarations in other shared objects.
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitInstantiationDeclaration:
+ break;
+ }
}
}
diff --git a/test/CodeGenCXX/mangle-subst-std.cpp b/test/CodeGenCXX/mangle-subst-std.cpp
index 9c1e978294..b08b12c91e 100644
--- a/test/CodeGenCXX/mangle-subst-std.cpp
+++ b/test/CodeGenCXX/mangle-subst-std.cpp
@@ -3,13 +3,13 @@
// Check mangling of Vtables, VTTs, and construction vtables that
// involve standard substitutions.
-// CHECK: @_ZTVSd = weak_odr constant
+// CHECK: @_ZTVSd = weak_odr hidden constant
// CHECK: @_ZTCSd0_Si = internal constant
// CHECK: @_ZTCSd16_So = internal constant
// CHECK: @_ZTTSd = weak_odr constant
-// CHECK: @_ZTVSo = weak_odr constant
+// CHECK: @_ZTVSo = weak_odr hidden constant
// CHECK: @_ZTTSo = weak_odr constant
-// CHECK: @_ZTVSi = weak_odr constant
+// CHECK: @_ZTVSi = weak_odr hidden constant
// CHECK: @_ZTTSi = weak_odr constant
namespace std {
struct A { A(); };
diff --git a/test/CodeGenCXX/virt-template-vtable.cpp b/test/CodeGenCXX/virt-template-vtable.cpp
index b955828312..ab406fd998 100644
--- a/test/CodeGenCXX/virt-template-vtable.cpp
+++ b/test/CodeGenCXX/virt-template-vtable.cpp
@@ -19,4 +19,4 @@ 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
+// CHECK: @_ZTV1AIiE = weak_odr hidden constant
diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp
index a4808d0b76..9b93a316be 100644
--- a/test/CodeGenCXX/vtable-linkage.cpp
+++ b/test/CodeGenCXX/vtable-linkage.cpp
@@ -11,6 +11,7 @@
// RUN: FileCheck --check-prefix=CHECK-10 %s < %t
// RUN: FileCheck --check-prefix=CHECK-11 %s < %t
// RUN: FileCheck --check-prefix=CHECK-12 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-13 %s < %t
namespace {
struct A {
@@ -83,12 +84,13 @@ struct F<char> {
template struct F<short>;
extern template struct F<int>;
-void use_F(F<char> &fc) {
+void use_F() {
+ F<char> fc;
+ fc.foo();
F<int> fi;
fi.foo();
F<long> fl;
(void)fl;
- fc.foo();
}
// B has a key function that is not defined in this translation unit so its vtable
@@ -135,8 +137,8 @@ void use_F(F<char> &fc) {
// CHECK-7: @_ZTI1EIlE = weak_odr constant
// F<long> is an implicit template instantiation with no key function,
-// so its vtable should have weak_odr linkage.
-// CHECK-8: @_ZTV1FIlE = weak_odr constant
+// so its vtable should have weak_odr linkage and hidden visibility.
+// CHECK-8: @_ZTV1FIlE = weak_odr hidden constant
// CHECK-8: @_ZTS1FIlE = weak_odr constant
// CHECK-8: @_ZTI1FIlE = weak_odr constant
@@ -161,6 +163,12 @@ void use_F(F<char> &fc) {
// CHECK-12: @_ZTSN12_GLOBAL__N_11AE = internal constant
// CHECK-12: @_ZTIN12_GLOBAL__N_11AE = internal constant
+// F<char> is an explicit specialization without a key function, so
+// its vtable should have weak_odr linkage and hidden visibility.
+// CHECK-13: @_ZTV1FIcE = weak_odr hidden constant
+// CHECK-13: @_ZTS1FIcE = weak_odr constant
+// CHECK-13: @_ZTI1FIcE = weak_odr constant
+
// RUN: FileCheck --check-prefix=CHECK-G %s < %t
//
// CHECK-G: @_ZTV1GIiE = weak_odr constant