copy/dispose helper functions
We found out that these fake functions would cause clang to crash if the
changes proposed in https://reviews.llvm.org/D98799 were made.
The original patch was reverted in f681fd927e
because debug locations were missing in the body of the block byref
helper functions. This patch fixes the bug by calling CreateArtificial
after the calls to StartFunction.
Differential Revision: https://reviews.llvm.org/D104082
84 lines
3.0 KiB
Objective-C
84 lines
3.0 KiB
Objective-C
// RUN: %clang_cc1 -emit-llvm -fblocks -debug-info-kind=limited -triple x86_64-apple-darwin10 -fobjc-dispatch-method=mixed -x objective-c < %s -o - | FileCheck %s
|
|
|
|
// rdar://problem/9279956
|
|
// Test that we generate the proper debug location for a captured self.
|
|
// The second half of this test is in llvm/tests/DebugInfo/debug-info-blocks.ll
|
|
|
|
// CHECK: define {{.*}}_block_invoke
|
|
// CHECK: %[[BLOCK:.*]] = bitcast i8* %.block_descriptor to <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>*, !dbg
|
|
// CHECK-NEXT: store <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[BLOCK]], <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA:.*]], align
|
|
// CHECK-NEXT: call void @llvm.dbg.declare(metadata <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA]], metadata ![[SELF:[0-9]+]], metadata !{{.*}})
|
|
// CHECK-NEXT: call void @llvm.dbg.declare(metadata %1** %d, metadata ![[D:[0-9]+]], metadata !{{.*}})
|
|
|
|
// Test that we do emit scope info for the helper functions, and that the
|
|
// parameters to these functions are marked as artificial (so the debugger
|
|
// doesn't accidentally step into the function).
|
|
// CHECK: define {{.*}} @__copy_helper_block_{{.*}}(i8* %0, i8* %1)
|
|
// CHECK-NOT: ret
|
|
// CHECK: call {{.*}}, !dbg ![[DBG_LINE:[0-9]+]]
|
|
// CHECK-NOT: ret
|
|
// CHECK: load {{.*}}, !dbg ![[DBG_LINE]]
|
|
// CHECK: ret {{.*}}, !dbg ![[DBG_LINE]]
|
|
// CHECK: define {{.*}} @__destroy_helper_block_{{.*}}(i8*
|
|
// CHECK-NOT: ret
|
|
// CHECK: load {{.*}}, !dbg ![[DESTROY_LINE:[0-9]+]]
|
|
// CHECK: ret {{.*}}, !dbg ![[DESTROY_LINE]]
|
|
|
|
// CHECK-DAG: [[DBG_LINE]] = !DILocation(line: 0, scope: ![[COPY_SP:[0-9]+]])
|
|
// CHECK-DAG: [[COPY_SP]] = distinct !DISubprogram(linkageName: "__copy_helper_block_
|
|
// CHECK-DAG: [[DESTROY_LINE]] = !DILocation(line: 0, scope: ![[DESTROY_SP:[0-9]+]])
|
|
// CHECK-DAG: [[DESTROY_SP]] = distinct !DISubprogram(linkageName: "__destroy_helper_block_
|
|
typedef unsigned int NSUInteger;
|
|
|
|
@protocol NSObject
|
|
@end
|
|
|
|
@interface NSObject <NSObject>
|
|
- (id)init;
|
|
+ (id)alloc;
|
|
@end
|
|
|
|
@interface NSDictionary : NSObject
|
|
- (NSUInteger)count;
|
|
@end
|
|
|
|
@interface NSMutableDictionary : NSDictionary
|
|
@end
|
|
|
|
@interface A : NSObject {
|
|
@public
|
|
int ivar;
|
|
}
|
|
@end
|
|
|
|
static void run(void (^block)(void))
|
|
{
|
|
block();
|
|
}
|
|
|
|
@implementation A
|
|
|
|
- (id)init
|
|
{
|
|
if ((self = [super init])) {
|
|
// CHECK-DAG: !DILocalVariable(arg: 1, scope: ![[COPY_SP]], {{.*}}, flags: DIFlagArtificial)
|
|
// CHECK-DAG: !DILocalVariable(arg: 2, scope: ![[COPY_SP]], {{.*}}, flags: DIFlagArtificial)
|
|
// CHECK-DAG: !DILocalVariable(arg: 1, scope: ![[DESTROY_SP]], {{.*}}, flags: DIFlagArtificial)
|
|
run(^{
|
|
// CHECK-DAG: ![[SELF]] = !DILocalVariable(name: "self", scope:{{.*}}, line: [[@LINE+4]],
|
|
// CHECK-DAG: ![[D]] = !DILocalVariable(name: "d", scope:{{.*}}, line: [[@LINE+1]],
|
|
NSMutableDictionary *d = [[NSMutableDictionary alloc] init];
|
|
ivar = 42 + (int)[d count];
|
|
});
|
|
}
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|
|
int main()
|
|
{
|
|
A *a = [[A alloc] init];
|
|
return 0;
|
|
}
|