diff options
| -rw-r--r-- | clang/include/clang/AST/Expr.h | 3 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticKinds.def | 2 | ||||
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 11 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 4 | ||||
| -rw-r--r-- | clang/test/Sema/block-literal.c | 17 |
5 files changed, 34 insertions, 3 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 1886053..9430b51 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -87,7 +87,8 @@ public: MLV_InvalidExpression, MLV_IncompleteType, MLV_ConstQualified, - MLV_ArrayType + MLV_ArrayType, + MLV_NotBlockQualified }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx) const; diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 5d4d893..cf4bf2a 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -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, diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 9c3d623..456b87b 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -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; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1a80283..e8b4d8c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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; diff --git a/clang/test/Sema/block-literal.c b/clang/test/Sema/block-literal.c index 235bb7e..3a09139 100644 --- a/clang/test/Sema/block-literal.c +++ b/clang/test/Sema/block-literal.c @@ -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() { |
