From: Steve Naroff Date: Tue, 16 Sep 2008 22:25:10 +0000 (+0000) Subject: Sema::ActOnBlockReturnStmt(): Need to perform the UsualUnaryConversions on the return... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c50a4a5f2eac14ac4c631d50b0a55cadc87700ce;p=clang Sema::ActOnBlockReturnStmt(): Need to perform the UsualUnaryConversions on the return type. Sema::CheckReturnStackAddr(): Make sure we skip over implicit casts. Added some more test cases... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56254 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 00b469b7c0..f870e26b6a 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -716,7 +716,12 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, Diag(DR->getLocStart(), diag::warn_ret_stack_addr, DR->getDecl()->getIdentifier()->getName(), RetValExp->getSourceRange()); - + + // Skip over implicit cast expressions when checking for block expressions. + if (ImplicitCastExpr *IcExpr = + dyn_cast_or_null(RetValExp)) + RetValExp = IcExpr->getSubExpr(); + if (BlockExpr *C = dyn_cast_or_null(RetValExp)) Diag(C->getLocStart(), diag::err_ret_local_block, C->getSourceRange()); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index d7a812cb2a..3cadd526a7 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -678,9 +678,10 @@ 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. if (CurBlock->ReturnType == 0) { - if (RetValExp) + if (RetValExp) { + UsualUnaryConversions(RetValExp); CurBlock->ReturnType = RetValExp->getType().getTypePtr(); - else + } else CurBlock->ReturnType = Context.VoidTy.getTypePtr(); return new ReturnStmt(ReturnLoc, RetValExp); } diff --git a/test/Sema/block-return.c b/test/Sema/block-return.c new file mode 100644 index 0000000000..93511dbd7e --- /dev/null +++ b/test/Sema/block-return.c @@ -0,0 +1,52 @@ +// RUN: clang -fsyntax-only %s -verify + +typedef void (^CL)(void); + +CL foo() { + + short y; + + short (^add1)(void) = ^{ return y+1; }; // expected-error {{incompatible block pointer types initializing 'int (^)(void)', expected 'short (^)(void)'}} + + CL X = ^{ + if (2) + return; + return 1; // expected-error {{void block should not return a value}} + }; + int (^Y) (void) = ^{ + if (3) + return 1; + else + return; // expected-error {{non-void block should return a value}} + }; + + char *(^Z)(void) = ^{ + if (3) + return ""; + else + return (char*)0; + }; + + double (^A)(void) = ^ { // expected-error {{incompatible block pointer types initializing 'float (^)(void)', expected 'double (^)(void)'}} + if (1) + return (float)1.0; + else + if (2) + return (double)2.0; // expected-error {{incompatible type returning 'double', expected 'float'}} + return 1; // expected-error {{incompatible type returning 'int', expected 'float'}} + }; + + char *(^B)(void) = ^{ + if (3) + return ""; + else + return 2; // expected-error {{incompatible type returning 'int', expected 'char *'}} + }; + return ^{ return 1; }; // expected-error {{incompatible block pointer types returning 'int (^)(void)', expected 'CL'}} expected-error {{returning block that lives on the local stack}} +} + +typedef int (^CL2)(void); + +CL2 foo2() { + return ^{ return 1; }; // expected-error {{returning block that lives on the local stack}} +}