// RUN: %clang_cc1 -fblocks -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -DDEAD_CODE -fblocks -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s typedef void (^BlockTy)(); void escapeFunc(BlockTy); typedef void (^BlockTy)(); void noEscapeFunc(__attribute__((noescape)) BlockTy); // Verify that the desired DIExpression are generated for escaping (i.e, not // 'noescape') blocks. void test_escape_func() { // CHECK-LABEL: void @test_escape_func // CHECK: call void @llvm.dbg.declare({{.*}}metadata ![[ESCAPE_VAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}){{.*}}) __block int escape_var; // Blocks in dead code branches still capture __block variables. #ifdef DEAD_CODE if (0) #endif escapeFunc(^{ (void)escape_var; }); } // Verify that the desired DIExpression are generated for noescape blocks. void test_noescape_func() { // CHECK-LABEL: void @test_noescape_func // CHECK: call void @llvm.dbg.declare({{.*}}metadata ![[NOESCAPE_VAR:[0-9]+]], metadata !DIExpression()) __block int noescape_var; noEscapeFunc(^{ (void)noescape_var; }); } // Verify that the desired DIExpression are generated for blocks. void test_local_block() { // CHECK-LABEL: void @test_local_block // CHECK: call void @llvm.dbg.declare({{.*}}metadata ![[BLOCK_VAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}){{.*}}) __block int block_var; // CHECK-LABEL: @__test_local_block_block_invoke // CHECK: call void @llvm.dbg.declare({{.*}}!DIExpression(DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}){{.*}}) ^ { block_var = 1; }(); } // Verify that the desired DIExpression are generated for __block vars not used // in any block. void test_unused() { // CHECK-LABEL: void @test_unused // CHECK: call void @llvm.dbg.declare({{.*}}metadata ![[UNUSED_VAR:[0-9]+]], metadata !DIExpression()) __block int unused_var; // Use i (not inside a block). ++unused_var; } // CHECK: ![[ESCAPE_VAR]] = !DILocalVariable(name: "escape_var" // CHECK: ![[NOESCAPE_VAR]] = !DILocalVariable(name: "noescape_var" // CHECK: ![[BLOCK_VAR]] = !DILocalVariable(name: "block_var" // CHECK: ![[UNUSED_VAR]] = !DILocalVariable(name: "unused_var"