]> granicus.if.org Git - clang/commitdiff
Tweak Expr::isModifiableLvalue() and Expr::isLvalue() to better deal with BlockDeclRe...
authorSteve Naroff <snaroff@apple.com>
Fri, 26 Sep 2008 14:41:28 +0000 (14:41 +0000)
committerSteve Naroff <snaroff@apple.com>
Fri, 26 Sep 2008 14:41:28 +0000 (14:41 +0000)
This fixes <rdar://problem/6248392> clang: Error when using address of stack variable inside block.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56652 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/Basic/DiagnosticKinds.def
lib/AST/Expr.cpp
lib/Sema/SemaExpr.cpp
test/Sema/block-literal.c

index 18860534f1b86a7b00f060ef42837b1e67140088..9430b51dead893e926c8fe87558ba648c0b2ed2a 100644 (file)
@@ -87,7 +87,8 @@ public:
     MLV_InvalidExpression,
     MLV_IncompleteType,
     MLV_ConstQualified,
-    MLV_ArrayType
+    MLV_ArrayType,
+    MLV_NotBlockQualified
   };
   isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx) const;
   
index 5d4d8931745d295f4982b6c80ed6d8a8e9fb0610..cf4bf2a2358bfaa7d0d16000a976970273510592 100644 (file)
@@ -1036,6 +1036,8 @@ DIAG(err_typecheck_incomplete_type_not_modifiable_lvalue, ERROR,
 
 DIAG(err_typecheck_duplicate_vector_components_not_mlvalue, ERROR,
      "vector is not assignable (contains duplicate components)")
+DIAG(err_block_decl_ref_not_modifiable_lvalue, ERROR,
+     "variable is not assignable (missing __block type specifier)")
 DIAG(err_typecheck_call_not_function, ERROR,
      "called object is not a function or function pointer")
 DIAG(err_typecheck_call_too_few_args, ERROR,
index 9c3d623c163670ed10dc1c55038648069402f6f0..456b87b64e01d314f72ddcbfb78584d3962181be 100644 (file)
@@ -425,7 +425,7 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
   }
   case BlockDeclRefExprClass: {
     const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(this);
-    if (BDR->isByRef() && isa<VarDecl>(BDR->getDecl()))
+    if (isa<VarDecl>(BDR->getDecl()))
       return LV_Valid;
     break;
   }
@@ -497,6 +497,15 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue(ASTContext &Ctx) const {
     if (r->hasConstFields()) 
       return MLV_ConstQualified;
   }
+  // The following is illegal:
+  //   void takeclosure(void (^C)(void));
+  //   void func() { int x = 1; takeclosure(^{ x = 7 }); }
+  //
+  if (getStmtClass() == BlockDeclRefExprClass) {
+    const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(this);
+    if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl()))
+      return MLV_NotBlockQualified;
+  }
   return MLV_Valid;    
 }
 
index 1a80283f8263f8aaf3fa4d0cafead26fb8b49239..e8b4d8cb4b3f0131fd4f98c4bfb70531541c2177 100644 (file)
@@ -2181,6 +2181,10 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
     Diag(loc, diag::err_typecheck_duplicate_vector_components_not_mlvalue,
          lex->getSourceRange());
     return QualType();
+  case Expr::MLV_NotBlockQualified:
+    Diag(loc, diag::err_block_decl_ref_not_modifiable_lvalue,
+         lex->getSourceRange());
+    return QualType();
   }
 
   AssignConvertType ConvTy;
index 235bb7e23d0f8e2e2ca41541579cc51ef2564480..3a091395d04a3686dbb0596978091b01ca2c7f82 100644 (file)
@@ -39,7 +39,9 @@ void test2() {
        }
 
 foo:
-       takeclosure(^{ x = 4; });  // expected-error {{expression is not assignable}}
+       takeclosure(^{ x = 4; });  // expected-error {{variable is not assignable (missing __block type specifier)}}
+  __block y = 7;
+  takeclosure(^{ y = 8; });
 }
 
 
@@ -52,6 +54,19 @@ void test4() {
   void (*noop2)() = 0;
 }
 
+void myfunc(int (^block)(int)) {}
+
+void myfunc3(int *x);
+
+void test5() {
+    int a;
+
+    myfunc(^(int abcd) {
+        myfunc3(&a);
+        return 1;
+    });
+}
+
 void *X;
 
 void test_arguments() {