diff options
author | Adrian Prantl <aprantl@apple.com> | 2013-05-02 17:30:20 +0000 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2013-05-02 17:30:20 +0000 |
commit | fa6b079b1231366696f6a497c6a084c73a35c85d (patch) | |
tree | 302668355094ed5d183c591e7fb9f529f451e715 /test/CodeGenObjC | |
parent | d4147c4b2d4eba0327658f36c5a2c63f2d234991 (diff) |
Ensure that the line table for functions with cleanups is sequential.
If there is cleanup code, the cleanup code gets the debug location of
the closing '}'. The subsequent ret IR-instruction does not get a
debug location. The return _expression_ will get the debug location
of the return statement.
If the function contains only a single, simple return statement,
the cleanup code may become the first breakpoint in the function.
In this case we set the debug location for the cleanup code
to the location of the return statement.
rdar://problem/13442648
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180932 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenObjC')
-rw-r--r-- | test/CodeGenObjC/arc-linetable.m | 101 | ||||
-rw-r--r-- | test/CodeGenObjC/debug-info-block-line.m | 11 |
2 files changed, 108 insertions, 4 deletions
diff --git a/test/CodeGenObjC/arc-linetable.m b/test/CodeGenObjC/arc-linetable.m new file mode 100644 index 0000000000..eac91f1889 --- /dev/null +++ b/test/CodeGenObjC/arc-linetable.m @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -emit-llvm -fblocks -fobjc-arc -g -triple x86_64-apple-darwin10 %s -o - | FileCheck %s + +// Legend: EXP = Return expression, RET = ret instruction + +// CHECK: define {{.*}}testNoSideEffect +// CHECK: call void @objc_storeStrong{{.*}} +// CHECK: call void @objc_storeStrong{{.*}} !dbg ![[ARC1:[0-9]+]] +// CHECK: ret {{.*}} !dbg ![[RET1:[0-9]+]] + +// CHECK: define {{.*}}testNoCleanup +// CHECK: ret {{.*}} !dbg ![[RET2:[0-9]+]] + +// CHECK: define {{.*}}testSideEffect +// CHECK: @objc_msgSend{{.*}} !dbg ![[MSG3:[0-9]+]] +// CHECK: ret {{.*}} !dbg ![[RET3:[0-9]+]] + +// CHECK: define {{.*}}testMultiline +// CHECK: @objc_msgSend{{.*}} !dbg ![[MSG4:[0-9]+]] +// CHECK: load{{.*}} !dbg ![[EXP4:[0-9]+]] +// CHECK: ret {{.*}} !dbg ![[RET4:[0-9]+]] + +// CHECK: define {{.*}}testVoid +// CHECK: call void @objc_storeStrong{{.*}} +// CHECK: call void @objc_storeStrong{{.*}} !dbg ![[ARC5:[0-9]+]] +// CHECK: ret {{.*}} !dbg ![[RET5:[0-9]+]] + +// CHECK: define {{.*}}testVoidNoReturn +// CHECK: @objc_msgSend{{.*}} !dbg ![[MSG6:[0-9]+]] +// CHECK: ret {{.*}} !dbg ![[RET6:[0-9]+]] + +// CHECK: define {{.*}}testNoCleanupSideEffect +// CHECK: @objc_msgSend{{.*}} !dbg ![[MSG7:[0-9]+]] +// CHECK: ret {{.*}} !dbg ![[RET7:[0-9]+]] + + +@interface NSObject ++ (id)alloc; +- (id)init; +- (id)retain; +@end + +@class NSString; + +@interface AppDelegate : NSObject + +@end + +@implementation AppDelegate : NSObject + +- (int)testNoSideEffect:(NSString *)foo { + // CHECK: ![[ARC1]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return 1; // Return expression + // CHECK: ![[RET1]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} +} // Cleanup + Ret + +- (int)testNoCleanup { + // CHECK: ![[RET2]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return 1; +} + +- (int)testSideEffect:(NSString *)foo { + // CHECK: ![[MSG3]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return [self testNoSideEffect :foo]; + // CHECK: ![[RET3]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} +} + +- (int)testMultiline:(NSString *)foo { + // CHECK: ![[MSG4]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + int r = [self testSideEffect :foo]; + // CHECK: ![[EXP4]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return r; + // CHECK: ![[RET4]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} +} + +- (void)testVoid:(NSString *)foo { + // CHECK: ![[ARC5]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return; + // CHECK: ![[RET5]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} +} + +- (void)testVoidNoReturn:(NSString *)foo { + // CHECK: ![[MSG6]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + [self testVoid :foo]; + // CHECK: ![[RET6]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} +} + +- (int)testNoCleanupSideEffect { + // CHECK: ![[MSG7]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + [self testVoid :@"foo"]; + // CHECK: ![[RET7]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return 1; +} + + +@end + + +int main(int argc, const char** argv) { + AppDelegate *o = [[AppDelegate alloc] init]; + return [o testMultiline :@"foo"]; +} diff --git a/test/CodeGenObjC/debug-info-block-line.m b/test/CodeGenObjC/debug-info-block-line.m index c913a972e1..2192575bb7 100644 --- a/test/CodeGenObjC/debug-info-block-line.m +++ b/test/CodeGenObjC/debug-info-block-line.m @@ -64,13 +64,16 @@ typedef enum : NSUInteger { // CHECK: define internal void @"__39-[TServer serverConnection:getCommand:]_block_invoke" // CHECK: call void @objc_storeStrong(i8** [[ZERO:%.*]], i8* [[ONE:%.*]]) [[NUW:#[0-9]+]] // CHECK: call void @objc_storeStrong(i8** [[TWO:%.*]], i8* [[THREE:%.*]]) [[NUW]] +// CHECK: call {{.*}}@objc_msgSend{{.*}}, !dbg ![[LINE_ABOVE:[0-9]+]] +// CHECK: getelementptr +// CHECK-NOT: !dbg, ![[LINE_ABOVE]] // CHECK: bitcast %5** [[TMP:%.*]] to i8** -// CHECK: call void @objc_storeStrong(i8** [[VAL1:%.*]], i8* null) [[NUW]], !dbg ![[MD1:.*]] -// CHECK: bitcast %4** [[TMP:%.*]] to i8** -// CHECK: call void @objc_storeStrong(i8** [[VAL2:%.*]], i8* null) [[NUW]], !dbg ![[MD1]] +// CHECK-NOT: !dbg, ![[LINE_ABOVE]] +// CHECK: call void @objc_storeStrong(i8** [[VAL1:%.*]], i8* null) [[NUW]] +// CHECK-NEXT: bitcast %4** [[TMP:%.*]] to i8** +// CHECK-NEXT: call void @objc_storeStrong(i8** [[VAL2:%.*]], i8* null) [[NUW]] // CHECK-NEXT: ret // CHECK: attributes [[NUW]] = { nounwind } -// CHECK: ![[MD1]] = metadata !{i32 87 [map dataWithCompletionBlock:^(NSData *data, NSError *error) { if (data) { NSString *encoded = [[data compressedData] encodedString:18]; |