]> granicus.if.org Git - clang/commitdiff
Move block return type inference diagnostic to a common place where
authorFariborz Jahanian <fjahanian@apple.com>
Sat, 3 Dec 2011 23:53:56 +0000 (23:53 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Sat, 3 Dec 2011 23:53:56 +0000 (23:53 +0000)
Function or array lvalue conversions happens.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145782 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaStmt.cpp
test/Sema/block-return.c
test/SemaCXX/instantiate-blocks.cpp

index 1255695016d7d718d68408dc8770a8fdfe081764..2325711b29c3114b35b379d6b9f9b5bd397f0204 100644 (file)
@@ -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
index 293967fea172848bd6bfac87a7b1a5d12a4b1ee4..70fb3e104e9e246bba9b7acbc1bbd82da436c2ef 100644 (file)
@@ -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) = ^{
index 799951a0aeadce2f74dbbaf13ad5e59e96b1a71a..bb0f8d881d366ce9f7251f02ebe6d84152b18805 100644 (file)
@@ -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}}
   };
 }