]> granicus.if.org Git - clang/commitdiff
Make use of available_externally linkage for vtables when the
authorDouglas Gregor <dgregor@apple.com>
Tue, 5 Jan 2010 21:40:05 +0000 (21:40 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 5 Jan 2010 21:40:05 +0000 (21:40 +0000)
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
test/CodeGenCXX/vtable-linkage.cpp

index ca148da95606b9b44883102abbd4e46dc04c450d..ccbb10505e59e0b4ec21a9e5cfb6a993b24abf4b 100644 (file)
@@ -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);
index 23d78aadf7eb77b76464f9f44012ddf30296459c..5738007041830c9ff7ab879f067856cd6eeea501 100644 (file)
@@ -30,6 +30,7 @@ void D::f() { }
 
 static struct : D { } e;
 
+// The destructor is the key function.
 template<typename T>
 struct E {
   virtual ~E();
@@ -37,6 +38,7 @@ struct E {
 
 template<typename T> E<T>::~E() { }
 
+// Anchor is the key function
 template<>
 struct E<char> {
   virtual void anchor();
@@ -54,6 +56,29 @@ void use_E() {
   (void)el;
 }
 
+// No key function
+template<typename T>
+struct F {
+  virtual void foo() { }
+};
+
+// No key function
+template<>
+struct F<char> {
+  virtual void foo() { }
+};
+
+template struct F<short>;
+extern template struct F<int>;
+
+void use_F(F<char> &fc) {
+  F<int> fi;
+  (void)fi;
+  F<long> 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<short> is an explicit template instantiation without a key
+// function, so its vtable should have weak_odr linkage
+// CHECK: @_ZTV1FIsE = weak_odr constant
+
 // E<long> 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<long> is an implicit template instantiation with no key function,
+// so its vtable should have weak_odr linkage.
+// CHECK: @_ZTV1FIlE = weak_odr constant
+
+// F<int> is an explicit template instantiation declaration without a
+// key function, so its vtable should have weak_odr linkage.
+// CHECK: @_ZTV1FIiE = available_externally constant
+
 // E<int> 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.