From 19c30c00e5e01e4608a43c7deb504f343f09e46d Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Wed, 29 Apr 2009 19:03:13 +0000 Subject: [PATCH] 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 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ lib/Parse/ParseExpr.cpp | 21 +++++++++++++++++++++ lib/Sema/SemaDeclAttr.cpp | 11 +++++++---- lib/Sema/SemaExpr.cpp | 1 + lib/Sema/SemaStmt.cpp | 6 ++++++ test/Sema/block-return.c | 6 ++++++ 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(d)) { + ValueDecl *VD = dyn_cast(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()) { + 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); +} -- 2.40.0