diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-12-03 23:53:56 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-12-03 23:53:56 +0000 |
commit | 649657e7d6c150136cae5ab22e39b9794cff80cc (patch) | |
tree | 40da8805502ae163345739a02c0ed6d62a00f589 | |
parent | 14795c86f1c37874afa332a7b9bc18e6a02bf420 (diff) |
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
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 29 | ||||
-rw-r--r-- | test/Sema/block-return.c | 4 | ||||
-rw-r--r-- | test/SemaCXX/instantiate-blocks.cpp | 2 |
3 files changed, 18 insertions, 17 deletions
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<BlockDeclRefExpr>(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 <typename T, typename T1> 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}} }; } |