From: Eli Friedman Date: Mon, 12 Mar 2012 20:57:19 +0000 (+0000) Subject: Make sure we treat variables captured by reference in lambda as modifiable lvalues... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=71930e02730f3afecd6e71e4d6831b4a07436a7f;p=clang Make sure we treat variables captured by reference in lambda as modifiable lvalues. Regression from r152491. Fixes PR12248. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152573 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 3261eb6974..6697c9d7da 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -558,18 +558,6 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, if (Ctx.getLangOpts().CPlusPlus && E->getType()->isFunctionType()) return Cl::CM_Function; - // You cannot assign to a variable outside a block from within the block if - // it is not marked __block, e.g. - // void takeclosure(void (^C)(void)); - // void func() { int x = 1; takeclosure(^{ x = 7; }); } - if (const DeclRefExpr *DRE = dyn_cast(E)) { - if (DRE->refersToEnclosingLocal() && - isa(DRE->getDecl()) && - cast(DRE->getDecl())->hasLocalStorage() && - !DRE->getDecl()->hasAttr()) - return Cl::CM_NotBlockQualified; - } - // Assignment to a property in ObjC is an implicit setter access. But a // setter might not exist. if (const ObjCPropertyRefExpr *Expr = dyn_cast(E)) { @@ -579,8 +567,19 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, CanQualType CT = Ctx.getCanonicalType(E->getType()); // Const stuff is obviously not modifiable. - if (CT.isConstQualified()) + if (CT.isConstQualified()) { + // Special-case variables captured by blocks to get an improved + // diagnostic. + if (const DeclRefExpr *DRE = dyn_cast(E)) { + if (DRE->refersToEnclosingLocal() && + isa(DRE->getDecl()) && + cast(DRE->getDecl())->hasLocalStorage() && + !DRE->getDecl()->hasAttr()) + return Cl::CM_NotBlockQualified; + } return Cl::CM_ConstQualified; + } + // Arrays are not modifiable, only their elements are. if (CT->isArrayType()) return Cl::CM_ArrayType; diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp index 9d3f9b857f..99fc0caaf7 100644 --- a/test/SemaCXX/lambda-expressions.cpp +++ b/test/SemaCXX/lambda-expressions.cpp @@ -133,3 +133,9 @@ namespace NullPtr { } (); } } + +void PR12248() +{ + unsigned int result = 0; + auto l = [&]() { ++result; }; +}