diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 5 | ||||
-rw-r--r-- | clang/test/Sema/block-literal.c | 4 | ||||
-rw-r--r-- | clang/test/Sema/block-return.c | 13 |
4 files changed, 21 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 827f63cfcd4..8e3a4212e05 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -872,8 +872,9 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, RetValExp = IcExpr->getSubExpr(); if (BlockExpr *C = dyn_cast_or_null<BlockExpr>(RetValExp)) - Diag(C->getLocStart(), diag::err_ret_local_block) - << C->getSourceRange(); + if (C->hasBlockDeclRefExprs()) + Diag(C->getLocStart(), diag::err_ret_local_block) + << C->getSourceRange(); } // Perform checking for stack values returned by reference. else if (lhsType->isReferenceType()) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f903e8f2535..e0d28fa140e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4774,6 +4774,11 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (BSI->ReturnType) RetTy = QualType(BSI->ReturnType, 0); + // A reference in a nested block, winds up being a reference in the outer + // block. + if (CurBlock) + CurBlock->hasBlockDeclRefExprs |= BSI->hasBlockDeclRefExprs; + llvm::SmallVector<QualType, 8> ArgTypes; for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i) ArgTypes.push_back(BSI->Params[i]->getType()); diff --git a/clang/test/Sema/block-literal.c b/clang/test/Sema/block-literal.c index 040c383033b..2c1700a7b71 100644 --- a/clang/test/Sema/block-literal.c +++ b/clang/test/Sema/block-literal.c @@ -21,7 +21,7 @@ T somefunction() { I(^{ }); - return ^{printf("\nClosure\n"); }; // expected-error {{returning block that lives on the local stack}} + return ^{printf("\nClosure\n"); }; } void test2() { int x = 4; @@ -46,7 +46,7 @@ foo: void (^test3())(void) { - return ^{}; // expected-error {{returning block that lives on the local stack}} + return ^{}; } void test4() { diff --git a/clang/test/Sema/block-return.c b/clang/test/Sema/block-return.c index d7717b38ca3..3eee002b603 100644 --- a/clang/test/Sema/block-return.c +++ b/clang/test/Sema/block-return.c @@ -41,13 +41,13 @@ CL foo() { return 2; // expected-warning {{incompatible integer to pointer conversion returning 'int', expected 'char *'}} }; - return ^{ return 1; }; // expected-warning {{incompatible block pointer types returning 'int (^)(void)', expected 'CL'}} expected-error {{returning block that lives on the local stack}} + return ^{ return 1; }; // expected-warning {{incompatible block pointer types returning 'int (^)(void)', expected 'CL'}} } typedef int (^CL2)(void); CL2 foo2() { - return ^{ return 1; }; // expected-error {{returning block that lives on the local stack}} + return ^{ return 1; }; } typedef unsigned int * uintptr_t; @@ -83,3 +83,12 @@ void foo4() { int (^nested)(char *s) = ^(char *str) { void (^nest)(void) = ^(void) { printf("%s\n", str); }; next(); return 1; }; // expected-warning{{implicitly declaring C library function 'printf' with type 'int (char const *, ...)'}} \ // expected-note{{please include the header <stdio.h> or explicitly provide a declaration for 'printf'}} } + +typedef void (^bptr)(void); + +bptr foo5(int j) { + __block int i; + if (j) + return ^{ ^{ i=0; }(); }; // expected-error {{returning block that lives on the local stack}} + return ^{ i=0; }; // expected-error {{returning block that lives on the local stack}} +} |