xref: /llvm-project/clang/test/CodeGen/pass-object-size.c (revision 39db5e1ed87363a9ffea81e53520b542201b3262)
1 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s
2 
3 typedef unsigned long size_t;
4 
5 struct Foo {
6   int t[10];
7 };
8 
9 #define PS(N) __attribute__((pass_object_size(N)))
10 #define PDS(N) __attribute__((pass_dynamic_object_size(N)))
11 
12 int gi = 0;
13 
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);
18 }
19 
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);
24 }
25 
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);
30 }
31 
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);
36 }
37 
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);
42 }
43 
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);
48 }
49 
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);
54 }
55 
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);
60 }
61 
62 void *malloc(unsigned long) __attribute__((alloc_size(1)));
63 
64 // CHECK-LABEL: define{{.*}} void @test1
test1(unsigned long sz)65 void test1(unsigned long sz) {
66   struct Foo t[10];
67 
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]);
76 
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]);
85 
86   char *ptr = (char *)malloc(sz);
87 
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);
91 
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);
96 
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);
100 }
101 
102 // CHECK-LABEL: define{{.*}} void @test2
test2(struct Foo * t)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]);
109 }
110 
111 // CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize0Pv
NoViableOverloadObjectSize0(void * const p)112 int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) {
113   // CHECK: @llvm.objectsize
114   return __builtin_object_size(p, 0);
115 }
116 
117 // CHECK-LABEL: define{{.*}} i32 @_Z34NoViableOverloadDynamicObjectSize0Pv
NoViableOverloadDynamicObjectSize0(void * const p)118 int NoViableOverloadDynamicObjectSize0(void *const p)
119   __attribute__((overloadable)) {
120   // CHECK: @llvm.objectsize
121   return __builtin_object_size(p, 0);
122 }
123 
124 // CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize1Pv
NoViableOverloadObjectSize1(void * const p)125 int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) {
126   // CHECK: @llvm.objectsize
127   return __builtin_object_size(p, 1);
128 }
129 
130 // CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize2Pv
NoViableOverloadObjectSize2(void * const p)131 int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) {
132   // CHECK: @llvm.objectsize
133   return __builtin_object_size(p, 2);
134 }
135 
136 // CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize3Pv
NoViableOverloadObjectSize3(void * const p)137 int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) {
138   // CHECK-NOT: @llvm.objectsize
139   return __builtin_object_size(p, 3);
140 }
141 
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);
147 }
148 
149 int NoViableOverloadDynamicObjectSize0(void *const p PDS(0))
150   __attribute__((overloadable)) {
151   return __builtin_dynamic_object_size(p, 0);
152 }
153 
154 int NoViableOverloadObjectSize1(void *const p PS(1))
155     __attribute__((overloadable)) {
156   return __builtin_object_size(p, 1);
157 }
158 
159 int NoViableOverloadObjectSize2(void *const p PS(2))
160     __attribute__((overloadable)) {
161   return __builtin_object_size(p, 2);
162 }
163 
164 int NoViableOverloadObjectSize3(void *const p PS(3))
165     __attribute__((overloadable)) {
166   return __builtin_object_size(p, 3);
167 }
168 
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;
173 }
174 
175 int NoViableOverloadObjectSize1(void *const p PS(1))
176     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
177   return SHOULDNT_BE_CALLED;
178 }
179 
180 int NoViableOverloadObjectSize2(void *const p PS(2))
181     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
182   return SHOULDNT_BE_CALLED;
183 }
184 
185 int NoViableOverloadObjectSize3(void *const p PS(3))
186     __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
187   return SHOULDNT_BE_CALLED;
188 }
189 
190 // CHECK-LABEL: define{{.*}} void @test3
test3(void)191 void test3(void) {
192   struct Foo t[10];
193 
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]);
202 
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]);
211 
212   // CHECK: call i32 @_Z34NoViableOverloadDynamicObjectSize0PvU25pass_dynamic_object_size0(ptr noundef %{{.*}}, i64 noundef 360)
213   gi = NoViableOverloadDynamicObjectSize0(&t[1]);
214 }
215 
216 // CHECK-LABEL: define{{.*}} void @test4
test4(struct Foo * t)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]);
226 
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]);
236 }
237 
test5(void)238 void test5(void) {
239   struct Foo t[10];
240 
241   int (*f)(void *) = &NoViableOverloadObjectSize0;
242   gi = f(&t[1]);
243 
244   int (*g)(void *) = &NoViableOverloadDynamicObjectSize0;
245   gi = g(&t[1]);
246 }
247 
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);
253 }
254 
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);
260 }
261 
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);
267 }
268 
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);
274 }
275 
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);
280 }
281 
282 int Overload0(void *, size_t, void *, size_t);
283 int OverloadNoSize(void *, void *);
284 
285 int OverloadedObjectSize(void *const p PS(0),
286                          void *const c PS(0))
287     __attribute__((overloadable)) __asm__("Overload0");
288 
289 int OverloadedObjectSize(void *const p, void *const c)
290     __attribute__((overloadable)) __asm__("OverloadNoSize");
291 
292 // CHECK-LABEL: define{{.*}} void @test6
test6(void)293 void test6(void) {
294   int known[10], *opaque;
295 
296   // CHECK: call i32 @"\01Overload0"
297   gi = OverloadedObjectSize(&known[0], &known[0]);
298 
299   // CHECK: call i32 @"\01Overload0"
300   gi = OverloadedObjectSize(&known[0], opaque);
301 
302   // CHECK: call i32 @"\01Overload0"
303   gi = OverloadedObjectSize(opaque, &known[0]);
304 
305   // CHECK: call i32 @"\01Overload0"
306   gi = OverloadedObjectSize(opaque, opaque);
307 }
308 
Identity(void * p,size_t i)309 int Identity(void *p, size_t i) { return i; }
310 
311 // CHECK-NOT: define{{.*}} void @AsmObjectSize
312 int AsmObjectSize0(void *const p PS(0)) __asm__("Identity");
313 
314 int AsmObjectSize1(void *const p PS(1)) __asm__("Identity");
315 
316 int AsmObjectSize2(void *const p PS(2)) __asm__("Identity");
317 
318 int AsmObjectSize3(void *const p PS(3)) __asm__("Identity");
319 
320 // CHECK-LABEL: define{{.*}} void @test7
test7(void)321 void test7(void) {
322   struct Foo t[10];
323 
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]);
332 
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]);
341 }
342 
343 // CHECK-LABEL: define{{.*}} void @test8
test8(struct Foo * t)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]);
350 }
351 
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))));
356 
357 // CHECK-LABEL: define{{.*}} void @test9
test9(void * const p)358 void test9(void *const p __attribute__((pass_object_size(0)))) {
359   // CHECK: @llvm.objectsize
360   DifferingObjectSize2(p);
361 
362   // CHECK-NOT: @llvm.objectsize
363   DifferingObjectSize0(p);
364   DifferingObjectSize1(p);
365 
366   // CHECK: call void @DifferingObjectSize3(ptr noundef %{{.*}}, i64 noundef 0)
367   DifferingObjectSize3(p);
368 }
369 
370 // CHECK-LABEL: define{{.*}} void @test10
test10(void * const p)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);
376 
377   // CHECK-NOT: @llvm.objectsize
378   DifferingObjectSize1(p);
379 
380   // CHECK: call void @DifferingObjectSize3(ptr noundef %{{.*}}, i64 noundef 0)
381   DifferingObjectSize3(p);
382 }
383 
384 // CHECK-LABEL: define{{.*}} void @test11
test11(void * const p)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);
390 
391   // CHECK-NOT: @llvm.objectsize
392   DifferingObjectSize2(p);
393 
394   // CHECK: call void @DifferingObjectSize3(ptr noundef %{{.*}}, i64 noundef 0)
395   DifferingObjectSize3(p);
396 }
397 
398 // CHECK-LABEL: define{{.*}} void @test12
test12(void * const p)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);
404 
405   // CHECK-NOT: @llvm.objectsize
406   DifferingObjectSize2(p);
407   DifferingObjectSize3(p);
408 }
409 
410 // CHECK-LABEL: define{{.*}} void @test13
test13(void)411 void test13(void) {
412   char c[10];
413   unsigned i = 0;
414   char *p = c;
415 
416   // CHECK: @llvm.objectsize
417   ObjectSize0(p);
418 
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);
426 
427   // CHECK: = add
428   // CHECK: @llvm.objectsize
429   // CHECK-NOT: = add
430   // CHECK: call i32 @ObjectSize0
431   ObjectSize0(p + i++);
432 }
433 
434 // There was a bug where variadic functions with pass_object_size would cause
435 // problems in the form of failed assertions.
my_sprintf(char * const c,...)436 void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {}
437 
438 // CHECK-LABEL: define{{.*}} void @test14
test14(char * c)439 void test14(char *c) {
440   // CHECK: @llvm.objectsize
441   // CHECK: call void (ptr, i64, ...) @my_sprintf
442   my_sprintf(c);
443 
444   // CHECK: @llvm.objectsize
445   // CHECK: call void (ptr, i64, ...) @my_sprintf
446   my_sprintf(c, 1, 2, 3);
447 }
448 
449 void pass_size_unsigned(unsigned *const PS(0));
450 
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
test15(unsigned * I)454 void test15(unsigned *I) {
455   // CHECK: @llvm.objectsize.i64.p0
456   // CHECK: call void @pass_size_unsigned
457   pass_size_unsigned(I);
458 }
459 
460 void pass_size_as1(__attribute__((address_space(1))) void *const PS(0));
461 
462 void pass_size_unsigned_as1(
463     __attribute__((address_space(1))) unsigned *const PS(0));
464 
465 // CHECK-LABEL: define{{.*}} void @test16
test16(unsigned * I)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);
473 }
474 
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
test17(char * C)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; }));
486 }
487 
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);
493 }
494