diff options
Diffstat (limited to 'test/CodeGenObjC/debug-info-block-captured-self.m')
-rw-r--r-- | test/CodeGenObjC/debug-info-block-captured-self.m | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/test/CodeGenObjC/debug-info-block-captured-self.m b/test/CodeGenObjC/debug-info-block-captured-self.m new file mode 100644 index 0000000..0316013 --- /dev/null +++ b/test/CodeGenObjC/debug-info-block-captured-self.m @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fblocks -g -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s +// +// Test that debug location is generated for a captured "self" inside +// a block. +// +// This test is split into two parts, this one for the frontend, and +// then llvm/test/DebugInfo/debug-info-block-captured-self.ll to +// ensure that DW_AT_location is generated for the captured self. +@class T; +@interface S +@end +@interface Mode +-(int) count; +@end +@interface Context +@end +@interface ViewController +@property (nonatomic, readwrite, strong) Context *context; +@end +typedef enum { + Unknown = 0, +} State; +@interface Main : ViewController +{ + T * t1; + T * t2; +} +@property(readwrite, nonatomic) State state; +@end +@implementation Main +- (id) initWithContext:(Context *) context +{ + t1 = [self.context withBlock:^(id obj){ + id *mode1; + t2 = [mode1 withBlock:^(id object){ + Mode *mode2 = object; + if ([mode2 count] != 0) { + self.state = 0; + } + }]; + }]; +} +@end +// The important part of this test is that there is a dbg.value +// intrinsic associated with the implicit .block_descriptor argument +// of the block. We also test that this value gets alloca'd, so the +// register llocator won't accidentally kill it. + +// outer block: +// CHECK: define internal void {{.*}}_block_invoke{{.*}} + +// inner block: +// CHECK: define internal void {{.*}}_block_invoke{{.*}} +// CHECK: %[[MEM1:.*]] = alloca i8*, align 8 +// CHECK-NEXT: %[[MEM2:.*]] = alloca i8*, align 8 +// CHECK: store i8* [[BLOCK_DESC:%.*]], i8** %[[MEM1]], align 8 +// CHECK: %[[TMP0:.*]] = load i8** %[[MEM1]] +// CHECK: call void @llvm.dbg.value(metadata !{i8* %[[TMP0]]}, i64 0, metadata ![[BDMD:[0-9]+]]) +// CHECK: call void @llvm.dbg.declare(metadata !{i8* [[BLOCK_DESC]]}, metadata ![[BDMD:[0-9]+]]) +// CHECK: %[[TMP1:.*]] = bitcast +// CHECK-NEXT: store +// CHECK-NEXT: %[[TMP2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[TMP1]] +// CHECK: call void @llvm.dbg.declare(metadata !{<{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** {{.*}}}, metadata ![[SELF:.*]]) +// make sure we are still in the same function +// CHECK: define {{.*}}__copy_helper_block_ +// Metadata +// CHECK: ![[MAIN:.*]] = {{.*}}!"Main"{{.*}}DW_TAG_structure_type{{.*}}line 23 +// CHECK: ![[PMAIN:.*]] = {{.*}}![[MAIN]]} ; [ DW_TAG_pointer_type ]{{.*}}from Main +// CHECK: ![[BDMD]] = metadata {{.*}}.block_descriptor +// CHECK: ![[SELF]] = {{.*}}![[PMAIN]]{{.*}}[ DW_TAG_auto_variable ] [self] [line 40] |