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
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<ImplicitCastExpr>(RetValExp))
+ RetValExp = IcExpr->getSubExpr();
+
if (BlockExpr *C = dyn_cast_or_null<BlockExpr>(RetValExp))
Diag(C->getLocStart(), diag::err_ret_local_block,
C->getSourceRange());
// 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);
}
--- /dev/null
+// 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}}
+}