[cfe-commits] r98441 - in /cfe/trunk: lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp test/CodeGenCXX/explicit-instantiation.cpp test/CodeGenCXX/mangle-exprs.cpp test/CodeGenCXX/mangle-template.cpp test/CodeGenCXX/mangle.cpp test/CodeGenCXX/member-templates.cpp test/CodeGenCXX/template-linkage.cpp test/CodeGenCXX/temporaries.cpp

Douglas Gregor dgregor at apple.com
Sat Mar 13 10:23:07 PST 2010


Author: dgregor
Date: Sat Mar 13 12:23:07 2010
New Revision: 98441

URL: http://llvm.org/viewvc/llvm-project?rev=98441&view=rev
Log:
Give explicit template instantiations weak ODR linkage. Former
iterations of this patch gave explicit template instantiation
link-once ODR linkage, which permitted the back end to eliminate
unused symbols. Weak ODR linkage still requires the symbols to be
generated.

Modified:
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
    cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp
    cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp
    cfe/trunk/test/CodeGenCXX/mangle-template.cpp
    cfe/trunk/test/CodeGenCXX/mangle.cpp
    cfe/trunk/test/CodeGenCXX/member-templates.cpp
    cfe/trunk/test/CodeGenCXX/template-linkage.cpp
    cfe/trunk/test/CodeGenCXX/temporaries.cpp

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Mar 13 12:23:07 2010
@@ -285,8 +285,7 @@
       break;
 
     case TSK_ExplicitInstantiationDefinition:
-      // FIXME: explicit instantiation definitions should use weak linkage
-      return CodeGenModule::GVA_StrongExternal;
+      return CodeGenModule::GVA_ExplicitTemplateInstantiation;
 
     case TSK_ExplicitInstantiationDeclaration:
     case TSK_ImplicitInstantiation:
@@ -343,6 +342,12 @@
     // merged with other definitions. c) C++ has the ODR, so we know the
     // definition is dependable.
     return llvm::Function::LinkOnceODRLinkage;
+  } else if (Linkage == GVA_ExplicitTemplateInstantiation) {
+    // An explicit instantiation of a template has weak linkage, since
+    // explicit instantiations can occur in multiple translation units
+    // and must all be equivalent. However, we are not allowed to
+    // throw away these explicit instantiations.
+    return llvm::Function::WeakODRLinkage;
   } else {
     assert(Linkage == GVA_StrongExternal);
     // Otherwise, we have strong external linkage.
@@ -589,6 +594,7 @@
 
     // static, static inline, always_inline, and extern inline functions can
     // always be deferred.  Normal inline functions can be deferred in C99/C++.
+    // Implicit template instantiations can also be deferred in C++.
     if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
         Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
       return true;
@@ -1043,15 +1049,15 @@
     switch (TSK) {
     case TSK_Undeclared:
     case TSK_ExplicitSpecialization:
-
-      // FIXME: ExplicitInstantiationDefinition should be weak!
-    case TSK_ExplicitInstantiationDefinition:
       return CodeGenModule::GVA_StrongExternal;
-      
+
     case TSK_ExplicitInstantiationDeclaration:
       llvm_unreachable("Variable should not be instantiated");
       // Fall through to treat this like any other instantiation.
         
+    case TSK_ExplicitInstantiationDefinition:
+      return CodeGenModule::GVA_ExplicitTemplateInstantiation;
+
     case TSK_ImplicitInstantiation:
       return CodeGenModule::GVA_TemplateInstantiation;      
     }
@@ -1171,7 +1177,10 @@
       GV->setLinkage(llvm::GlobalVariable::WeakODRLinkage);
     else
       GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
-  } else if (Linkage == GVA_TemplateInstantiation)
+  } else if (Linkage == GVA_TemplateInstantiation ||
+             Linkage == GVA_ExplicitTemplateInstantiation)
+    // FIXME: It seems like we can provide more specific linkage here
+    // (LinkOnceODR, WeakODR).
     GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);   
   else if (!getLangOptions().CPlusPlus && !CodeGenOpts.NoCommon &&
            !D->hasExternalStorage() && !D->getInit() &&

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sat Mar 13 12:23:07 2010
@@ -437,7 +437,8 @@
     GVA_C99Inline,
     GVA_CXXInline,
     GVA_StrongExternal,
-    GVA_TemplateInstantiation
+    GVA_TemplateInstantiation,
+    GVA_ExplicitTemplateInstantiation
   };
 
   llvm::GlobalVariable::LinkageTypes

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp Sat Mar 13 12:23:07 2010
@@ -12,10 +12,10 @@
 template<typename T>
 T X<T>::member2 = 17;
 
-// CHECK: @_ZN1XIiE7member1E = global i32 0
+// CHECK: @_ZN1XIiE7member1E = weak global i32 0
 template int X<int>::member1;
 
