From: Fariborz Jahanian Date: Sat, 3 Dec 2011 23:53:56 +0000 (+0000) Subject: Move block return type inference diagnostic to a common place where X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=649657e7d6c150136cae5ab22e39b9794cff80cc;p=clang Move block return type inference diagnostic to a common place where Function or array lvalue conversions happens. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145782 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 1255695016..2325711b29 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1760,7 +1760,8 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If this is the first return we've seen in the block, infer the type of // the block from it. BlockScopeInfo *CurBlock = getCurBlock(); - if (CurBlock->ReturnType.isNull()) { + if (CurBlock->TheDecl->blockMissingReturnType()) { + QualType BlockReturnT; if (RetValExp) { // Don't call UsualUnaryConversions(), since we don't want to do // integer promotions here. @@ -1770,7 +1771,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { RetValExp = Result.take(); if (!RetValExp->isTypeDependent()) { - CurBlock->ReturnType = RetValExp->getType(); + BlockReturnT = RetValExp->getType(); if (BlockDeclRefExpr *CDRE = dyn_cast(RetValExp)) { // We have to remove a 'const' added to copied-in variable which was // part of the implementation spec. and not the actual qualifier for @@ -1779,9 +1780,19 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { CurBlock->ReturnType.removeLocalConst(); // FIXME: local??? } } else - CurBlock->ReturnType = Context.DependentTy; + BlockReturnT = Context.DependentTy; } else - CurBlock->ReturnType = Context.VoidTy; + BlockReturnT = Context.VoidTy; + if (!CurBlock->ReturnType.isNull() && !CurBlock->ReturnType->isDependentType() + && !BlockReturnT->isDependentType() + // when block's return type is not specified, all return types + // must strictly match. + && !Context.hasSameType(BlockReturnT, CurBlock->ReturnType)) { + Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) + << BlockReturnT << CurBlock->ReturnType; + return StmtError(); + } + CurBlock->ReturnType = BlockReturnT; } QualType FnRetType = CurBlock->ReturnType; @@ -1809,16 +1820,6 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } else if (!RetValExp) { return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr)); } else if (!RetValExp->isTypeDependent()) { - if (CurBlock->TheDecl->blockMissingReturnType()) { - // when block's return type is not specified, all return types - // must strictly match. - if (Context.getCanonicalType(FnRetType) != - Context.getCanonicalType(RetValExp->getType())) { - Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) - << RetValExp->getType() << FnRetType; - return StmtError(); - } - } // we have a non-void block with an expression, continue checking // C99 6.8.6.4p3(136): The return statement is not an assignment. The diff --git a/test/Sema/block-return.c b/test/Sema/block-return.c index 293967fea1..70fb3e104e 100644 --- a/test/Sema/block-return.c +++ b/test/Sema/block-return.c @@ -9,14 +9,14 @@ CL foo() { CL X = ^{ if (2) return; - return 1; // expected-error {{void block should not return a value}} + return 1; // expected-error {{return type 'int' must match previous return type 'void' when block literal has unspecified explicit return type}} }; int (^Y) (void) = ^{ if (3) return 1; else - return; // expected-error {{non-void block should return a value}} + return; // expected-error {{return type 'void' must match previous return type 'int' when block literal has unspecified explicit return type}} }; char *(^Z)(void) = ^{ diff --git a/test/SemaCXX/instantiate-blocks.cpp b/test/SemaCXX/instantiate-blocks.cpp index 799951a0ae..bb0f8d881d 100644 --- a/test/SemaCXX/instantiate-blocks.cpp +++ b/test/SemaCXX/instantiate-blocks.cpp @@ -19,7 +19,7 @@ template void noret(T t, T1 r) if (1) return t; else if (2) - return r; // expected-error {{return type 'const double' must match previous return type 'float' when block literal has unspecified explicit return type}} + return r; // expected-error {{return type 'double' must match previous return type 'float' when block literal has unspecified explicit return type}} }; }