1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s 2 3#define PRECISE_LIFETIME __attribute__((objc_precise_lifetime)) 4 5id test0_helper(void) __attribute__((ns_returns_retained)); 6void test0() { 7 PRECISE_LIFETIME id x = test0_helper(); 8 x = 0; 9 // CHECK: [[X:%.*]] = alloca i8* 10 // CHECK-NEXT: [[CALL:%.*]] = call i8* @test0_helper() 11 // CHECK-NEXT: store i8* [[CALL]], i8** [[X]] 12 13 // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] 14 // CHECK-NEXT: store i8* null, i8** [[X]] 15 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]] 16 // CHECK-NOT: clang.imprecise_release 17 18 // CHECK-NEXT: [[T1:%.*]] = load i8** [[X]] 19 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]] 20 // CHECK-NOT: clang.imprecise_release 21 22 // CHECK-NEXT: ret void 23} 24 25// rdar://problem/9821110 26@interface Test1 27- (char*) interior __attribute__((objc_returns_inner_pointer)); 28// Should we allow this on properties? 29@end 30extern Test1 *test1_helper(void); 31 32// CHECK: define void @test1a() 33void test1a(void) { 34 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 35 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 36 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 37 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 38 // CHECK-NEXT: store [[TEST1]]* [[T3]] 39 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 40 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 41 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]]) 42 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 43 // CHECK-NEXT: [[T4:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ 44 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8* 45 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast 46 // CHECK-NEXT: store i8* [[T6]], i8** 47 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 48 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 49 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 50 // CHECK-NEXT: ret void 51 Test1 *ptr = test1_helper(); 52 char *c = [(ptr) interior]; 53} 54 55// CHECK: define void @test1b() 56void test1b(void) { 57 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper() 58 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 59 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) 60 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]* 61 // CHECK-NEXT: store [[TEST1]]* [[T3]] 62 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 63 // CHECK-NEXT: [[T1:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ 64 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 65 // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast 66 // CHECK-NEXT: store i8* [[T3]], i8** 67 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]** 68 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* 69 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]] 70 // CHECK-NOT: clang.imprecise_release 71 // CHECK-NEXT: ret void 72 __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper(); 73 char *c = [ptr interior]; 74} 75 76@interface Test2 { 77@public 78 id ivar; 79} 80@end 81// CHECK: define void @test2( 82void test2(Test2 *x) { 83 x->ivar = 0; 84 // CHECK: [[X:%.*]] = alloca [[TEST2:%.*]]* 85 // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST2]]* {{%.*}} to i8* 86 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]] 87 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST2]]* 88 // CHECK-NEXT: store [[TEST2]]* [[T2]], [[TEST2]]** [[X]], 89 90 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[X]], 91 // CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test2.ivar" 92 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* 93 // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8* [[T1]], i64 [[OFFSET]] 94 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8** 95 // CHECK-NEXT: [[T4:%.*]] = load i8** [[T3]], 96 // CHECK-NEXT: store i8* null, i8** [[T3]], 97 // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]] 98 // CHECK-NOT: imprecise 99 100 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[X]] 101 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8* 102 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release 103 104 // CHECK-NEXT: ret void 105} 106 107// CHECK: define void @test3(i8* 108void test3(PRECISE_LIFETIME id x) { 109 // CHECK: [[X:%.*]] = alloca i8*, 110 // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) [[NUW]] 111 // CHECK-NEXT: store i8* [[T0]], i8** [[X]], 112 113 // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] 114 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] 115 // CHECK-NOT: imprecise_release 116 117 // CHECK-NEXT: ret void 118} 119 120// CHECK: attributes [[NUW]] = { nounwind } 121