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

llvm-svn: 145774
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 1e9f319..cc94050 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -8715,8 +8715,10 @@
   // 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/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index e8a6104..1255695 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -1809,6 +1809,16 @@
   } 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 @@
     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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index d7bdbaf..3dc8136 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -8118,6 +8118,8 @@
   // 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;