-// CHECK: @_ZN1XIiE7member2E = global i32 17
+// CHECK: @_ZN1XIiE7member2E = weak global i32 17
 template int X<int>::member2;
 
 // For implicit instantiation of 

Modified: cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp Sat Mar 13 12:23:07 2010
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o %t %s
-// RUN: grep "define i32 @_ZNK4plusIillEclERKiRKl" %t | count 1
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o - %s | FileCheck %s
 
 template<typename T, typename U, typename Result>
 struct plus {
@@ -11,4 +10,5 @@
   return t + u;
 }
 
+// CHECK: define weak_odr i32 @_ZNK4plusIillEclERKiRKl
 template struct plus<int, long, long>;

Modified: cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp Sat Mar 13 12:23:07 2010
@@ -30,15 +30,15 @@
 
   template <int N> T<N> f() { return T<N>(); }
   
-  // CHECK: define void @_ZN5Casts8implicitILj4EEEvPN9enable_ifIXleT_Li4EEvE4typeE
+  // CHECK: define weak_odr void @_ZN5Casts8implicitILj4EEEvPN9enable_ifIXleT_Li4EEvE4typeE
   template void implicit<4>(void*);
-  // CHECK: define void @_ZN5Casts6cstyleILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
+  // CHECK: define weak_odr void @_ZN5Casts6cstyleILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
   template void cstyle<4>(void*);
-  // CHECK: define void @_ZN5Casts10functionalILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
+  // CHECK: define weak_odr void @_ZN5Casts10functionalILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
   template void functional<4>(void*);
-  // CHECK: define void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
+  // CHECK: define weak_odr void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
   template void static_<4>(void*);
 
-  // CHECK: define i64 @_ZN5Casts1fILi6EEENS_1TIXT_EEEv
+  // CHECK: define weak_odr i64 @_ZN5Casts1fILi6EEENS_1TIXT_EEEv
   template T<6> f<6>();
 }

Modified: cfe/trunk/test/CodeGenCXX/mangle-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-template.cpp?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-template.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-template.cpp Sat Mar 13 12:23:07 2010
@@ -82,7 +82,7 @@
     X(U*, typename int_c<(meta<T>::value + meta<U>::value)>::type *) { }
   };
 
-  // CHECK: define void @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsrNS6_IS3_EE5valueEE4typeE
+  // CHECK: define weak_odr void @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsrNS6_IS3_EE5valueEE4typeE
   template X<int>::X(double*, float*);
 }
 
@@ -101,6 +101,6 @@
   template<typename T>
   void f(int_c<meta<T>::type::value>) { }
 
-  // CHECK: define void @_ZN5test81fIiEEvNS_5int_cIXsrNS_4metaIT_E4typeE5valueEEE
+  // CHECK: define weak_odr void @_ZN5test81fIiEEvNS_5int_cIXsrNS_4metaIT_E4typeE5valueEEE
   template void f<int>(int_c<sizeof(int)>);
 }

Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Sat Mar 13 12:23:07 2010
@@ -250,26 +250,26 @@
 namespace Expressions {
 // Unary operators.
 
-// CHECK: define void @_ZN11Expressions2f1ILi1EEEvPAplngT_Li2E_i
+// CHECK: define weak_odr void @_ZN11Expressions2f1ILi1EEEvPAplngT_Li2E_i
 template <int i> void f1(int (*)[(-i) + 2]) { };
 template void f1<1>(int (*)[1]);
 
-// CHECK: define void @_ZN11Expressions2f2ILi1EEEvPApsT__i
+// CHECK: define weak_odr void @_ZN11Expressions2f2ILi1EEEvPApsT__i
 template <int i> void f2(int (*)[+i]) { };
 template void f2<1>(int (*)[1]);
 
 // Binary operators.
 
-// CHECK: define void @_ZN11Expressions2f3ILi1EEEvPAplT_T__i
+// CHECK: define weak_odr void @_ZN11Expressions2f3ILi1EEEvPAplT_T__i
 template <int i> void f3(int (*)[i+i]) { };
 template void f3<1>(int (*)[2]);
 
-// CHECK: define void @_ZN11Expressions2f4ILi1EEEvPAplplLi2ET_T__i
+// CHECK: define weak_odr void @_ZN11Expressions2f4ILi1EEEvPAplplLi2ET_T__i
 template <int i> void f4(int (*)[2 + i+i]) { };
 template void f4<1>(int (*)[4]);
 
 // The ternary operator.
-// CHECK: define void @_ZN11Expressions2f4ILb1EEEvPAquT_Li1ELi2E_i
+// CHECK: define weak_odr void @_ZN11Expressions2f4ILb1EEEvPAquT_Li1ELi2E_i
 template <bool b> void f4(int (*)[b ? 1 : 2]) { };
 template void f4<true>(int (*)[1]);
 }
