]> granicus.if.org Git - clang/commitdiff
Fix the linkage of static locals inside a CapturedStmt. (Found in the
authorEli Friedman <eli.friedman@gmail.com>
Thu, 13 Jun 2013 21:50:44 +0000 (21:50 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Thu, 13 Jun 2013 21:50:44 +0000 (21:50 +0000)
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
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
test/CodeGenCXX/captured-statements.cpp

index 7fdd334e04c1a6669bd392ade6bc7d521a2faa28..cb15748646310ba3c84f54bfa97a0d38bc365795 100644 (file)
@@ -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<BlockDecl>(D)) {
+          // FIXME: Handle this case properly!  (Should be similar to the
+          // way we handle lambdas in computeLVForDecl in Decl.cpp.)
+          break;
+        } else if (isa<CapturedDecl>(D)) {
+          D = cast<Decl>(cast<CapturedDecl>(D)->getParent());
+        } else {
+          break;
+        }
+      }
+      // FIXME: Do we really only care about FunctionDecls here?
+      if (D && isa<FunctionDecl>(D)) {
+        llvm::GlobalValue::LinkageTypes ParentLinkage =
+            CGM.getFunctionLinkage(cast<FunctionDecl>(D));
+        if (llvm::GlobalValue::isWeakForLinker(ParentLinkage))
+          Linkage = ParentLinkage;
+      }
+    }
 
     return EmitStaticVarDecl(D, Linkage);
   }
index f6218cddfb5b9777e49bd9ecae31d06bdd1b3136..4865a9174c9cf091c68648728c0ea5e52149f1d0 100644 (file)
@@ -510,7 +510,11 @@ void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
 
 llvm::GlobalValue::LinkageTypes
 CodeGenModule::getFunctionLinkage(GlobalDecl GD) {
-  const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
+  return getFunctionLinkage(cast<FunctionDecl>(GD.getDecl()));
+}
+
+llvm::GlobalValue::LinkageTypes
+CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
   GVALinkage Linkage = getContext().GetGVALinkageForFunction(D);
 
   if (Linkage == GVA_Internal)
index ffb1243726ea49d368baf50f3ac991cd32f2e3e1..6e5985d9bf1fd66c6f1952cc40555ce9019c3cfa 100644 (file)
@@ -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));
index cfa693611151c1c98aa47207ce4875a7b6929349..65f5abb9a4fb36d53c6f3390e724a7790f15c62e 100644 (file)
@@ -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<int>();
 }
+
+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();
+}