From 678eca456bc62900dc7407bdbc9fa282da9d2f8f Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 13 Jun 2013 21:50:44 +0000 Subject: [PATCH] Fix the linkage of static locals inside a CapturedStmt. (Found in the process of trying to fix the related issue for block literals.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183951 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 24 +++++++++++++++++++++--- lib/CodeGen/CodeGenModule.cpp | 6 +++++- lib/CodeGen/CodeGenModule.h | 1 + test/CodeGenCXX/captured-statements.cpp | 15 +++++++++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 7fdd334e04..cb15748646 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -129,9 +129,27 @@ void CodeGenFunction::EmitVarDecl(const VarDecl &D) { // uniqued. We can't do this in C, though, because there's no // standard way to agree on which variables are the same (i.e. // there's no mangling). - if (getLangOpts().CPlusPlus) - if (llvm::GlobalValue::isWeakForLinker(CurFn->getLinkage())) - Linkage = CurFn->getLinkage(); + if (getLangOpts().CPlusPlus) { + const Decl *D = CurCodeDecl; + while (true) { + if (isa(D)) { + // FIXME: Handle this case properly! (Should be similar to the + // way we handle lambdas in computeLVForDecl in Decl.cpp.) + break; + } else if (isa(D)) { + D = cast(cast(D)->getParent()); + } else { + break; + } + } + // FIXME: Do we really only care about FunctionDecls here? + if (D && isa(D)) { + llvm::GlobalValue::LinkageTypes ParentLinkage = + CGM.getFunctionLinkage(cast(D)); + if (llvm::GlobalValue::isWeakForLinker(ParentLinkage)) + Linkage = ParentLinkage; + } + } return EmitStaticVarDecl(D, Linkage); } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index f6218cddfb..4865a9174c 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -510,7 +510,11 @@ void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) { llvm::GlobalValue::LinkageTypes CodeGenModule::getFunctionLinkage(GlobalDecl GD) { - const FunctionDecl *D = cast(GD.getDecl()); + return getFunctionLinkage(cast(GD.getDecl())); +} + +llvm::GlobalValue::LinkageTypes +CodeGenModule::getFunctionLinkage(const FunctionDecl *D) { GVALinkage Linkage = getContext().GetGVALinkageForFunction(D); if (Linkage == GVA_Internal) diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ffb1243726..6e5985d9bf 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -925,6 +925,7 @@ public: void AddDependentLib(StringRef Lib); llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD); + llvm::GlobalVariable::LinkageTypes getFunctionLinkage(const FunctionDecl *D); void setFunctionLinkage(GlobalDecl GD, llvm::GlobalValue *V) { V->setLinkage(getFunctionLinkage(GD)); diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp index cfa6936111..65f5abb9a4 100644 --- a/test/CodeGenCXX/captured-statements.cpp +++ b/test/CodeGenCXX/captured-statements.cpp @@ -5,6 +5,7 @@ // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-4 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-5 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-6 +// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-7 struct Foo { int x; @@ -172,3 +173,17 @@ void test_capture_lambda() { // CHECK-6-NEXT: ret void template_capture_lambda(); } + +inline int test_captured_linkage() { + // CHECK-7: @_ZN21test_captured_linkage1iE = linkonce_odr global i32 0 + int j; + #pragma clang __debug captured + { + static int i = 0; + j = ++i; + } + return j; +} +void call_test_captured_linkage() { + test_captured_linkage(); +} -- 2.40.0