blob: 6f5827befa714a1dd65addc043d9e61cd86e207a [file] [log] [blame]
George Burgess IV08a4a8c2015-12-03 19:19:09 +00001// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s
2
3typedef unsigned long size_t;
4
5struct Foo {
6 int t[10];
7};
8
9#define PS(N) __attribute__((pass_object_size(N)))
10
11int gi = 0;
12
13// CHECK-LABEL: define i32 @ObjectSize0(i8* %{{.*}}, i64)
14int ObjectSize0(void *const p PS(0)) {
15 // CHECK-NOT: @llvm.objectsize
16 return __builtin_object_size(p, 0);
17}
18
19// CHECK-LABEL: define i32 @ObjectSize1(i8* %{{.*}}, i64)
20int ObjectSize1(void *const p PS(1)) {
21 // CHECK-NOT: @llvm.objectsize
22 return __builtin_object_size(p, 1);
23}
24
25// CHECK-LABEL: define i32 @ObjectSize2(i8* %{{.*}}, i64)
26int ObjectSize2(void *const p PS(2)) {
27 // CHECK-NOT: @llvm.objectsize
28 return __builtin_object_size(p, 2);
29}
30
31// CHECK-LABEL: define i32 @ObjectSize3(i8* %{{.*}}, i64)
32int ObjectSize3(void *const p PS(3)) {
33 // CHECK-NOT: @llvm.objectsize
34 return __builtin_object_size(p, 3);
35}
36
37// CHECK-LABEL: define void @test1
38void test1() {
39 struct Foo t[10];
40
41 // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 360)
42 gi = ObjectSize0(&t[1]);
43 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 360)
44 gi = ObjectSize1(&t[1]);
45 // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 360)
46 gi = ObjectSize2(&t[1]);
47 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 360)
48 gi = ObjectSize3(&t[1]);
49
50 // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 356)
51 gi = ObjectSize0(&t[1].t[1]);
52 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
53 gi = ObjectSize1(&t[1].t[1]);
54 // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 356)
55 gi = ObjectSize2(&t[1].t[1]);
56 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
57 gi = ObjectSize3(&t[1].t[1]);
58}
59
60// CHECK-LABEL: define void @test2
61void test2(struct Foo *t) {
George Burgess IVf8f63242016-09-12 23:50:35 +000062 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
63 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 [[VAR]])
George Burgess IV08a4a8c2015-12-03 19:19:09 +000064 gi = ObjectSize1(&t->t[1]);
65 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
66 gi = ObjectSize3(&t->t[1]);
67}
68
69// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
70int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) {
71 // CHECK: @llvm.objectsize
72 return __builtin_object_size(p, 0);
73}
74
75// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize1Pv
76int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) {
77 // CHECK: @llvm.objectsize
78 return __builtin_object_size(p, 1);
79}
80
81// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize2Pv
82int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) {
83 // CHECK: @llvm.objectsize
84 return __builtin_object_size(p, 2);
85}
86
87// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize3Pv
88int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) {
89 // CHECK-NOT: @llvm.objectsize
90 return __builtin_object_size(p, 3);
91}
92
93// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
94// CHECK-NOT: @llvm.objectsize
95int NoViableOverloadObjectSize0(void *const p PS(0))
96 __attribute__((overloadable)) {
97 return __builtin_object_size(p, 0);
98}
99
100int NoViableOverloadObjectSize1(void *const p PS(1))
101 __attribute__((overloadable)) {
102 return __builtin_object_size(p, 1);
103}
104
105int NoViableOverloadObjectSize2(void *const p PS(2))
106 __attribute__((overloadable)) {
107 return __builtin_object_size(p, 2);
108}
109
110int NoViableOverloadObjectSize3(void *const p PS(3))
111 __attribute__((overloadable)) {
112 return __builtin_object_size(p, 3);
113}
114
115const static int SHOULDNT_BE_CALLED = -100;
116int NoViableOverloadObjectSize0(void *const p PS(0))
117 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
118 return SHOULDNT_BE_CALLED;
119}
120
121int NoViableOverloadObjectSize1(void *const p PS(1))
122 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
123 return SHOULDNT_BE_CALLED;
124}
125
126int NoViableOverloadObjectSize2(void *const p PS(2))
127 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
128 return SHOULDNT_BE_CALLED;
129}
130
131int NoViableOverloadObjectSize3(void *const p PS(3))
132 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
133 return SHOULDNT_BE_CALLED;
134}
135
136// CHECK-LABEL: define void @test3
137void test3() {
138 struct Foo t[10];
139
140 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 360)
141 gi = NoViableOverloadObjectSize0(&t[1]);
142 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 360)
143 gi = NoViableOverloadObjectSize1(&t[1]);
144 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 360)
145 gi = NoViableOverloadObjectSize2(&t[1]);
146 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 360)
147 gi = NoViableOverloadObjectSize3(&t[1]);
148
149 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 356)
150 gi = NoViableOverloadObjectSize0(&t[1].t[1]);
151 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
152 gi = NoViableOverloadObjectSize1(&t[1].t[1]);
153 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 356)
154 gi = NoViableOverloadObjectSize2(&t[1].t[1]);
155 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
156 gi = NoViableOverloadObjectSize3(&t[1].t[1]);
157}
158
159// CHECK-LABEL: define void @test4
160void test4(struct Foo *t) {
161 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
162 gi = NoViableOverloadObjectSize0(&t[1]);
163 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 %{{.*}})
164 gi = NoViableOverloadObjectSize1(&t[1]);
165 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
166 gi = NoViableOverloadObjectSize2(&t[1]);
167 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 0)
168 gi = NoViableOverloadObjectSize3(&t[1]);
169
170 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
171 gi = NoViableOverloadObjectSize0(&t[1].t[1]);
George Burgess IVf8f63242016-09-12 23:50:35 +0000172 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
173 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 [[VAR]])
George Burgess IV08a4a8c2015-12-03 19:19:09 +0000174 gi = NoViableOverloadObjectSize1(&t[1].t[1]);
175 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
176 gi = NoViableOverloadObjectSize2(&t[1].t[1]);
177 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
178 gi = NoViableOverloadObjectSize3(&t[1].t[1]);
179}
180
181void test5() {
182 struct Foo t[10];
183
184 int (*f)(void *) = &NoViableOverloadObjectSize0;
185 gi = f(&t[1]);
186}
187
188// CHECK-LABEL: define i32 @IndirectObjectSize0
189int IndirectObjectSize0(void *const p PS(0)) {
190 // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}})
191 // CHECK-NOT: @llvm.objectsize
192 return ObjectSize0(p);
193}
194
195// CHECK-LABEL: define i32 @IndirectObjectSize1
196int IndirectObjectSize1(void *const p PS(1)) {
197 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 %{{.*}})
198 // CHECK-NOT: @llvm.objectsize
199 return ObjectSize1(p);
200}
201
202// CHECK-LABEL: define i32 @IndirectObjectSize2
203int IndirectObjectSize2(void *const p PS(2)) {
204 // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 %{{.*}})
205 // CHECK-NOT: @llvm.objectsize
206 return ObjectSize2(p);
207}
208
209// CHECK-LABEL: define i32 @IndirectObjectSize3
210int IndirectObjectSize3(void *const p PS(3)) {
211 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 %{{.*}})
212 // CHECK-NOT: @llvm.objectsize
213 return ObjectSize3(p);
214}
215
216int Overload0(void *, size_t, void *, size_t);
217int OverloadNoSize(void *, void *);
218
219int OverloadedObjectSize(void *const p PS(0),
220 void *const c PS(0))
221 __attribute__((overloadable)) __asm__("Overload0");
222
223int OverloadedObjectSize(void *const p, void *const c)
224 __attribute__((overloadable)) __asm__("OverloadNoSize");
225
226// CHECK-LABEL: define void @test6
227void test6() {
228 int known[10], *opaque;
229
230 // CHECK: call i32 @"\01Overload0"
231 gi = OverloadedObjectSize(&known[0], &known[0]);
232
233 // CHECK: call i32 @"\01Overload0"
234 gi = OverloadedObjectSize(&known[0], opaque);
235
236 // CHECK: call i32 @"\01Overload0"
237 gi = OverloadedObjectSize(opaque, &known[0]);
238
239 // CHECK: call i32 @"\01Overload0"
240 gi = OverloadedObjectSize(opaque, opaque);
241}
242
243int Identity(void *p, size_t i) { return i; }
244
245// CHECK-NOT: define void @AsmObjectSize
246int AsmObjectSize0(void *const p PS(0)) __asm__("Identity");
247
248int AsmObjectSize1(void *const p PS(1)) __asm__("Identity");
249
250int AsmObjectSize2(void *const p PS(2)) __asm__("Identity");
251
252int AsmObjectSize3(void *const p PS(3)) __asm__("Identity");
253
254// CHECK-LABEL: define void @test7
255void test7() {
256 struct Foo t[10];
257
258 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
259 gi = AsmObjectSize0(&t[1]);
260 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
261 gi = AsmObjectSize1(&t[1]);
262 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
263 gi = AsmObjectSize2(&t[1]);
264 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
265 gi = AsmObjectSize3(&t[1]);
266
267 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
268 gi = AsmObjectSize0(&t[1].t[1]);
269 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
270 gi = AsmObjectSize1(&t[1].t[1]);
271 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
272 gi = AsmObjectSize2(&t[1].t[1]);
273 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
274 gi = AsmObjectSize3(&t[1].t[1]);
275}
276
277// CHECK-LABEL: define void @test8
278void test8(struct Foo *t) {
George Burgess IVf8f63242016-09-12 23:50:35 +0000279 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
280 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 [[VAR]])
George Burgess IV08a4a8c2015-12-03 19:19:09 +0000281 gi = AsmObjectSize1(&t[1].t[1]);
282 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
283 gi = AsmObjectSize3(&t[1].t[1]);
284}
285
286void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0))));
287void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1))));
288void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2))));
289void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3))));
290
291// CHECK-LABEL: define void @test9
292void test9(void *const p __attribute__((pass_object_size(0)))) {
293 // CHECK: @llvm.objectsize
294 DifferingObjectSize2(p);
295
296 // CHECK-NOT: @llvm.objectsize
297 DifferingObjectSize0(p);
298 DifferingObjectSize1(p);
299
300 // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
301 DifferingObjectSize3(p);
302}
303
304// CHECK-LABEL: define void @test10
305void test10(void *const p __attribute__((pass_object_size(1)))) {
306 // CHECK: @llvm.objectsize
307 DifferingObjectSize2(p);
308 // CHECK: @llvm.objectsize
309 DifferingObjectSize0(p);
310
311 // CHECK-NOT: @llvm.objectsize
312 DifferingObjectSize1(p);
313
314 // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
315 DifferingObjectSize3(p);
316}
317
318// CHECK-LABEL: define void @test11
319void test11(void *const p __attribute__((pass_object_size(2)))) {
320 // CHECK: @llvm.objectsize
321 DifferingObjectSize0(p);
322 // CHECK: @llvm.objectsize
323 DifferingObjectSize1(p);
324
325 // CHECK-NOT: @llvm.objectsize
326 DifferingObjectSize2(p);
327
328 // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
329 DifferingObjectSize3(p);
330}
331
332// CHECK-LABEL: define void @test12
333void test12(void *const p __attribute__((pass_object_size(3)))) {
334 // CHECK: @llvm.objectsize
335 DifferingObjectSize0(p);
336 // CHECK: @llvm.objectsize
337 DifferingObjectSize1(p);
338
339 // CHECK-NOT: @llvm.objectsize
340 DifferingObjectSize2(p);
341 DifferingObjectSize3(p);
342}
343
344// CHECK-LABEL: define void @test13
345void test13() {
346 // Ensuring that we don't lower objectsize if the expression has side-effects
347 char c[10];
348 char *p = c;
349
350 // CHECK: @llvm.objectsize
351 ObjectSize0(p);
352
353 // CHECK-NOT: @llvm.objectsize
354 ObjectSize0(++p);
355 ObjectSize0(p++);
356}
George Burgess IV419996c2016-06-16 23:06:04 +0000357
358// There was a bug where variadic functions with pass_object_size would cause
359// problems in the form of failed assertions.
360void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {}
361
362// CHECK-LABEL: define void @test14
363void test14(char *c) {
364 // CHECK: @llvm.objectsize
365 // CHECK: call void (i8*, i64, ...) @my_sprintf
366 my_sprintf(c);
367
368 // CHECK: @llvm.objectsize
369 // CHECK: call void (i8*, i64, ...) @my_sprintf
370 my_sprintf(c, 1, 2, 3);
371}