aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-12-03 23:53:56 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-12-03 23:53:56 +0000
commit649657e7d6c150136cae5ab22e39b9794cff80cc (patch)
tree40da8805502ae163345739a02c0ed6d62a00f589
parent14795c86f1c37874afa332a7b9bc18e6a02bf420 (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.cpp29
-rw-r--r--test/Sema/block-return.c4
-rw-r--r--test/SemaCXX/instantiate-blocks.cpp2
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}}
};
}