From 074a2cf3c51229b90b77e998463530c9b06470e6 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 5 Jan 2010 21:40:05 +0000 Subject: [PATCH] Make use of available_externally linkage for vtables when the non-inline key function of a class template instantiation, when no key function is present, the class template instantiation itself was instantiated with an explicit instantiation declaration (aka extern template). I'm fairly certain that the C++0x specification gives us this lattitude, although GCC doesn't take advantage of it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92779 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGVtable.cpp | 23 +++++++++++++++---- test/CodeGenCXX/vtable-linkage.cpp | 37 ++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index ca148da956..ccbb10505e 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1501,16 +1501,31 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { break; case TSK_ImplicitInstantiation: - case TSK_ExplicitInstantiationDeclaration: - // FIXME: could an explicit instantiation declaration imply - // available_externally linkage? case TSK_ExplicitInstantiationDefinition: Linkage = llvm::GlobalVariable::WeakODRLinkage; break; + + case TSK_ExplicitInstantiationDeclaration: + Linkage = llvm::GlobalVariable::AvailableExternallyLinkage; + break; } } - else + else if (KeyFunction) Linkage = llvm::GlobalVariable::WeakODRLinkage; + else { + switch (RD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDefinition: + Linkage = llvm::GlobalVariable::WeakODRLinkage; + break; + + case TSK_ExplicitInstantiationDeclaration: + Linkage = llvm::GlobalVariable::AvailableExternallyLinkage; + break; + } + } // Emit the data. GenerateClassData(Linkage, RD); diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp index 23d78aadf7..5738007041 100644 --- a/test/CodeGenCXX/vtable-linkage.cpp +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -30,6 +30,7 @@ void D::f() { } static struct : D { } e; +// The destructor is the key function. template struct E { virtual ~E(); @@ -37,6 +38,7 @@ struct E { template E::~E() { } +// Anchor is the key function template<> struct E { virtual void anchor(); @@ -54,6 +56,29 @@ void use_E() { (void)el; } +// No key function +template +struct F { + virtual void foo() { } +}; + +// No key function +template<> +struct F { + virtual void foo() { } +}; + +template struct F; +extern template struct F; + +void use_F(F &fc) { + F fi; + (void)fi; + F fl; + (void)fl; + fc.foo(); +} + // B has a key function that is not defined in this translation unit so its vtable // has external linkage. // CHECK: @_ZTV1B = external constant @@ -79,6 +104,10 @@ void use_E() { // weak_odr linkage. // CHECK: @_ZTV1EIsE = weak_odr constant +// F is an explicit template instantiation without a key +// function, so its vtable should have weak_odr linkage +// CHECK: @_ZTV1FIsE = weak_odr constant + // E is an implicit template instantiation with a key function // defined in this translation unit, so its vtable should have // weak_odr linkage. @@ -90,6 +119,14 @@ void use_E() { // CHECK: @"_ZTI3$_0" = internal constant // CHECK: @"_ZTV3$_0" = internal constant +// F is an implicit template instantiation with no key function, +// so its vtable should have weak_odr linkage. +// CHECK: @_ZTV1FIlE = weak_odr constant + +// F is an explicit template instantiation declaration without a +// key function, so its vtable should have weak_odr linkage. +// CHECK: @_ZTV1FIiE = available_externally constant + // E is an explicit template instantiation declaration. It has a // key function that is not instantiation, so we should only reference // its vtable, not define it. -- 2.40.0