diff options
author | John McCall <rjmccall@apple.com> | 2011-11-11 03:19:12 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-11-11 03:19:12 +0000 |
commit | 538773cbfbba03b85d931efe122b743b7b0cc60d (patch) | |
tree | 5a601e4c9c9bd5e4459e5a2695ea2a5aaadc52c4 | |
parent | d7df785e8ba3284c66c1a05537f9e1c8cc27d252 (diff) |
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
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 12 | ||||
-rw-r--r-- | test/CodeGenCXX/blocks.cpp | 25 |
2 files changed, 37 insertions, 0 deletions
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<BlockScopeInfo>(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 +} |