From: Douglas Gregor Date: Wed, 8 Feb 2012 20:56:50 +0000 (+0000) Subject: When computing the type of a local variable reference within a lambda, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1e3767ac5449db6a1ede192d5e4217e34fa61f26;p=clang When computing the type of a local variable reference within a lambda, only add 'const' for variables captured by copy in potentially evaluated expressions of non-mutable lambdas. (The "by copy" part was missing). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150088 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bbf992c219..accf85171e 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2094,6 +2094,15 @@ static bool shouldBuildBlockDeclRef(ValueDecl *D, Sema &S) { return S.getCurBlock() != 0; } +/// \brief Determine whether the given lambda would capture the given +/// variable by copy. +static bool willCaptureByCopy(LambdaScopeInfo *LSI, VarDecl *Var) { + if (LSI->isCaptured(Var)) + return LSI->getCapture(Var).isCopyCapture(); + + return LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval; +} + static bool shouldAddConstQualToVarRef(ValueDecl *D, Sema &S) { VarDecl *var = dyn_cast(D); if (!var) @@ -2117,7 +2126,8 @@ static bool shouldAddConstQualToVarRef(ValueDecl *D, Sema &S) { // about decltype hints that it might apply in unevaluated contexts // as well... and there's precent in our blocks implementation. return !LSI->Mutable && - S.ExprEvalContexts.back().Context != Sema::Unevaluated; + S.ExprEvalContexts.back().Context != Sema::Unevaluated && + willCaptureByCopy(LSI, var); } static ExprResult BuildBlockDeclRefExpr(Sema &S, ValueDecl *VD, diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp index 239b6d4f46..0696f603b6 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp @@ -6,7 +6,40 @@ void analysis_based_warnings() { // expected-error{{lambda expressions are not supported yet}} } -// FIXME: Also check translation of captured vars to data members, -// most of which isn't in the AST. +// Check that we get the right types of captured variables (the semantic-analysis part of +int &check_const_int(int&); +float &check_const_int(const int&); + +void test_capture_constness(int i, const int ic) { + [i,ic] ()->void { // expected-error{{lambda expressions are not supported yet}} + float &fr1 = check_const_int(i); + float &fr2 = check_const_int(ic); + }; + + [=] ()->void { // expected-error{{lambda expressions are not supported yet}} + float &fr1 = check_const_int(i); + float &fr2 = check_const_int(ic); + }; + + [i,ic] () mutable ->void { // expected-error{{lambda expressions are not supported yet}} + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + [=] () mutable ->void { // expected-error{{lambda expressions are not supported yet}} + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + [&i,&ic] ()->void { // expected-error{{lambda expressions are not supported yet}} + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + [&] ()->void { // expected-error{{lambda expressions are not supported yet}} + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; +}