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) {
/// 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();
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();
// 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
+}