1 | // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -std=c++11 -emit-llvm -debug-info-kind=limited -o - | FileCheck %s |
2 | |
3 | class S { |
4 | public: |
5 | S& operator = (const S&); |
6 | S (const S&); |
7 | S (); |
8 | }; |
9 | |
10 | struct CGRect { |
11 | CGRect & operator = (const CGRect &); |
12 | }; |
13 | |
14 | @interface I { |
15 | S position; |
16 | CGRect bounds; |
17 | } |
18 | |
19 | @property(assign, nonatomic) S position; |
20 | @property CGRect bounds; |
21 | @property CGRect frame; |
22 | - (void)setFrame:(CGRect)frameRect; |
23 | - (CGRect)frame; |
24 | - (void) initWithOwner; |
25 | - (CGRect)extent; |
26 | - (void)dealloc; |
27 | @end |
28 | |
29 | @implementation I |
30 | @synthesize position; |
31 | @synthesize bounds; |
32 | @synthesize frame; |
33 | |
34 | // CHECK: define internal void @"\01-[I setPosition:]" |
35 | // CHECK: call dereferenceable({{[0-9]+}}) %class.S* @_ZN1SaSERKS_ |
36 | // CHECK-NEXT: ret void |
37 | |
38 | // Don't attach debug locations to the prologue instructions. These were |
39 | // leaking over from the previous function emission by accident. |
40 | // CHECK: define internal void @"\01-[I setBounds:]"({{.*}} { |
41 | // CHECK-NOT: !dbg |
42 | // CHECK: call void @llvm.dbg.declare |
43 | - (void)setFrame:(CGRect)frameRect {} |
44 | - (CGRect)frame {return bounds;} |
45 | |
46 | - (void)initWithOwner { |
47 | I* _labelLayer; |
48 | CGRect labelLayerFrame = self.bounds; |
49 | labelLayerFrame = self.bounds; |
50 | _labelLayer.frame = labelLayerFrame; |
51 | } |
52 | |
53 | // rdar://8366604 |
54 | - (void)dealloc |
55 | { |
56 | CGRect cgrect = self.extent; |
57 | } |
58 | - (struct CGRect)extent {return bounds;} |
59 | |
60 | @end |
61 | |
62 | // CHECK-LABEL: define i32 @main |
63 | // CHECK: call void @_ZN1SC1ERKS_(%class.S* [[AGGTMP:%[a-zA-Z0-9\.]+]], %class.S* dereferenceable({{[0-9]+}}) {{%[a-zA-Z0-9\.]+}}) |
64 | // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %class.S*)*)(i8* {{%[a-zA-Z0-9\.]+}}, i8* {{%[a-zA-Z0-9\.]+}}, %class.S* [[AGGTMP]]) |
65 | // CHECK-NEXT: ret i32 0 |
66 | int main() { |
67 | I *i; |
68 | S s1; |
69 | i.position = s1; |
70 | return 0; |
71 | } |
72 | |
73 | // rdar://8379892 |
74 | // CHECK-LABEL: define void @_Z1fP1A |
75 | // CHECK: call void @_ZN1XC1Ev(%struct.X* [[LVTEMP:%[a-zA-Z0-9\.]+]]) |
76 | // CHECK: call void @_ZN1XC1ERKS_(%struct.X* [[AGGTMP:%[a-zA-Z0-9\.]+]], %struct.X* dereferenceable({{[0-9]+}}) [[LVTEMP]]) |
77 | // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %struct.X*)*)({{.*}} %struct.X* [[AGGTMP]]) |
78 | struct X { |
79 | X(); |
80 | X(const X&); |
81 | ~X(); |
82 | }; |
83 | |
84 | @interface A { |
85 | X xval; |
86 | } |
87 | - (X)x; |
88 | - (void)setX:(X)x; |
89 | @end |
90 | |
91 | void f(A* a) { |
92 | a.x = X(); |
93 | } |
94 | |
95 | // rdar://21801088 |
96 | // Ensure that pseudo-objecet expressions that require the RHS to be |
97 | // rewritten don't result in crashes or redundant emission of code. |
98 | struct B0 { long long x; }; |
99 | struct B1 { long long x; }; B1 operator+(B1, B1); |
100 | struct B2 { B1 x; }; |
101 | struct B3 { B3(); B1 x; operator B1(); }; |
102 | @interface B |
103 | @property B0 b0; |
104 | @property B1 b1; |
105 | @property B2 b2; |
106 | @property B3 b3; |
107 | @end |
108 | |
109 | int b_makeInt(); |
110 | |
111 | // Note that there's a promotion from int to long long, so |
112 | // the syntactic form of the RHS will be bogus. |
113 | void testB0(B *b) { |
114 | b.b0 = { b_makeInt() }; |
115 | } |
116 | void testB1(B *b) { |
117 | b.b1 += { b_makeInt() }; |
118 | } |
119 | // CHECK: define void @_Z6testB0P1B([[B:%.*]]* |
120 | // CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 |
121 | // CHECK: [[TEMP:%.*]] = alloca [[B0:%.*]], align 8 |
122 | // CHECK: [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0 |
123 | // CHECK-NEXT: [[T0:%.*]] = call i32 @_Z9b_makeIntv() |
124 | // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64 |
125 | // CHECK-NEXT: store i64 [[T1]], i64* [[X]], align 8 |
126 | // CHECK: load [[B]]*, [[B]]** [[BVAR]] |
127 | // CHECK-NOT: call |
128 | // CHECK: call void @llvm.memcpy |
129 | // CHECK-NOT: call |
130 | // CHECK: call void bitcast {{.*}} @objc_msgSend |
131 | // CHECK-NOT: call |
132 | // CHECK: ret void |
133 | |
134 | // CHECK: define void @_Z6testB1P1B([[B]]* |
135 | // CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 |
136 | // CHECK: load [[B]]*, [[B]]** [[BVAR]] |
137 | // CHECK-NOT: call |
138 | // CHECK: [[T0:%.*]] = call i64 bitcast {{.*}} @objc_msgSend |
139 | // CHECK-NOT: call |
140 | // CHECK: store i64 [[T0]], |
141 | // CHECK-NOT: call |
142 | // CHECK: [[T0:%.*]] = call i32 @_Z9b_makeIntv() |
143 | // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64 |
144 | // CHECK-NEXT: store i64 [[T1]], i64* {{.*}}, align 8 |
145 | // CHECK-NOT: call |
146 | // CHECK: [[T0:%.*]] = call i64 @_Zpl2B1S_ |
147 | // CHECK-NOT: call |
148 | // CHECK: store i64 [[T0]], |
149 | // CHECK-NOT: call |
150 | // CHECK: call void @llvm.memcpy |
151 | // CHECK-NOT: call |
152 | // CHECK: call void bitcast {{.*}} @objc_msgSend |
153 | // CHECK-NOT: call |
154 | // CHECK: ret void |
155 | |
156 | // Another example of a conversion that needs to be applied |
157 | // in the semantic form. |
158 | void testB2(B *b) { |
159 | b.b2 = { B3() }; |
160 | } |
161 | |
162 | // CHECK: define void @_Z6testB2P1B([[B]]* |
163 | // CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 |
164 | // CHECK: call void @llvm.dbg.declare( |
165 | // CHECK: call void @_ZN2B3C1Ev( |
166 | // CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev( |
167 | // CHECK-NOT: call |
168 | // CHECK: store i64 [[T0]], |
169 | // CHECK: load [[B]]*, [[B]]** [[BVAR]] |
170 | // CHECK-NOT: call |
171 | // CHECK: call void @llvm.memcpy |
172 | // CHECK-NOT: call |
173 | // CHECK: call void bitcast {{.*}} @objc_msgSend |
174 | // CHECK-NOT: call |
175 | // CHECK: ret void |
176 | |
177 | // A similar test to B, but using overloaded function references. |
178 | struct C1 { |
179 | int x; |
180 | friend C1 operator+(C1, void(&)()); |
181 | }; |
182 | @interface C |
183 | @property void (*c0)(); |
184 | @property C1 c1; |
185 | @end |
186 | |
187 | void c_helper(); |
188 | void c_helper(int); |
189 | |
190 | void testC0(C *c) { |
191 | c.c0 = c_helper; |
192 | c.c0 = &c_helper; |
193 | } |
194 | // CHECK: define void @_Z6testC0P1C([[C:%.*]]* |
195 | // CHECK: [[CVAR:%.*]] = alloca [[C]]*, align 8 |
196 | // CHECK: load [[C]]*, [[C]]** [[CVAR]] |
197 | // CHECK-NOT: call |
198 | // CHECK: call void bitcast {{.*}} @objc_msgSend {{.*}} @_Z8c_helperv |
199 | // CHECK-NOT: call |
200 | // CHECK: call void bitcast {{.*}} @objc_msgSend {{.*}} @_Z8c_helperv |
201 | // CHECK-NOT: call |
202 | // CHECK: ret void |
203 | |
204 | void testC1(C *c) { |
205 | c.c1 += c_helper; |
206 | } |
207 | // CHECK: define void @_Z6testC1P1C([[C]]* |
208 | // CHECK: [[CVAR:%.*]] = alloca [[C]]*, align 8 |
209 | // CHECK: load [[C]]*, [[C]]** [[CVAR]] |
210 | // CHECK-NOT: call |
211 | // CHECK: [[T0:%.*]] = call i32 bitcast {{.*}} @objc_msgSend |
212 | // CHECK-NOT: call |
213 | // CHECK: store i32 [[T0]], |
214 | // CHECK-NOT: call |
215 | // CHECK: [[T0:%.*]] = call i32 @_Zpl2C1RFvvE({{.*}} @_Z8c_helperv |
216 | // CHECK-NOT: call |
217 | // CHECK: store i32 [[T0]], |
218 | // CHECK-NOT: call |
219 | // CHECK: call void @llvm.memcpy |
220 | // CHECK-NOT: call |
221 | // CHECK: call void bitcast {{.*}} @objc_msgSend |
222 | // CHECK-NOT: call |
223 | // CHECK: ret void |
224 | |