summaryrefslogtreecommitdiffstats
path: root/lib/AST/ExprClassification.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-03-12 20:57:19 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-03-12 20:57:19 +0000
commit71930e02730f3afecd6e71e4d6831b4a07436a7f (patch)
tree8f4c395ad236ade2799a37ffb4a053541578fdce /lib/AST/ExprClassification.cpp
parent9a0b6b4e2bf6a9ef41d32b4e83f2911981d2d44d (diff)
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
Diffstat (limited to 'lib/AST/ExprClassification.cpp')
-rw-r--r--lib/AST/ExprClassification.cpp25
1 files changed, 12 insertions, 13 deletions
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<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;