aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2009-04-29 21:40:37 +0000
committerMike Stump <mrs@apple.com>2009-04-29 21:40:37 +0000
commit6c92fa75e62937f9738696840efcb258560f4568 (patch)
tree35b9cd76fa5c10c396c07f8ab37fdb18eab83d1b
parent298862dbcc0313766c8d2e25f836b62efcc75c51 (diff)
Fixup Sema and CodeGen for block literal attributes when the return
type and argument types are missing, and let return type deduction happen before we give errors for returning from a noreturn block. Radar 6441502 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70413 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Parse/ParseExpr.cpp4
-rw-r--r--lib/Sema/SemaExpr.cpp3
-rw-r--r--lib/Sema/SemaStmt.cpp13
-rw-r--r--test/Sema/block-return.c3
4 files changed, 14 insertions, 9 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 1f37532d71..c0a0aad175 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1291,6 +1291,10 @@ void Parser::ParseBlockId() {
Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
ParseDeclarator(DeclaratorInfo);
+ // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes.
+ DeclaratorInfo.AddAttributes(DS.TakeAttributes(),
+ SourceLocation());
+
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
AttributeList *AttrList = ParseAttributes(&Loc);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 5d16d77f9f..99ed741120 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4722,6 +4722,8 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
assert(ParamInfo.getIdentifier() == 0 && "block-id should have no identifier!");
+ ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo);
+
if (ParamInfo.getNumTypeObjects() == 0
|| ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) {
QualType T = GetTypeForDeclarator(ParamInfo, CurScope);
@@ -4773,7 +4775,6 @@ 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 e44aeb7557..fff7a44bc4 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -706,13 +706,6 @@ 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) {
@@ -726,6 +719,12 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
QualType FnRetType = QualType(CurBlock->ReturnType, 0);
+ if (CurBlock->TheDecl->hasAttr<NoReturnAttr>()) {
+ Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr)
+ << getCurFunctionOrMethodDecl()->getDeclName();
+ return StmtError();
+ }
+
// Otherwise, verify that this result type matches the previous one. We are
// pickier with blocks than for normal functions because we don't have GCC
// compatibility to worry about here.
diff --git a/test/Sema/block-return.c b/test/Sema/block-return.c
index 4a32a97a5d..e1a3cfd812 100644
--- a/test/Sema/block-return.c
+++ b/test/Sema/block-return.c
@@ -97,7 +97,8 @@ 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));
+ int (^b)(int) __attribute__((noreturn));
b = ^ (int i) __attribute__((noreturn)) { return 1; }; // expected-error {{block declared 'noreturn' should not return}}
b(1);
+ int (^c)(void) __attribute__((noreturn)) = ^ __attribute__((noreturn)) { return 100; }; // expected-error {{block declared 'noreturn' should not return}}
}