From: John McCall Date: Fri, 11 Nov 2011 03:19:12 +0000 (+0000) Subject: Be sure to insulate block literals from any cleanups in their X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=538773cbfbba03b85d931efe122b743b7b0cc60d;p=clang Be sure to insulate block literals from any cleanups in their enclosing full-expressions. It is somewhat amazing that this hasn't come up as a problem before. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144362 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bc422db8b9..a5b766ad73 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -8615,6 +8615,10 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) { PushDeclContext(CurScope, Block); else CurContext = Block; + + // Enter a new evaluation context to insulate the block from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext(PotentiallyEvaluated); } void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { @@ -8742,6 +8746,10 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { /// ActOnBlockError - If there is an error parsing a block, this callback /// is invoked to pop the information about the block from the action impl. void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { + // Leave the expression-evaluation context. + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + // Pop off CurBlock, handle nested blocks. PopDeclContext(); PopFunctionOrBlockScope(); @@ -8755,6 +8763,10 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (!LangOpts.Blocks) Diag(CaretLoc, diag::err_blocks_disable); + // Leave the expression-evaluation context. + assert(!ExprNeedsCleanups && "cleanups within block not correctly bound!"); + PopExpressionEvaluationContext(); + BlockScopeInfo *BSI = cast(FunctionScopes.back()); PopDeclContext(); diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp index 40faf1bf23..921d94a138 100644 --- a/test/CodeGenCXX/blocks.cpp +++ b/test/CodeGenCXX/blocks.cpp @@ -178,3 +178,28 @@ namespace test5 { // CHECK: call void @_ZN5test51AD1Ev([[A]]* [[X]]) // CHECK-NEXT: ret void } + +namespace test6 { + struct A { + A(); + ~A(); + }; + + void foo(const A &, void (^)()); + void bar(); + + void test() { + // Make sure that the temporary cleanup isn't somehow captured + // within the block. + foo(A(), ^{ bar(); }); + bar(); + } + + // CHECK: define void @_ZN5test64testEv() + // CHECK: [[TEMP:%.*]] = alloca [[A:%.*]], align 1 + // CHECK-NEXT: call void @_ZN5test61AC1Ev([[A]]* [[TEMP]]) + // CHECK-NEXT: call void @_ZN5test63fooERKNS_1AEU13block_pointerFvvE( + // CHECK-NEXT: call void @_ZN5test61AD1Ev([[A]]* [[TEMP]]) + // CHECK-NEXT: call void @_ZN5test63barEv() + // CHECK-NEXT: ret void +}