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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98441 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index c67948d..f41db14 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -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() &&
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 40dc563..9077ade 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -437,7 +437,8 @@
     GVA_C99Inline,
     GVA_CXXInline,
     GVA_StrongExternal,
-    GVA_TemplateInstantiation
+    GVA_TemplateInstantiation,
+    GVA_ExplicitTemplateInstantiation
   };
 
   llvm::GlobalVariable::LinkageTypes