Author: dblaikie Date: Fri Jan 27 17:11:10 2017 New Revision: 293344 URL: http://llvm.org/viewvc/llvm-project?rev=293344&view=rev Log: Fix linkage of static locals in available_externally functions to be DiscardableODR/linkonce_odr
As Mehdi put it, entities should either be available_externally+weak_odr, or linkonce_odr+linkonce_odr. While some functions are emitted a_e/weak, their local variables were emitted a_e/linkonce_odr. While it might be nice to emit them a_e/weak, the Itanium ABI (& best guess at MSVC's behavior as well) requires the local to be linkonce/linkonce. Reviewers: rsmith, mehdi_amini Differential Revision: https://reviews.llvm.org/D29233 Modified: cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=293344&r1=293343&r2=293344&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jan 27 17:11:10 2017 @@ -8892,22 +8892,30 @@ static GVALinkage basicGVALinkageForVari return GVA_Internal; if (VD->isStaticLocal()) { - GVALinkage StaticLocalLinkage = GVA_DiscardableODR; const DeclContext *LexicalContext = VD->getParentFunctionOrMethod(); while (LexicalContext && !isa<FunctionDecl>(LexicalContext)) LexicalContext = LexicalContext->getLexicalParent(); - // Let the static local variable inherit its linkage from the nearest - // enclosing function. - if (LexicalContext) - StaticLocalLinkage = - Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext)); + // ObjC Blocks can create local variables that don't have a FunctionDecl + // LexicalContext. + if (!LexicalContext) + return GVA_DiscardableODR; - // GVA_StrongODR function linkage is stronger than what we need, - // downgrade to GVA_DiscardableODR. - // This allows us to discard the variable if we never end up needing it. - return StaticLocalLinkage == GVA_StrongODR ? GVA_DiscardableODR - : StaticLocalLinkage; + // Otherwise, let the static local variable inherit its linkage from the + // nearest enclosing function. + auto StaticLocalLinkage = + Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext)); + + // Itanium ABI 5.2.2: "Each COMDAT group [for a static local variable] must + // be emitted in any object with references to the symbol for the object it + // contains, whether inline or out-of-line." + // Similar behavior is observed with MSVC. An alternative ABI could use + // StrongODR/AvailableExternally to match the function, but none are + // known/supported currently. + if (StaticLocalLinkage == GVA_StrongODR || + StaticLocalLinkage == GVA_AvailableExternally) + return GVA_DiscardableODR; + return StaticLocalLinkage; } // MSVC treats in-class initialized static data members as definitions. Modified: cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp?rev=293344&r1=293343&r2=293344&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp (original) +++ cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp Fri Jan 27 17:11:10 2017 @@ -5,6 +5,9 @@ // This check logically is attached to 'template int S<int>::i;' below. // CHECK: @_ZN1SIiE1iE = weak_odr global i32 +// This check is logically attached to 'template int ExportedStaticLocal::f<int>()' below. +// CHECK-OPT: @_ZZN19ExportedStaticLocal1fIiEEvvE1i = linkonce_odr global + template<typename T, typename U, typename Result> struct plus { Result operator()(const T& t, const U& u) const; @@ -153,3 +156,17 @@ template <typename T> void S<T>::f() {} template <typename T> void S<T>::g() {} template <typename T> int S<T>::i; template <typename T> void S<T>::S2::h() {} + +namespace ExportedStaticLocal { +void sink(int&); +template <typename T> +inline void f() { + static int i; + sink(i); +} +// See the check line at the top of the file. +extern template void f<int>(); +void use() { + f<int>(); +} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits