This revision was automatically updated to reflect the committed changes. Closed by commit rL293344: Fix linkage of static locals in available_externally functions to be… (authored by dblaikie).
Changed prior to commit: https://reviews.llvm.org/D29233?vs=86137&id=86138#toc Repository: rL LLVM https://reviews.llvm.org/D29233 Files: cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp Index: cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp +++ cfe/trunk/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: cfe/trunk/lib/AST/ASTContext.cpp =================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp +++ cfe/trunk/lib/AST/ASTContext.cpp @@ -8892,22 +8892,30 @@ 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 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.
Index: cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp +++ cfe/trunk/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: cfe/trunk/lib/AST/ASTContext.cpp =================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp +++ cfe/trunk/lib/AST/ASTContext.cpp @@ -8892,22 +8892,30 @@ 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 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.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits