1*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -fblocks -g -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s 2*f4a2713aSLionel Sambuc// 3*f4a2713aSLionel Sambuc// Test that debug location is generated for a captured "self" inside 4*f4a2713aSLionel Sambuc// a block. 5*f4a2713aSLionel Sambuc// 6*f4a2713aSLionel Sambuc// This test is split into two parts, this one for the frontend, and 7*f4a2713aSLionel Sambuc// then llvm/test/DebugInfo/debug-info-block-captured-self.ll to 8*f4a2713aSLionel Sambuc// ensure that DW_AT_location is generated for the captured self. 9*f4a2713aSLionel Sambuc@class T; 10*f4a2713aSLionel Sambuc@interface S 11*f4a2713aSLionel Sambuc@end 12*f4a2713aSLionel Sambuc@interface Mode 13*f4a2713aSLionel Sambuc-(int) count; 14*f4a2713aSLionel Sambuc@end 15*f4a2713aSLionel Sambuc@interface Context 16*f4a2713aSLionel Sambuc@end 17*f4a2713aSLionel Sambuc@interface ViewController 18*f4a2713aSLionel Sambuc@property (nonatomic, readwrite, strong) Context *context; 19*f4a2713aSLionel Sambuc@end 20*f4a2713aSLionel Sambuctypedef enum { 21*f4a2713aSLionel Sambuc Unknown = 0, 22*f4a2713aSLionel Sambuc} State; 23*f4a2713aSLionel Sambuc@interface Main : ViewController 24*f4a2713aSLionel Sambuc{ 25*f4a2713aSLionel Sambuc T * t1; 26*f4a2713aSLionel Sambuc T * t2; 27*f4a2713aSLionel Sambuc} 28*f4a2713aSLionel Sambuc@property(readwrite, nonatomic) State state; 29*f4a2713aSLionel Sambuc@end 30*f4a2713aSLionel Sambuc@implementation Main 31*f4a2713aSLionel Sambuc- (id) initWithContext:(Context *) context 32*f4a2713aSLionel Sambuc{ 33*f4a2713aSLionel Sambuc t1 = [self.context withBlock:^(id obj){ 34*f4a2713aSLionel Sambuc id *mode1; 35*f4a2713aSLionel Sambuc t2 = [mode1 withBlock:^(id object){ 36*f4a2713aSLionel Sambuc Mode *mode2 = object; 37*f4a2713aSLionel Sambuc if ([mode2 count] != 0) { 38*f4a2713aSLionel Sambuc self.state = 0; 39*f4a2713aSLionel Sambuc } 40*f4a2713aSLionel Sambuc }]; 41*f4a2713aSLionel Sambuc }]; 42*f4a2713aSLionel Sambuc} 43*f4a2713aSLionel Sambuc@end 44*f4a2713aSLionel Sambuc// The important part of this test is that there is a dbg.value 45*f4a2713aSLionel Sambuc// intrinsic associated with the implicit .block_descriptor argument 46*f4a2713aSLionel Sambuc// of the block. We also test that this value gets alloca'd, so the 47*f4a2713aSLionel Sambuc// register llocator won't accidentally kill it. 48*f4a2713aSLionel Sambuc 49*f4a2713aSLionel Sambuc// outer block: 50*f4a2713aSLionel Sambuc// CHECK: define internal void {{.*}}_block_invoke{{.*}} 51*f4a2713aSLionel Sambuc 52*f4a2713aSLionel Sambuc// inner block: 53*f4a2713aSLionel Sambuc// CHECK: define internal void {{.*}}_block_invoke{{.*}} 54*f4a2713aSLionel Sambuc// CHECK: %[[MEM1:.*]] = alloca i8*, align 8 55*f4a2713aSLionel Sambuc// CHECK-NEXT: %[[MEM2:.*]] = alloca i8*, align 8 56*f4a2713aSLionel Sambuc// CHECK: store i8* [[BLOCK_DESC:%.*]], i8** %[[MEM1]], align 8 57*f4a2713aSLionel Sambuc// CHECK: %[[TMP0:.*]] = load i8** %[[MEM1]] 58*f4a2713aSLionel Sambuc// CHECK: call void @llvm.dbg.value(metadata !{i8* %[[TMP0]]}, i64 0, metadata ![[BDMD:[0-9]+]]) 59*f4a2713aSLionel Sambuc// CHECK: call void @llvm.dbg.declare(metadata !{i8* [[BLOCK_DESC]]}, metadata ![[BDMD:[0-9]+]]) 60*f4a2713aSLionel Sambuc// CHECK: %[[TMP1:.*]] = bitcast 61*f4a2713aSLionel Sambuc// CHECK-NEXT: store 62*f4a2713aSLionel Sambuc// CHECK: call void @llvm.dbg.declare(metadata !{<{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** {{.*}}}, metadata ![[SELF:.*]]) 63*f4a2713aSLionel Sambuc// make sure we are still in the same function 64*f4a2713aSLionel Sambuc// CHECK: define {{.*}}__copy_helper_block_ 65*f4a2713aSLionel Sambuc// Metadata 66*f4a2713aSLionel Sambuc// CHECK: ![[MAIN:.*]] = {{.*}}!"Main"{{.*}}DW_TAG_structure_type{{.*}}line 23 67*f4a2713aSLionel Sambuc// CHECK: ![[PMAIN:.*]] = {{.*}}![[MAIN]]} ; [ DW_TAG_pointer_type ]{{.*}}from Main 68*f4a2713aSLionel Sambuc// CHECK: ![[BDMD]] = metadata {{.*}}.block_descriptor 69*f4a2713aSLionel Sambuc// CHECK: ![[SELF]] = {{.*}}![[PMAIN]]{{.*}}[ DW_TAG_auto_variable ] [self] [line 40] 70