diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-04-28 22:17:59 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-04-28 22:17:59 +0000 |
commit | 27d69dbbd073b5a4973d7089dcb37f764a76ebb9 (patch) | |
tree | d2a7bd670c8adaedce38c20ed88e33da5f18d9ee /clang/lib/AST/ASTContext.cpp | |
parent | 923cecab5c9361720e81bb098627743e83d21576 (diff) | |
download | bcm5719-llvm-27d69dbbd073b5a4973d7089dcb37f764a76ebb9.tar.gz bcm5719-llvm-27d69dbbd073b5a4973d7089dcb37f764a76ebb9.zip |
CodeGen: Fix linkage of reference temporaries
Summary:
A reference temporary should inherit the linkage of the variable it
initializes. Otherwise, we may hit cases where a reference temporary
wouldn't have the same value in all translation units.
Reviewers: rsmith
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D3515
llvm-svn: 207451
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 84abda2dea6..c6f8e20a17c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7767,8 +7767,10 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { return GVA_StrongODR; case TSK_ExplicitInstantiationDeclaration: + return GVA_AvailableExternally; + case TSK_ImplicitInstantiation: - External = GVA_TemplateInstantiation; + External = GVA_DiscardableODR; break; } @@ -7783,7 +7785,7 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { return External; // C99 inline semantics, where the symbol is not externally visible. - return GVA_C99Inline; + return GVA_AvailableExternally; } // C++0x [temp.explicit]p9: @@ -7794,7 +7796,7 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { // generated in the translation unit. -- end note ] if (FD->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDeclaration) - return GVA_C99Inline; + return GVA_AvailableExternally; // Functions specified with extern and inline in -fms-compatibility mode // forcibly get emitted. While the body of the function cannot be later @@ -7802,27 +7804,53 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { if (FD->getMostRecentDecl()->isMSExternInline()) return GVA_StrongODR; - return GVA_CXXInline; + return GVA_DiscardableODR; } GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { if (!VD->isExternallyVisible()) 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 it's linkage from the nearest + // enclosing function. + if (LexicalContext) + StaticLocalLinkage = + 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; + } + + // On Darwin, the backing variable for a C++11 thread_local variable always + // has internal linkage; all accesses should just be calls to the + // Itanium-specified entry point, which has the normal linkage of the + // variable. + if (VD->getTLSKind() == VarDecl::TLS_Dynamic && + getTargetInfo().getTriple().isMacOSX()) + return GVA_Internal; + switch (VD->getTemplateSpecializationKind()) { case TSK_Undeclared: case TSK_ExplicitSpecialization: return GVA_StrongExternal; - case TSK_ExplicitInstantiationDeclaration: - llvm_unreachable("Variable should not be instantiated"); - // Fall through to treat this like any other instantiation. - case TSK_ExplicitInstantiationDefinition: return GVA_StrongODR; + case TSK_ExplicitInstantiationDeclaration: + return GVA_AvailableExternally; + case TSK_ImplicitInstantiation: - return GVA_TemplateInstantiation; + return GVA_DiscardableODR; } llvm_unreachable("Invalid Linkage!"); @@ -7878,8 +7906,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // static, static inline, always_inline, and extern inline functions can // always be deferred. Normal inline functions can be deferred in C99/C++. // Implicit template instantiations can also be deferred in C++. - if (Linkage == GVA_Internal || Linkage == GVA_C99Inline || - Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) + if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally || + Linkage == GVA_DiscardableODR) return false; return true; } @@ -7892,7 +7920,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Variables that can be needed in other TUs are required. GVALinkage L = GetGVALinkageForVariable(VD); - if (L != GVA_Internal && L != GVA_TemplateInstantiation) + if (L != GVA_Internal && L != GVA_DiscardableODR) return true; // Variables that have destruction with side-effects are required. |