Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -1244,17 +1244,30 @@ return emission; } +static bool isCapturedBy(const VarDecl &, const Expr *); + +/// Determines whether the given __block variable is potentially +/// captured by the given statement. +static bool isCapturedBy(const VarDecl &Var, const Stmt *S) { + if (const Expr *E = dyn_cast(S)) + return isCapturedBy(Var, E); + for (const Stmt *SubStmt : S->children()) + if (isCapturedBy(Var, SubStmt)) + return true; + return false; +} + /// Determines whether the given __block variable is potentially /// captured by the given expression. -static bool isCapturedBy(const VarDecl &var, const Expr *e) { +static bool isCapturedBy(const VarDecl &Var, const Expr *E) { // Skip the most common kinds of expressions that make // hierarchy-walking expensive. - e = e->IgnoreParenCasts(); + E = E->IgnoreParenCasts(); - if (const BlockExpr *be = dyn_cast(e)) { - const BlockDecl *block = be->getBlockDecl(); - for (const auto &I : block->captures()) { - if (I.getVariable() == &var) + if (const BlockExpr *BE = dyn_cast(E)) { + const BlockDecl *Block = BE->getBlockDecl(); + for (const auto &I : Block->captures()) { + if (I.getVariable() == &Var) return true; } @@ -1262,19 +1275,19 @@ return false; } - if (const StmtExpr *SE = dyn_cast(e)) { + if (const StmtExpr *SE = dyn_cast(E)) { const CompoundStmt *CS = SE->getSubStmt(); for (const auto *BI : CS->body()) - if (const auto *E = dyn_cast(BI)) { - if (isCapturedBy(var, E)) - return true; + if (const auto *BIE = dyn_cast(BI)) { + if (isCapturedBy(Var, BIE)) + return true; } else if (const auto *DS = dyn_cast(BI)) { // special case declarations for (const auto *I : DS->decls()) { if (const auto *VD = dyn_cast((I))) { const Expr *Init = VD->getInit(); - if (Init && isCapturedBy(var, Init)) + if (Init && isCapturedBy(Var, Init)) return true; } } @@ -1286,8 +1299,8 @@ return false; } - for (const Stmt *SubStmt : e->children()) - if (isCapturedBy(var, cast(SubStmt))) + for (const Stmt *SubStmt : E->children()) + if (isCapturedBy(Var, SubStmt)) return true; return false; Index: test/CodeGenCXX/block-capture.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/block-capture.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -x c++ -std=c++11 -fblocks -emit-llvm %s -o - | FileCheck %s + +// CHECK: %struct.__block_byref_baz = type { i8*, %struct.__block_byref_baz*, i32, i32, i32 } +// CHECK: [[baz:%[0-9a-z_]*]] = alloca %struct.__block_byref_baz +// CHECK: [[bazref:%[0-9a-z_\.]*]] = getelementptr inbounds %struct.__block_byref_baz, %struct.__block_byref_baz* [[baz]], i32 0, i32 1 +// CHECK: store %struct.__block_byref_baz* [[baz]], %struct.__block_byref_baz** [[bazref]] +// CHECK: [[disposable:%[0-9a-z_]*]] = bitcast %struct.__block_byref_baz* [[baz]] to i8* +// CHECK: call void @_Block_object_dispose(i8* [[disposable]] + +int main() { + __block int baz = [&]() { return 0; }(); + return 0; +}