diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-03-12 20:57:19 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-03-12 20:57:19 +0000 |
commit | 60226ea0d75dbd644e8c2f54e9c44abc3a3c9c17 (patch) | |
tree | 861046f6a4251284060ef22a3696507d0b31e1c3 /clang/lib/AST/ExprClassification.cpp | |
parent | 5ad914038b094aa1c14758b41d1a7d4522f3b910 (diff) |
Make sure we treat variables captured by reference in lambda as modifiable lvalues. Regression from r152491. Fixes PR12248.
llvm-svn: 152573
Diffstat (limited to 'clang/lib/AST/ExprClassification.cpp')
-rw-r--r-- | clang/lib/AST/ExprClassification.cpp | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 3261eb6974da..6697c9d7da60 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/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<DeclRefExpr>(E)) { - if (DRE->refersToEnclosingLocal() && - isa<VarDecl>(DRE->getDecl()) && - cast<VarDecl>(DRE->getDecl())->hasLocalStorage() && - !DRE->getDecl()->hasAttr<BlocksAttr>()) - 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<ObjCPropertyRefExpr>(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<DeclRefExpr>(E)) { + if (DRE->refersToEnclosingLocal() && + isa<VarDecl>(DRE->getDecl()) && + cast<VarDecl>(DRE->getDecl())->hasLocalStorage() && + !DRE->getDecl()->hasAttr<BlocksAttr>()) + return Cl::CM_NotBlockQualified; + } return Cl::CM_ConstQualified; + } + // Arrays are not modifiable, only their elements are. if (CT->isArrayType()) return Cl::CM_ArrayType; |