<div dir="ltr">Reid:<br><br>Richard and I played around with this with <a href="http://gcc.godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(j:1,options:(colouriseAsm:'0',compileOnChange:'0'),source:'int+g(const+int+%26v)%0A%23if+DEF%0A%7B+return+v%3B+%7D%0A%23else%0A%3B%0A%23endif%0A%0Atemplate%3Ctypename+T%3E%0Ainline+int+f()+%7B%0A++static+const+int+n+%3D+0%3B%0A++return+g(n)%3B%0A%7D%0A%0A%23if+DEF%0Atemplate+int+f%3Cint%3E()%3B%0A%23else%0Aextern+template+int+f%3Cint%3E()%3B%0Aint+k()+%7B+return+f%3Cint%3E()%3B+%7D%0A%23endif'),l:'5',n:'1',o:'C%2B%2B+source+%231',t:'0')),k:43.27735263873981,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:cl19_64,filters:(),options:/Ox),l:'5',n:'0',o:'%231+with+x86-64+CL+19+RC',t:'0'),(h:output,i:(compiler:1,editor:1),l:'5',n:'0',o:'%231+with+x86-64+CL+19+RC',t:'0')),k:56.722647361260194,l:'4',m:50,n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:cl19_64,filters:(),options:'/Ox+/DDEF'),l:'5',n:'0',o:'%231+with+x86-64+CL+19+RC',t:'0')),l:'4',m:50,n:'0',o:'',s:0,t:'0')),k:56.722647361260194,l:'3',n:'0',o:'',t:'0')),l:'2',n:'0',o:'',t:'0')),version:4">MSVC on godbolt</a> but weren't able to get MSVC to inline an template under an explicit instantiation declaration, so while we can see that the definition side doesn't provide a definition for the static local if it optimizes it away (so that seems consistent with the Itanium ABI and GCC's behavior here - no weak_odr definition on the definition side) we couldn't check the declaration/available_externally side to see if it would produce its own linkonce_odr-type definition.<br><br>If you knew of any ways to check, or ways to verify Clang's behavior here is consistent (it looks like it will be with this patch), that might be handy.<br><br>- Dave<br><br><div class="gmail_quote"><div dir="ltr">On Fri, Jan 27, 2017 at 2:04 PM David Blaikie via Phabricator via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">dblaikie created this revision.<br class="gmail_msg">
<br class="gmail_msg">
As Mehdi put it, entities should either be<br class="gmail_msg">
available_externally+weak_odr, or linkonce_odr+linkonce_odr. While some<br class="gmail_msg">
functions are emitted a_e/weak, their local variables were emitted<br class="gmail_msg">
a_e/linkonce_odr.<br class="gmail_msg">
<br class="gmail_msg">
While it might be nice to emit them a_e/weak, the Itanium ABI (& best<br class="gmail_msg">
guess at MSVC's behavior as well) requires the local to be<br class="gmail_msg">
linkonce/linkonce.<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
<a href="https://reviews.llvm.org/D29233" rel="noreferrer" class="gmail_msg" target="_blank">https://reviews.llvm.org/D29233</a><br class="gmail_msg">
<br class="gmail_msg">
Files:<br class="gmail_msg">
  lib/AST/ASTContext.cpp<br class="gmail_msg">
  test/CodeGenCXX/explicit-instantiation.cpp<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Index: test/CodeGenCXX/explicit-instantiation.cpp<br class="gmail_msg">
===================================================================<br class="gmail_msg">
--- test/CodeGenCXX/explicit-instantiation.cpp<br class="gmail_msg">
+++ test/CodeGenCXX/explicit-instantiation.cpp<br class="gmail_msg">
@@ -5,6 +5,9 @@<br class="gmail_msg">
 // This check logically is attached to 'template int S<int>::i;' below.<br class="gmail_msg">
 // CHECK: @_ZN1SIiE1iE = weak_odr global i32<br class="gmail_msg">
<br class="gmail_msg">
+// This check is logically attached to 'template int ExportedStaticLocal::f<int>()' below.<br class="gmail_msg">
+// CHECK-OPT: @_ZZN19ExportedStaticLocal1fIiEEvvE1i = linkonce_odr global<br class="gmail_msg">
+<br class="gmail_msg">
 template<typename T, typename U, typename Result><br class="gmail_msg">
 struct plus {<br class="gmail_msg">
   Result operator()(const T& t, const U& u) const;<br class="gmail_msg">
@@ -153,3 +156,17 @@<br class="gmail_msg">
 template <typename T> void S<T>::g() {}<br class="gmail_msg">
 template <typename T> int S<T>::i;<br class="gmail_msg">
 template <typename T> void S<T>::S2::h() {}<br class="gmail_msg">
+<br class="gmail_msg">
+namespace ExportedStaticLocal {<br class="gmail_msg">
+void sink(int&);<br class="gmail_msg">
+template <typename T><br class="gmail_msg">
+inline void f() {<br class="gmail_msg">
+  static int i;<br class="gmail_msg">
+  sink(i);<br class="gmail_msg">
+}<br class="gmail_msg">
+// See the check line at the top of the file.<br class="gmail_msg">
+extern template void f<int>();<br class="gmail_msg">
+void use() {<br class="gmail_msg">
+  f<int>();<br class="gmail_msg">
+}<br class="gmail_msg">
+}<br class="gmail_msg">
Index: lib/AST/ASTContext.cpp<br class="gmail_msg">
===================================================================<br class="gmail_msg">
--- lib/AST/ASTContext.cpp<br class="gmail_msg">
+++ lib/AST/ASTContext.cpp<br class="gmail_msg">
@@ -8892,22 +8892,27 @@<br class="gmail_msg">
     return GVA_Internal;<br class="gmail_msg">
<br class="gmail_msg">
   if (VD->isStaticLocal()) {<br class="gmail_msg">
-    GVALinkage StaticLocalLinkage = GVA_DiscardableODR;<br class="gmail_msg">
     const DeclContext *LexicalContext = VD->getParentFunctionOrMethod();<br class="gmail_msg">
     while (LexicalContext && !isa<FunctionDecl>(LexicalContext))<br class="gmail_msg">
       LexicalContext = LexicalContext->getLexicalParent();<br class="gmail_msg">
<br class="gmail_msg">
-    // Let the static local variable inherit its linkage from the nearest<br class="gmail_msg">
-    // enclosing function.<br class="gmail_msg">
-    if (LexicalContext)<br class="gmail_msg">
-      StaticLocalLinkage =<br class="gmail_msg">
-          Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext));<br class="gmail_msg">
-<br class="gmail_msg">
-    // GVA_StrongODR function linkage is stronger than what we need,<br class="gmail_msg">
-    // downgrade to GVA_DiscardableODR.<br class="gmail_msg">
-    // This allows us to discard the variable if we never end up needing it.<br class="gmail_msg">
-    return StaticLocalLinkage == GVA_StrongODR ? GVA_DiscardableODR<br class="gmail_msg">
-                                               : StaticLocalLinkage;<br class="gmail_msg">
+    // ObjC Blocks can create local variables that don't have a FunctionDecl<br class="gmail_msg">
+    // LexicalContext.<br class="gmail_msg">
+    if (!LexicalContext)<br class="gmail_msg">
+      return GVA_DiscardableODR;<br class="gmail_msg">
+<br class="gmail_msg">
+    // Otherwise, let the static local variable inherit its linkage from the<br class="gmail_msg">
+    // nearest enclosing function.<br class="gmail_msg">
+    auto StaticLocalLinkage =<br class="gmail_msg">
+        Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext));<br class="gmail_msg">
+<br class="gmail_msg">
+    // Itanium ABI (& MSVC seems to do similarly) requires static locals in<br class="gmail_msg">
+    // inline functions to be emitted anywhere they're needed, even if the<br class="gmail_msg">
+    // function they are local to is emitted StrongODR/AvailableExternally.<br class="gmail_msg">
+    if (StaticLocalLinkage == GVA_StrongODR ||<br class="gmail_msg">
+        StaticLocalLinkage == GVA_AvailableExternally)<br class="gmail_msg">
+      return GVA_DiscardableODR;<br class="gmail_msg">
+    return StaticLocalLinkage;<br class="gmail_msg">
   }<br class="gmail_msg">
<br class="gmail_msg">
   // MSVC treats in-class initialized static data members as definitions.<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
_______________________________________________<br class="gmail_msg">
cfe-commits mailing list<br class="gmail_msg">
<a href="mailto:cfe-commits@lists.llvm.org" class="gmail_msg" target="_blank">cfe-commits@lists.llvm.org</a><br class="gmail_msg">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" class="gmail_msg" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="gmail_msg">
</blockquote></div></div>