From 39edfeb34b0b0b8033179e35cf13cd5d95d56fa8 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 28 Sep 2013 04:31:26 +0000 Subject: [PATCH] Switch from putting init capture VarDecls in the surrounding DeclContext to 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 | 15 +++++++++++---- lib/Sema/SemaLambda.cpp | 2 +- test/CodeGenCXX/cxx1y-init-captures.cpp | 4 ++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index b1a768d635..9940e8ba79 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1577,7 +1577,9 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, bool refersToEnclosingScope = (CurContext != D->getDeclContext() && - D->getDeclContext()->isFunctionOrMethod()); + D->getDeclContext()->isFunctionOrMethod()) || + (isa(D) && + cast(D)->isInitCapture()); DeclRefExpr *E; if (isa(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(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(); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 08048d54d9..a87c903d3b 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -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); diff --git a/test/CodeGenCXX/cxx1y-init-captures.cpp b/test/CodeGenCXX/cxx1y-init-captures.cpp index 6258cda3b0..a60269f3b1 100644 --- a/test/CodeGenCXX/cxx1y-init-captures.cpp +++ b/test/CodeGenCXX/cxx1y-init-captures.cpp @@ -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( -- 2.40.0