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
3 #define PRECISE_LIFETIME __attribute__((objc_precise_lifetime))
5 id test0_helper(void) __attribute__((ns_returns_retained));
7 PRECISE_LIFETIME id x = test0_helper();
9 // CHECK: [[X:%.*]] = alloca i8*
10 // CHECK-NEXT: [[CALL:%.*]] = call i8* @test0_helper()
11 // CHECK-NEXT: store i8* [[CALL]], i8** [[X]]
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
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
22 // CHECK-NEXT: ret void
25 // rdar://problem/9821110
27 - (char*) interior __attribute__((objc_returns_inner_pointer));
28 // Should we allow this on properties? Yes! see // rdar://14990439
29 @property (nonatomic, readonly) char * PropertyReturnsInnerPointer __attribute__((objc_returns_inner_pointer));
31 extern Test1 *test1_helper(void);
33 // CHECK-LABEL: define void @test1a()
35 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
36 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
37 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
38 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
39 // CHECK-NEXT: store [[TEST1]]* [[T3]]
40 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]**
41 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
42 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
43 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
44 // CHECK-NEXT: [[T4:%.*]] = load i8** @OBJC_SELECTOR_REFERENCES_
45 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
46 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
47 // CHECK-NEXT: store i8* [[T6]], i8**
48 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]**
49 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
50 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
51 // CHECK-NEXT: ret void
52 Test1 *ptr = test1_helper();
53 char *c = [(ptr) interior];
56 // CHECK-LABEL: define void @test1b()
58 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
59 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
60 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
61 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
62 // CHECK-NEXT: store [[TEST1]]* [[T3]]
63 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]**
64 // CHECK-NEXT: [[T1:%.*]] = load i8** @OBJC_SELECTOR_REFERENCES_
65 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
66 // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast
67 // CHECK-NEXT: store i8* [[T3]], i8**
68 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]**
69 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
70 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
71 // CHECK-NOT: clang.imprecise_release
72 // CHECK-NEXT: ret void
73 __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();
74 char *c = [ptr interior];
78 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
79 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
80 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
81 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
82 // CHECK-NEXT: store [[TEST1]]* [[T3]]
83 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]**
84 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
85 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
86 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
87 // CHECK-NEXT: [[T4:%.*]] = load i8** @OBJC_SELECTOR_REFERENCES_
88 // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
89 // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
90 // CHECK-NEXT: store i8* [[T6]], i8**
91 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]**
92 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
93 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
94 // CHECK-NEXT: ret void
95 Test1 *ptr = test1_helper();
96 char *pc = ptr.PropertyReturnsInnerPointer;
100 // CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
101 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
102 // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
103 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
104 // CHECK-NEXT: store [[TEST1]]* [[T3]]
105 // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]**
106 // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
107 // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease
108 // CHECK-NEXT: [[SIX:%.*]] = bitcast i8* [[T3]] to [[TEST1]]*
109 // CHECK-NEXT: [[SEVEN:%.*]] = load i8** @OBJC_SELECTOR_REFERENCES_
110 // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[SIX]] to i8*
111 // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]])
112 // CHECK-NEXT: store i8* [[CALL1]], i8**
113 // CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]**
114 // CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*
115 // CHECK-NEXT: call void @objc_release(i8* [[TEN]])
116 // CHECK-NEXT: ret void
117 __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();
118 char *pc = ptr.PropertyReturnsInnerPointer;
126 // CHECK-LABEL: define void @test2(
127 void test2(Test2 *x) {
129 // CHECK: [[X:%.*]] = alloca [[TEST2:%.*]]*
130 // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST2]]* {{%.*}} to i8*
131 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]]
132 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST2]]*
133 // CHECK-NEXT: store [[TEST2]]* [[T2]], [[TEST2]]** [[X]],
135 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[X]],
136 // CHECK-NEXT: [[OFFSET:%.*]] = load i64* @"OBJC_IVAR_$_Test2.ivar"
137 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8*
138 // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8* [[T1]], i64 [[OFFSET]]
139 // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8**
140 // CHECK-NEXT: [[T4:%.*]] = load i8** [[T3]],
141 // CHECK-NEXT: store i8* null, i8** [[T3]],
142 // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]]
143 // CHECK-NOT: imprecise
145 // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]** [[X]]
146 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8*
147 // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
149 // CHECK-NEXT: ret void
152 // CHECK-LABEL: define void @test3(i8*
153 void test3(PRECISE_LIFETIME id x) {
154 // CHECK: [[X:%.*]] = alloca i8*,
155 // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) [[NUW]]
156 // CHECK-NEXT: store i8* [[T0]], i8** [[X]],
158 // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]]
159 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
160 // CHECK-NOT: imprecise_release
162 // CHECK-NEXT: ret void
165 // CHECK: attributes [[NUW]] = { nounwind }