aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/Expr.h3
-rw-r--r--clang/include/clang/Basic/DiagnosticKinds.def2
-rw-r--r--clang/lib/AST/Expr.cpp11
-rw-r--r--clang/lib/Sema/SemaExpr.cpp4
-rw-r--r--clang/test/Sema/block-literal.c17
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() {