aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-12-03 17:47:53 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-12-03 17:47:53 +0000
commit0586520acb2f368c874943353a222be7f00c3068 (patch)
tree911cefdbb13174380fcbbcaf49a285de44bee01c /lib
parent4d604d6f1d413864e7dad8e368ba9a69a3f478c7 (diff)
If block literal return type is not specified, return type of the block is
inferred from return types. All the return statements have to agree about the type. // rdar://10466373 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145774 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/SemaExpr.cpp4
-rw-r--r--lib/Sema/SemaStmt.cpp12
-rw-r--r--lib/Sema/TreeTransform.h2
3 files changed, 16 insertions, 2 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 1e9f319d4f..cc94050a6f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -8715,8 +8715,10 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
// return type. TODO: what should we do with declarators like:
// ^ * { ... }
// If the answer is "apply template argument deduction"....
- if (RetTy != Context.DependentTy)
+ if (RetTy != Context.DependentTy) {
CurBlock->ReturnType = RetTy;
+ CurBlock->TheDecl->setBlockMissingReturnType(false);
+ }
// Push block parameters from the declarator if we had them.
SmallVector<ParmVarDecl*, 8> Params;
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index e8a61044b5..1255695016 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -1809,6 +1809,16 @@ 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
@@ -1820,7 +1830,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
FnRetType,
- NRVOCandidate != 0);
+ NRVOCandidate != 0);
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
FnRetType, RetValExp);
if (Res.isInvalid()) {
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index d7bdbafaba..3dc8136b78 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -8118,6 +8118,8 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
// in above, CapturesCXXThis need be set here from the block
// expression.
blockScope->CapturesCXXThis = oldBlock->capturesCXXThis();
+ blockScope->TheDecl->setBlockMissingReturnType(
+ oldBlock->blockMissingReturnType());
SmallVector<ParmVarDecl*, 4> params;
SmallVector<QualType, 4> paramTypes;