diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-12-03 17:47:53 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-12-03 17:47:53 +0000 |
commit | 0586520acb2f368c874943353a222be7f00c3068 (patch) | |
tree | 911cefdbb13174380fcbbcaf49a285de44bee01c /lib | |
parent | 4d604d6f1d413864e7dad8e368ba9a69a3f478c7 (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.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 2 |
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; |