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
llvm-svn: 293344
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a8732d7..07721b2 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/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));
+ // 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.