aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2009-04-29 19:03:13 +0000
committerMike Stump <mrs@apple.com>2009-04-29 19:03:13 +0000
commit19c30c00e5e01e4608a43c7deb504f343f09e46d (patch)
tree562016df236e451dc15aca58efc9e30c47bf89f2
parentc887d13b07d72c8e67d1a73a82d3167e866f50e5 (diff)
Sema and CodeGen support for attributes on blocks. Radar 6441502
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70403 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Parse/ParseExpr.cpp21
-rw-r--r--lib/Sema/SemaDeclAttr.cpp11
-rw-r--r--lib/Sema/SemaExpr.cpp1
-rw-r--r--lib/Sema/SemaStmt.cpp6
-rw-r--r--test/Sema/block-return.c6
6 files changed, 43 insertions, 4 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 6fcdff96e0..6604ddef36 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1609,6 +1609,8 @@ def ext_return_has_void_expr : Extension<
"void %select{function|method}1 %0 should not return void expression">;
def err_noreturn_function_has_return_expr : Error<
"function %0 declared 'noreturn' should not return">;
+def err_noreturn_block_has_return_expr : Error<
+ "block declared 'noreturn' should not return">;
def err_shufflevector_non_vector : Error<
"first two arguments to __builtin_shufflevector must be vectors">;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index f299c5246e..1f37532d71 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1290,6 +1290,13 @@ void Parser::ParseBlockId() {
// Parse the block-declarator.
Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
ParseDeclarator(DeclaratorInfo);
+
+ if (Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseAttributes(&Loc);
+ DeclaratorInfo.AddAttributes(AttrList, Loc);
+ }
+
// Inform sema that we are starting a block.
Actions.ActOnBlockArguments(DeclaratorInfo, CurScope);
}
@@ -1345,6 +1352,13 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
Actions.ActOnBlockError(CaretLoc, CurScope);
return ExprError();
}
+
+ if (Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseAttributes(&Loc);
+ ParamInfo.AddAttributes(AttrList, Loc);
+ }
+
// Inform sema that we are starting a block.
Actions.ActOnBlockArguments(ParamInfo, CurScope);
} else if (!Tok.is(tok::l_brace)) {
@@ -1357,6 +1371,13 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
false, false, 0, 0,
CaretLoc, ParamInfo),
CaretLoc);
+
+ if (Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseAttributes(&Loc);
+ ParamInfo.AddAttributes(AttrList, Loc);
+ }
+
// Inform sema that we are starting a block.
Actions.ActOnBlockArguments(ParamInfo, CurScope);
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 9e550ba44f..2df4e36cc9 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -408,10 +408,13 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
return false;
}
- if (!isFunctionOrMethod(d)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << attrName << 0 /*function*/;
- return false;
+ if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) {
+ ValueDecl *VD = dyn_cast<ValueDecl>(d);
+ if (VD == 0 || !VD->getType()->isBlockPointerType()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << attrName << 0 /*function*/;
+ return false;
+ }
}
return true;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index dcc0311f60..5d16d77f9f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4773,6 +4773,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
}
CurBlock->TheDecl->setParams(Context, &CurBlock->Params[0],
CurBlock->Params.size());
+ ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo);
for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
E = CurBlock->TheDecl->param_end(); AI != E; ++AI)
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 311496c720..e44aeb7557 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -707,6 +707,12 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
Action::OwningStmtResult
Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
+ if (CurBlock->TheDecl->hasAttr<NoReturnAttr>()) {
+ Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr)
+ << getCurFunctionOrMethodDecl()->getDeclName();
+ return StmtError();
+ }
+
// If this is the first return we've seen in the block, infer the type of
// the block from it.
if (CurBlock->ReturnType == 0) {
diff --git a/test/Sema/block-return.c b/test/Sema/block-return.c
index 4b0dbb0b01..4a32a97a5d 100644
--- a/test/Sema/block-return.c
+++ b/test/Sema/block-return.c
@@ -95,3 +95,9 @@ bptr foo5(int j) {
int (*funcptr3[5])(long);
int sz8 = sizeof(^int (*[5])(long) {return funcptr3;}); // expected-error {{block declared as returning an array}}
+
+void foo6() {
+ void (^b)(int) __attribute__((noreturn));
+ b = ^ (int i) __attribute__((noreturn)) { return 1; }; // expected-error {{block declared 'noreturn' should not return}}
+ b(1);
+}