From: Mike Stump Date: Fri, 17 Apr 2009 00:09:41 +0000 (+0000) Subject: Fixup semantic analysis for nested blocks, and allow block literal X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=397195bf3077fb42789b326f69f7d417227a0588;p=clang Fixup semantic analysis for nested blocks, and allow block literal expressions that can be of static duration to be returned. Radar 6786551 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69331 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 827f63cfcd..8e3a4212e0 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -872,8 +872,9 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, RetValExp = IcExpr->getSubExpr(); if (BlockExpr *C = dyn_cast_or_null(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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f903e8f253..e0d28fa140 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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 ArgTypes; for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i) ArgTypes.push_back(BSI->Params[i]->getType()); diff --git a/test/Sema/block-literal.c b/test/Sema/block-literal.c index 040c383033..2c1700a7b7 100644 --- a/test/Sema/block-literal.c +++ b/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/test/Sema/block-return.c b/test/Sema/block-return.c index d7717b38ca..3eee002b60 100644 --- a/test/Sema/block-return.c +++ b/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 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}} +}