[PATCH] D29233: Fix linkage of static locals in available_externally functions to be DiscardableODR/linkonce_odr

Mehdi Amini via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 27 14:13:02 PST 2017


CC Hans.

This is not a regression (AFAICT), but this is a quality improvement, so may be worth considering in the 4.0 branch?

— 
Mehdi

> On Jan 27, 2017, at 2:04 PM, David Blaikie via Phabricator <reviews at reviews.llvm.org> wrote:
> 
> dblaikie created this revision.
> 
> 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.
> 
> 
> https://reviews.llvm.org/D29233
> 
> Files:
>  lib/AST/ASTContext.cpp
>  test/CodeGenCXX/explicit-instantiation.cpp
> 
> 
> Index: test/CodeGenCXX/explicit-instantiation.cpp
> ===================================================================
> --- test/CodeGenCXX/explicit-instantiation.cpp
> +++ test/CodeGenCXX/explicit-instantiation.cpp
> @@ -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>::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>();
> +}
> +}
> Index: lib/AST/ASTContext.cpp
> ===================================================================
> --- lib/AST/ASTContext.cpp
> +++ lib/AST/ASTContext.cpp
> @@ -8892,22 +8892,27 @@
>     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));
> -
> -    // 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;
> +    // ObjC Blocks can create local variables that don't have a FunctionDecl
> +    // LexicalContext.
> +    if (!LexicalContext)
> +      return GVA_DiscardableODR;
> +
> +    // Otherwise, let the static local variable inherit its linkage from the
> +    // nearest enclosing function.
> +    auto StaticLocalLinkage =
> +        Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext));
> +
> +    // Itanium ABI (& MSVC seems to do similarly) requires static locals in
> +    // inline functions to be emitted anywhere they're needed, even if the
> +    // function they are local to is emitted StrongODR/AvailableExternally.
> +    if (StaticLocalLinkage == GVA_StrongODR ||
> +        StaticLocalLinkage == GVA_AvailableExternally)
> +      return GVA_DiscardableODR;
> +    return StaticLocalLinkage;
>   }
> 
>   // MSVC treats in-class initialized static data members as definitions.
> 
> 
> <D29233.86118.patch>



More information about the cfe-commits mailing list