]> granicus.if.org Git - clang/commitdiff
Switch from putting init capture VarDecls in the surrounding DeclContext to
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 28 Sep 2013 04:31:26 +0000 (04:31 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 28 Sep 2013 04:31:26 +0000 (04:31 +0000)
putting them in the call operator's DeclContext. This better matches the
language wording and avoids some cases where code gets confused by them for
namespace-scope lambdas and the like.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191606 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
lib/Sema/SemaLambda.cpp
test/CodeGenCXX/cxx1y-init-captures.cpp

index b1a768d635db0c4498c4102181feac4588508b87..9940e8ba79b1a07106e97fc3e68c1f1d0a16cfe3 100644 (file)
@@ -1577,7 +1577,9 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
 
   bool refersToEnclosingScope =
     (CurContext != D->getDeclContext() &&
-     D->getDeclContext()->isFunctionOrMethod());
+     D->getDeclContext()->isFunctionOrMethod()) ||
+    (isa<VarDecl>(D) &&
+     cast<VarDecl>(D)->isInitCapture());
 
   DeclRefExpr *E;
   if (isa<VarTemplateSpecializationDecl>(D)) {
@@ -8116,9 +8118,14 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
   assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
 
   // Decide whether the first capture was for a block or a lambda.
-  DeclContext *DC = S.CurContext;
-  while (DC->getParent() != var->getDeclContext())
+  DeclContext *DC = S.CurContext, *Prev = 0;
+  while (DC != var->getDeclContext()) {
+    Prev = DC;
     DC = DC->getParent();
+  }
+  // Unless we have an init-capture, we've gone one step too far.
+  if (!var->isInitCapture())
+    DC = Prev;
   return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
 }
 
@@ -11353,7 +11360,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
   bool Nested = false;
   
   DeclContext *DC = CurContext;
-  if (Var->getDeclContext() == DC) return true;
+  if (!Var->isInitCapture() && Var->getDeclContext() == DC) return true;
   if (!Var->hasLocalStorage()) return true;
 
   bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
index 08048d54d92d768c59a482bd22d50adb52bc26e3..a87c903d3bcea40e7028b96e8ef6d1938a97b6c2 100644 (file)
@@ -514,7 +514,7 @@ VarDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
   // used as a variable, and only exists as a way to name and refer to the
   // init-capture.
   // FIXME: Pass in separate source locations for '&' and identifier.
-  VarDecl *NewVD = VarDecl::Create(Context, CurContext->getLexicalParent(), Loc,
+  VarDecl *NewVD = VarDecl::Create(Context, CurContext, Loc,
                                    Loc, Id, TSI->getType(), TSI, SC_Auto);
   NewVD->setInitCapture(true);
   NewVD->setReferenced(true);
index 6258cda3b0e5d4b1667f6e83a2030bbb658d4ff6..a60269f3b1854a045a91654c68bf6d93f79c5fda 100644 (file)
@@ -94,5 +94,9 @@ int h(int a) {
   } ();
 }
 
+// Ensure we can emit code for init-captures in global lambdas too.
+auto global_lambda = [a = 0] () mutable { return ++a; };
+int get_incremented() { return global_lambda(); }
+
 // CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D2Ev"(
 // CHECK: call void @_ZN1SD1Ev(