[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / CodeGen / pass-object-size.c
blobc7c505b0fb3e7817784b2b54bee32979b1a2852d
1 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s
3 typedef unsigned long size_t;
5 struct Foo {
6 int t[10];
7 };
9 #define PS(N) __attribute__((pass_object_size(N)))
10 #define PDS(N) __attribute__((pass_dynamic_object_size(N)))
12 int gi = 0;
14 // CHECK-LABEL: define{{.*}} i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef %0)
15 int ObjectSize0(void *const p PS(0)) {
16 // CHECK-NOT: @llvm.objectsize
17 return __builtin_object_size(p, 0);
20 // CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize0(ptr noundef %{{.*}}, i64 noundef %0)
21 int DynamicObjectSize0(void *const p PDS(0)) {
22 // CHECK-NOT: @llvm.objectsize
23 return __builtin_dynamic_object_size(p, 0);
26 // CHECK-LABEL: define{{.*}} i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef %0)
27 int ObjectSize1(void *const p PS(1)) {
28 // CHECK-NOT: @llvm.objectsize
29 return __builtin_object_size(p, 1);
32 // CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize1(ptr noundef %{{.*}}, i64 noundef %0)
33 int DynamicObjectSize1(void *const p PDS(1)) {
34 // CHECK-NOT: @llvm.objectsize
35 return __builtin_dynamic_object_size(p, 1);
38 // CHECK-LABEL: define{{.*}} i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef %0)
39 int ObjectSize2(void *const p PS(2)) {
40 // CHECK-NOT: @llvm.objectsize
41 return __builtin_object_size(p, 2);
44 // CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize2(ptr noundef %{{.*}}, i64 noundef %0)
45 int DynamicObjectSize2(void *const p PDS(2)) {
46 // CHECK-NOT: @llvm.objectsize
47 return __builtin_object_size(p, 2);
50 // CHECK-LABEL: define{{.*}} i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef %0)
51 int ObjectSize3(void *const p PS(3)) {
52 // CHECK-NOT: @llvm.objectsize
53 return __builtin_object_size(p, 3);
56 // CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize3(ptr noundef %{{.*}}, i64 noundef %0)
57 int DynamicObjectSize3(void *const p PDS(3)) {
58 // CHECK-NOT: @llvm.objectsize
59 return __builtin_object_size(p, 3);
62 void *malloc(unsigned long) __attribute__((alloc_size(1)));
64 // CHECK-LABEL: define{{.*}} void @test1
65 void test1(unsigned long sz) {
66 struct Foo t[10];
68 // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef 360)
69 gi = ObjectSize0(&t[1]);
70 // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef 360)
71 gi = ObjectSize1(&t[1]);
72 // CHECK: call i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef 360)
73 gi = ObjectSize2(&t[1]);
74 // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef 360)
75 gi = ObjectSize3(&t[1]);
77 // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef 356)
78 gi = ObjectSize0(&t[1].t[1]);
79 // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef 36)
80 gi = ObjectSize1(&t[1].t[1]);
81 // CHECK: call i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef 356)
82 gi = ObjectSize2(&t[1].t[1]);
83 // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef 36)
84 gi = ObjectSize3(&t[1].t[1]);
86 char *ptr = (char *)malloc(sz);
88 // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0({{.*}}, i1 false, i1 true, i1 true)
89 // CHECK: call i32 @DynamicObjectSize0(ptr noundef %{{.*}}, i64 noundef [[REG]])
90 gi = DynamicObjectSize0(ptr);
92 // CHECK: [[WITH_OFFSET:%.*]] = getelementptr
93 // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0(ptr [[WITH_OFFSET]], i1 false, i1 true, i1 true)
94 // CHECK: call i32 @DynamicObjectSize0(ptr noundef {{.*}}, i64 noundef [[REG]])
95 gi = DynamicObjectSize0(ptr+10);
97 // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0({{.*}}, i1 true, i1 true, i1 true)
98 // CHECK: call i32 @DynamicObjectSize2(ptr noundef {{.*}}, i64 noundef [[REG]])
99 gi = DynamicObjectSize2(ptr);
102 // CHECK-LABEL: define{{.*}} void @test2
103 void test2(struct Foo *t) {
104 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
105 // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef [[VAR]])
106 gi = ObjectSize1(&t->t[1]);
107 // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef 36)
108 gi = ObjectSize3(&t->t[1]);
111 // CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize0Pv
112 int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) {
113 // CHECK: @llvm.objectsize
114 return __builtin_object_size(p, 0);
117 // CHECK-LABEL: define{{.*}} i32 @_Z34NoViableOverloadDynamicObjectSize0Pv
118 int NoViableOverloadDynamicObjectSize0(void *const p)
119 __attribute__((overloadable)) {
120 // CHECK: @llvm.objectsize
121 return __builtin_object_size(p, 0);
124 // CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize1Pv
125 int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) {
126 // CHECK: @llvm.objectsize
127 return __builtin_object_size(p, 1);
130 // CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize2Pv
131 int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) {
132 // CHECK: @llvm.objectsize
133 return __builtin_object_size(p, 2);
136 // CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize3Pv
137 int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) {
138 // CHECK-NOT: @llvm.objectsize
139 return __builtin_object_size(p, 3);
142 // CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize0Pv
143 // CHECK-NOT: @llvm.objectsize
144 int NoViableOverloadObjectSize0(void *const p PS(0))
145 __attribute__((overloadable)) {
146 return __builtin_object_size(p, 0);
149 int NoViableOverloadDynamicObjectSize0(void *const p PDS(0))
150 __attribute__((overloadable)) {
151 return __builtin_dynamic_object_size(p, 0);
154 int NoViableOverloadObjectSize1(void *const p PS(1))
155 __attribute__((overloadable)) {
156 return __builtin_object_size(p, 1);
159 int NoViableOverloadObjectSize2(void *const p PS(2))
160 __attribute__((overloadable)) {
161 return __builtin_object_size(p, 2);
164 int NoViableOverloadObjectSize3(void *const p PS(3))
165 __attribute__((overloadable)) {
166 return __builtin_object_size(p, 3);
169 const static int SHOULDNT_BE_CALLED = -100;
170 int NoViableOverloadObjectSize0(void *const p PS(0))
171 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
172 return SHOULDNT_BE_CALLED;
175 int NoViableOverloadObjectSize1(void *const p PS(1))
176 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
177 return SHOULDNT_BE_CALLED;
180 int NoViableOverloadObjectSize2(void *const p PS(2))
181 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
182 return SHOULDNT_BE_CALLED;
185 int NoViableOverloadObjectSize3(void *const p PS(3))
186 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
187 return SHOULDNT_BE_CALLED;
190 // CHECK-LABEL: define{{.*}} void @test3
191 void test3(void) {
192 struct Foo t[10];
194 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(ptr noundef %{{.*}}, i64 noundef 360)
195 gi = NoViableOverloadObjectSize0(&t[1]);
196 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(ptr noundef %{{.*}}, i64 noundef 360)
197 gi = NoViableOverloadObjectSize1(&t[1]);
198 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(ptr noundef %{{.*}}, i64 noundef 360)
199 gi = NoViableOverloadObjectSize2(&t[1]);
200 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(ptr noundef %{{.*}}, i64 noundef 360)
201 gi = NoViableOverloadObjectSize3(&t[1]);
203 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(ptr noundef %{{.*}}, i64 noundef 356)
204 gi = NoViableOverloadObjectSize0(&t[1].t[1]);
205 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(ptr noundef %{{.*}}, i64 noundef 36)
206 gi = NoViableOverloadObjectSize1(&t[1].t[1]);
207 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(ptr noundef %{{.*}}, i64 noundef 356)
208 gi = NoViableOverloadObjectSize2(&t[1].t[1]);
209 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(ptr noundef %{{.*}}, i64 noundef 36)
210 gi = NoViableOverloadObjectSize3(&t[1].t[1]);
212 // CHECK: call i32 @_Z34NoViableOverloadDynamicObjectSize0PvU25pass_dynamic_object_size0(ptr noundef %{{.*}}, i64 noundef 360)
213 gi = NoViableOverloadDynamicObjectSize0(&t[1]);
216 // CHECK-LABEL: define{{.*}} void @test4
217 void test4(struct Foo *t) {
218 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(ptr noundef %{{.*}}, i64 noundef %{{.*}})
219 gi = NoViableOverloadObjectSize0(&t[1]);
220 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(ptr noundef %{{.*}}, i64 noundef %{{.*}})
221 gi = NoViableOverloadObjectSize1(&t[1]);
222 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(ptr noundef %{{.*}}, i64 noundef %{{.*}})
223 gi = NoViableOverloadObjectSize2(&t[1]);
224 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(ptr noundef %{{.*}}, i64 noundef 0)
225 gi = NoViableOverloadObjectSize3(&t[1]);
227 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(ptr noundef %{{.*}}, i64 noundef %{{.*}})
228 gi = NoViableOverloadObjectSize0(&t[1].t[1]);
229 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
230 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(ptr noundef %{{.*}}, i64 noundef [[VAR]])
231 gi = NoViableOverloadObjectSize1(&t[1].t[1]);
232 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(ptr noundef %{{.*}}, i64 noundef %{{.*}})
233 gi = NoViableOverloadObjectSize2(&t[1].t[1]);
234 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(ptr noundef %{{.*}}, i64 noundef 36)
235 gi = NoViableOverloadObjectSize3(&t[1].t[1]);
238 void test5(void) {
239 struct Foo t[10];
241 int (*f)(void *) = &NoViableOverloadObjectSize0;
242 gi = f(&t[1]);
244 int (*g)(void *) = &NoViableOverloadDynamicObjectSize0;
245 gi = g(&t[1]);
248 // CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize0
249 int IndirectObjectSize0(void *const p PS(0)) {
250 // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef %{{.*}})
251 // CHECK-NOT: @llvm.objectsize
252 return ObjectSize0(p);
255 // CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize1
256 int IndirectObjectSize1(void *const p PS(1)) {
257 // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef %{{.*}})
258 // CHECK-NOT: @llvm.objectsize
259 return ObjectSize1(p);
262 // CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize2
263 int IndirectObjectSize2(void *const p PS(2)) {
264 // CHECK: call i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef %{{.*}})
265 // CHECK-NOT: @llvm.objectsize
266 return ObjectSize2(p);
269 // CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize3
270 int IndirectObjectSize3(void *const p PS(3)) {
271 // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef %{{.*}})
272 // CHECK-NOT: @llvm.objectsize
273 return ObjectSize3(p);
276 int IndirectDynamicObjectSize0(void *const p PDS(0)) {
277 // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef %{{.*}})
278 // CHECK-NOT: @llvm.objectsize
279 return ObjectSize0(p);
282 int Overload0(void *, size_t, void *, size_t);
283 int OverloadNoSize(void *, void *);
285 int OverloadedObjectSize(void *const p PS(0),
286 void *const c PS(0))
287 __attribute__((overloadable)) __asm__("Overload0");
289 int OverloadedObjectSize(void *const p, void *const c)
290 __attribute__((overloadable)) __asm__("OverloadNoSize");
292 // CHECK-LABEL: define{{.*}} void @test6
293 void test6(void) {
294 int known[10], *opaque;
296 // CHECK: call i32 @"\01Overload0"
297 gi = OverloadedObjectSize(&known[0], &known[0]);
299 // CHECK: call i32 @"\01Overload0"
300 gi = OverloadedObjectSize(&known[0], opaque);
302 // CHECK: call i32 @"\01Overload0"
303 gi = OverloadedObjectSize(opaque, &known[0]);
305 // CHECK: call i32 @"\01Overload0"
306 gi = OverloadedObjectSize(opaque, opaque);
309 int Identity(void *p, size_t i) { return i; }
311 // CHECK-NOT: define{{.*}} void @AsmObjectSize
312 int AsmObjectSize0(void *const p PS(0)) __asm__("Identity");
314 int AsmObjectSize1(void *const p PS(1)) __asm__("Identity");
316 int AsmObjectSize2(void *const p PS(2)) __asm__("Identity");
318 int AsmObjectSize3(void *const p PS(3)) __asm__("Identity");
320 // CHECK-LABEL: define{{.*}} void @test7
321 void test7(void) {
322 struct Foo t[10];
324 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 360)
325 gi = AsmObjectSize0(&t[1]);
326 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 360)
327 gi = AsmObjectSize1(&t[1]);
328 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 360)
329 gi = AsmObjectSize2(&t[1]);
330 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 360)
331 gi = AsmObjectSize3(&t[1]);
333 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 356)
334 gi = AsmObjectSize0(&t[1].t[1]);
335 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 36)
336 gi = AsmObjectSize1(&t[1].t[1]);
337 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 356)
338 gi = AsmObjectSize2(&t[1].t[1]);
339 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 36)
340 gi = AsmObjectSize3(&t[1].t[1]);
343 // CHECK-LABEL: define{{.*}} void @test8
344 void test8(struct Foo *t) {
345 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
346 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef [[VAR]])
347 gi = AsmObjectSize1(&t[1].t[1]);
348 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 36)
349 gi = AsmObjectSize3(&t[1].t[1]);
352 void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0))));
353 void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1))));
354 void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2))));
355 void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3))));
357 // CHECK-LABEL: define{{.*}} void @test9
358 void test9(void *const p __attribute__((pass_object_size(0)))) {
359 // CHECK: @llvm.objectsize
360 DifferingObjectSize2(p);
362 // CHECK-NOT: @llvm.objectsize
363 DifferingObjectSize0(p);
364 DifferingObjectSize1(p);
366 // CHECK: call void @DifferingObjectSize3(ptr noundef %{{.*}}, i64 noundef 0)
367 DifferingObjectSize3(p);
370 // CHECK-LABEL: define{{.*}} void @test10
371 void test10(void *const p __attribute__((pass_object_size(1)))) {
372 // CHECK: @llvm.objectsize
373 DifferingObjectSize2(p);
374 // CHECK: @llvm.objectsize
375 DifferingObjectSize0(p);
377 // CHECK-NOT: @llvm.objectsize
378 DifferingObjectSize1(p);
380 // CHECK: call void @DifferingObjectSize3(ptr noundef %{{.*}}, i64 noundef 0)
381 DifferingObjectSize3(p);
384 // CHECK-LABEL: define{{.*}} void @test11
385 void test11(void *const p __attribute__((pass_object_size(2)))) {
386 // CHECK: @llvm.objectsize
387 DifferingObjectSize0(p);
388 // CHECK: @llvm.objectsize
389 DifferingObjectSize1(p);
391 // CHECK-NOT: @llvm.objectsize
392 DifferingObjectSize2(p);
394 // CHECK: call void @DifferingObjectSize3(ptr noundef %{{.*}}, i64 noundef 0)
395 DifferingObjectSize3(p);
398 // CHECK-LABEL: define{{.*}} void @test12
399 void test12(void *const p __attribute__((pass_object_size(3)))) {
400 // CHECK: @llvm.objectsize
401 DifferingObjectSize0(p);
402 // CHECK: @llvm.objectsize
403 DifferingObjectSize1(p);
405 // CHECK-NOT: @llvm.objectsize
406 DifferingObjectSize2(p);
407 DifferingObjectSize3(p);
410 // CHECK-LABEL: define{{.*}} void @test13
411 void test13(void) {
412 char c[10];
413 unsigned i = 0;
414 char *p = c;
416 // CHECK: @llvm.objectsize
417 ObjectSize0(p);
419 // Allow side-effects, since they always need to happen anyway. Just make sure
420 // we don't perform them twice.
421 // CHECK: = add
422 // CHECK-NOT: = add
423 // CHECK: @llvm.objectsize
424 // CHECK: call i32 @ObjectSize0
425 ObjectSize0(p + ++i);
427 // CHECK: = add
428 // CHECK: @llvm.objectsize
429 // CHECK-NOT: = add
430 // CHECK: call i32 @ObjectSize0
431 ObjectSize0(p + i++);
434 // There was a bug where variadic functions with pass_object_size would cause
435 // problems in the form of failed assertions.
436 void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {}
438 // CHECK-LABEL: define{{.*}} void @test14
439 void test14(char *c) {
440 // CHECK: @llvm.objectsize
441 // CHECK: call void (ptr, i64, ...) @my_sprintf
442 my_sprintf(c);
444 // CHECK: @llvm.objectsize
445 // CHECK: call void (ptr, i64, ...) @my_sprintf
446 my_sprintf(c, 1, 2, 3);
449 void pass_size_unsigned(unsigned *const PS(0));
451 // Bug: we weren't lowering to the proper @llvm.objectsize for pointers that
452 // don't turn into ptr s, which caused crashes.
453 // CHECK-LABEL: define{{.*}} void @test15
454 void test15(unsigned *I) {
455 // CHECK: @llvm.objectsize.i64.p0
456 // CHECK: call void @pass_size_unsigned
457 pass_size_unsigned(I);
460 void pass_size_as1(__attribute__((address_space(1))) void *const PS(0));
462 void pass_size_unsigned_as1(
463 __attribute__((address_space(1))) unsigned *const PS(0));
465 // CHECK-LABEL: define{{.*}} void @test16
466 void test16(__attribute__((address_space(1))) unsigned *I) {
467 // CHECK: call i64 @llvm.objectsize.i64.p1
468 // CHECK: call void @pass_size_as1
469 pass_size_as1(I);
470 // CHECK: call i64 @llvm.objectsize.i64.p1
471 // CHECK: call void @pass_size_unsigned_as1
472 pass_size_unsigned_as1(I);
475 // This used to cause assertion failures, since we'd try to emit the statement
476 // expression (and definitions for `a`) twice.
477 // CHECK-LABEL: define{{.*}} void @test17
478 void test17(char *C) {
479 // Check for 65535 to see if we're emitting this pointer twice.
480 // CHECK: 65535
481 // CHECK-NOT: 65535
482 // CHECK: @llvm.objectsize.i64.p0(ptr [[PTR:%[^,]+]],
483 // CHECK-NOT: 65535
484 // CHECK: call i32 @ObjectSize0(ptr noundef [[PTR]]
485 ObjectSize0(C + ({ int a = 65535; a; }));
488 // CHECK-LABEL: define{{.*}} void @test18
489 void test18(char *const p PDS(0)) {
490 // CHECK-NOT: llvm.objectsize
491 gi = __builtin_dynamic_object_size(p, 0);
492 gi = __builtin_object_size(p, 0);