r293344 - Fix linkage of static locals in available_externally functions to be DiscardableODR/linkonce_odr
David Blaikie via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 27 15:11:10 PST 2017
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>();
+}
+}
More information about the cfe-commits
mailing list