]> granicus.if.org Git - clang/commitdiff
Make sure we treat variables captured by reference in lambda as modifiable lvalues...
authorEli Friedman <eli.friedman@gmail.com>
Mon, 12 Mar 2012 20:57:19 +0000 (20:57 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 12 Mar 2012 20:57:19 +0000 (20:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152573 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprClassification.cpp
test/SemaCXX/lambda-expressions.cpp

index 3261eb6974dac2404e227ae71979739d3a501dd0..6697c9d7da6039e724dbfd9544acb694f1b09503 100644 (file)
@@ -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;
index 9d3f9b857f322c2b9ee92c5da27cda708d5acece..99fc0caaf7a4f92cc8593bbf6b4e6ff6014c3dfa 100644 (file)
@@ -133,3 +133,9 @@ namespace NullPtr {
     } ();
   }
 }
+
+void PR12248()
+{
+  unsigned int result = 0;
+  auto l = [&]() { ++result; };
+}