@@ -305,7 +305,7 @@
   T *allocate(int, const void*) { return 0; }
 };
 
-// CHECK: define i8* @_ZN6PR58615AllocIcNS_6PolicyINS_1PELb1EEEE8allocateEiPKv
+// CHECK: define weak_odr i8* @_ZN6PR58615AllocIcNS_6PolicyINS_1PELb1EEEE8allocateEiPKv
 template class Alloc<char>;
 }
 
@@ -369,7 +369,7 @@
 namespace test1 {
   template<typename T> struct X { };
   template<template<class> class Y, typename T> void f(Y<T>) { }
-  // CHECK: define void @_ZN5test11fINS_1XEiEEvT_IT0_E
+  // CHECK: define weak_odr void @_ZN5test11fINS_1XEiEEvT_IT0_E
   template void f(X<int>);
 }
 
@@ -399,10 +399,10 @@
   //template <class T> decltype(((T*) 0)->Path1::ab) get_ab_1(T &ref) { return ref.Path1::ab; }
   //template <class T> decltype(((T*) 0)->Path2::ab) get_ab_2(T &ref) { return ref.Path2::ab; }
 
-  // define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path11pERS2_(
+  // define weak_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path11pERS2_(
   template <class T> decltype(((T*) 0)->Path1::p) get_p_1(T &ref) { return ref.Path1::p; }
 
-  // define linkonce_odr double @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path21pERS2_(
+  // define weak_odr double @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path21pERS2_(
   template <class T> decltype(((T*) 0)->Path2::p) get_p_2(T &ref) { return ref.Path2::p; }
 
   Derived obj;
@@ -447,7 +447,7 @@
   void g(zed<&foo::bar>*)
   {}
 }
-// CHECK: define void @_ZN5test81AILZNS_1B5valueEEE3incEv
+// CHECK: define weak_odr void @_ZN5test81AILZNS_1B5valueEEE3incEv
 namespace test8 {
   template <int &counter> class A { void inc() { counter++; } };
   class B { static int value; };

Modified: cfe/trunk/test/CodeGenCXX/member-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/member-templates.cpp?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/member-templates.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/member-templates.cpp Sat Mar 13 12:23:07 2010
@@ -15,8 +15,8 @@
 
 template<typename T> B::B(T) {}
 
-// CHECK: define void @_ZN1BC1IiEET_(%struct.B* %this, i32)
-// CHECK: define void @_ZN1BC2IiEET_(%struct.B* %this, i32)
+// CHECK: define weak_odr void @_ZN1BC1IiEET_(%struct.B* %this, i32)
+// CHECK: define weak_odr void @_ZN1BC2IiEET_(%struct.B* %this, i32)
 template B::B(int);
 
 template<typename T>

Modified: cfe/trunk/test/CodeGenCXX/template-linkage.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/template-linkage.cpp?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/template-linkage.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/template-linkage.cpp Sat Mar 13 12:23:07 2010
@@ -6,19 +6,19 @@
 
 // Explicit instantiations have external linkage.
 
-// CHECK: define void @_ZN1AIiE1gEv(
+// CHECK: define weak_odr void @_ZN1AIiE1gEv(
 template void A<int>::g();
 
-// CHECK: define void @_ZN1AIfE1fEf(
-// CHECK: define void @_ZN1AIfE1gEv(
+// CHECK: define weak_odr void @_ZN1AIfE1fEf(
+// CHECK: define weak_odr void @_ZN1AIfE1gEv(
 // FIXME: This should also emit the vtable.
 template struct A<float>;
 
-// CHECK: define void @_Z1fIiEvT_
+// CHECK: define weak_odr void @_Z1fIiEvT_
 template <typename T> void f(T) { }
 template void f<int>(int);
 
-// CHECK: define void @_Z1gIiEvT_
+// CHECK: define weak_odr void @_Z1gIiEvT_
 template <typename T> inline void g(T) { }
 template void g<int>(int);
 

Modified: cfe/trunk/test/CodeGenCXX/temporaries.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/temporaries.cpp?rev=98441&r1=98440&r2=98441&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/temporaries.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/temporaries.cpp Sat Mar 13 12:23:07 2010
@@ -256,7 +256,7 @@
 
   struct B { operator A(); };
 
-  // CHECK: define void @_ZN6PR61992f2IiEENS_1AET_
+  // CHECK: define weak_odr void @_ZN6PR61992f2IiEENS_1AET_
   template<typename T> A f2(T) {
     B b;
     // CHECK: call void @_ZN6PR61991BcvNS_1AEEv





More information about the cfe-commits mailing list