]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGenObjC/arc-precise-lifetime.m
Vendor import of clang trunk r238337:
[FreeBSD/FreeBSD.git] / test / CodeGenObjC / arc-precise-lifetime.m
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
5 id test0_helper(void) __attribute__((ns_returns_retained));
6 void test0() {
7   PRECISE_LIFETIME id x = test0_helper();
8   x = 0;
9   // CHECK:      [[X:%.*]] = alloca i8*
10   // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
11   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])
12   // CHECK-NEXT: [[CALL:%.*]] = call i8* @test0_helper()
13   // CHECK-NEXT: store i8* [[CALL]], i8** [[X]]
14
15   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
16   // CHECK-NEXT: store i8* null, i8** [[X]]
17   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]]
18   // CHECK-NOT:  clang.imprecise_release
19
20   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
21   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW:#[0-9]+]]
22   // CHECK-NOT:  clang.imprecise_release
23
24   // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
25   // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])
26   // CHECK-NEXT: ret void
27 }
28
29 // rdar://problem/9821110
30 @interface Test1
31 - (char*) interior __attribute__((objc_returns_inner_pointer));
32 // Should we allow this on properties? Yes! see // rdar://14990439
33 @property (nonatomic, readonly) char * PropertyReturnsInnerPointer __attribute__((objc_returns_inner_pointer));
34 @end
35 extern Test1 *test1_helper(void);
36
37 // CHECK-LABEL: define void @test1a()
38 void test1a(void) {
39   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
40   // CHECK:      [[C:%.*]] = alloca i8*, align 8
41   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
42   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
43   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
44   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
45   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
46   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
47   // CHECK-NEXT: store [[TEST1]]* [[T3]]
48   // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
49   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
50   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
51   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
52   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
53   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
54   // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
55   // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
56   // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
57   // CHECK-NEXT: store i8* [[T6]], i8**
58   // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
59   // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
60   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
61   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
62   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
63   // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
64   // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
65   // CHECK-NEXT: ret void
66   Test1 *ptr = test1_helper();
67   char *c = [(ptr) interior];
68 }
69
70 // CHECK-LABEL: define void @test1b()
71 void test1b(void) {
72   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
73   // CHECK:      [[C:%.*]] = alloca i8*, align 8
74   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
75   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
76   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
77   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
78   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
79   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
80   // CHECK-NEXT: store [[TEST1]]* [[T3]]
81   // CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
82   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
83   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
84   // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
85   // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
86   // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast
87   // CHECK-NEXT: store i8* [[T3]], i8**
88   // CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
89   // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
90   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
91   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
92   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
93   // CHECK-NOT:  clang.imprecise_release
94   // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
95   // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
96   // CHECK-NEXT: ret void
97   __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();
98   char *c = [ptr interior];
99 }
100
101 void test1c(void) {
102   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
103   // CHECK:      [[PC:%.*]] = alloca i8*, align 8
104   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
105   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
106   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
107   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
108   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
109   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
110   // CHECK-NEXT: store [[TEST1]]* [[T3]]
111   // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
112   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
113   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
114   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
115   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
116   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
117   // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
118   // CHECK-NEXT: [[T5:%.*]] = bitcast [[TEST1]]* [[T3]] to i8*
119   // CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
120   // CHECK-NEXT: store i8* [[T6]], i8**
121   // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
122   // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
123   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
124   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
125   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
126   // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
127   // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
128   // CHECK-NEXT: ret void
129   Test1 *ptr = test1_helper();
130   char *pc = ptr.PropertyReturnsInnerPointer;
131 }
132
133 void test1d(void) {
134   // CHECK:      [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
135   // CHECK:      [[PC:%.*]] = alloca i8*, align 8
136   // CHECK:      [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
137   // CHECK:      call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
138   // CHECK:      [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
139   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
140   // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
141   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
142   // CHECK-NEXT: store [[TEST1]]* [[T3]]
143   // CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
144   // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
145   // CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
146   // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
147   // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease
148   // CHECK-NEXT: [[SIX:%.*]] = bitcast i8* [[T3]] to [[TEST1]]*
149   // CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
150   // CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[SIX]] to i8*
151   // CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]])
152   // CHECK-NEXT: store i8* [[CALL1]], i8**
153   // CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
154   // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
155   // CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]**
156   // CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*
157   // CHECK-NEXT: call void @objc_release(i8* [[TEN]])
158   // CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
159   // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
160   // CHECK-NEXT: ret void
161   __attribute__((objc_precise_lifetime)) Test1 *ptr = test1_helper();
162   char *pc = ptr.PropertyReturnsInnerPointer;
163 }
164
165 @interface Test2 {
166 @public
167   id ivar;
168 }
169 @end
170 // CHECK-LABEL:      define void @test2(
171 void test2(Test2 *x) {
172   x->ivar = 0;
173   // CHECK:      [[X:%.*]] = alloca [[TEST2:%.*]]*
174   // CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST2]]* {{%.*}} to i8*
175   // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]]
176   // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST2]]*
177   // CHECK-NEXT: store [[TEST2]]* [[T2]], [[TEST2]]** [[X]],
178
179   // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]*, [[TEST2]]** [[X]],
180   // CHECK-NEXT: [[OFFSET:%.*]] = load i64, i64* @"OBJC_IVAR_$_Test2.ivar"
181   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8*
182   // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8, i8* [[T1]], i64 [[OFFSET]]
183   // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8**
184   // CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[T3]],
185   // CHECK-NEXT: store i8* null, i8** [[T3]],
186   // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]]
187   // CHECK-NOT:  imprecise
188
189   // CHECK-NEXT: [[T0:%.*]] = load [[TEST2]]*, [[TEST2]]** [[X]]
190   // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST2]]* [[T0]] to i8*
191   // CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
192
193   // CHECK-NEXT: ret void
194 }
195
196 // CHECK-LABEL:      define void @test3(i8*
197 void test3(PRECISE_LIFETIME id x) {
198   // CHECK:      [[X:%.*]] = alloca i8*,
199   // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) [[NUW]]
200   // CHECK-NEXT: store i8* [[T0]], i8** [[X]],
201
202   // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
203   // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
204   // CHECK-NOT:  imprecise_release
205
206   // CHECK-NEXT: ret void  
207 }
208
209 // CHECK: attributes [[NUW]] = { nounwind }