]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGenObjC/arc-precise-lifetime.m
Vendor import of clang RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1):
[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: [[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? Yes! see // rdar://14990439
29 @property (nonatomic, readonly) char * PropertyReturnsInnerPointer __attribute__((objc_returns_inner_pointer));
30 @end
31 extern Test1 *test1_helper(void);
32
33 // CHECK-LABEL: define void @test1a()
34 void test1a(void) {
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];
54 }
55
56 // CHECK-LABEL: define void @test1b()
57 void test1b(void) {
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];
75 }
76
77 void test1c(void) {
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;
97 }
98
99 void test1d(void) {
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;
119 }
120
121 @interface Test2 {
122 @public
123   id ivar;
124 }
125 @end
126 // CHECK-LABEL:      define void @test2(
127 void test2(Test2 *x) {
128   x->ivar = 0;
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]],
134
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
144
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
148
149   // CHECK-NEXT: ret void
150 }
151
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]],
157
158   // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]]
159   // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
160   // CHECK-NOT:  imprecise_release
161
162   // CHECK-NEXT: ret void  
163 }
164
165 // CHECK: attributes [[NUW]] = { nounwind }