tree-optimization/104009: Conservative underflow estimate in object size
[official-gcc.git] / gcc / testsuite / gcc.dg / builtin-object-size-1.c
blobb772e2da9b94924cf162363bb9aa190a05ee3652
1 /* { dg-do run } */
2 /* { dg-options "-O2" } */
3 /* { dg-require-effective-target alloca } */
5 typedef __SIZE_TYPE__ size_t;
6 extern void abort (void);
7 extern void exit (int);
8 extern void *malloc (size_t);
9 extern void *calloc (size_t, size_t);
10 extern void *alloca (size_t);
11 extern void *memcpy (void *, const void *, size_t);
12 extern void *memset (void *, int, size_t);
13 extern char *strcpy (char *, const char *);
15 struct A
17 char a[10];
18 int b;
19 char c[10];
20 } y, w[4];
22 extern char exta[];
23 extern char extb[30];
24 extern struct A zerol[0];
26 void
27 __attribute__ ((noinline))
28 test1 (void *q, int x)
30 struct A a;
31 void *p = &a.a[3], *r;
32 char var[x + 10];
33 if (x < 0)
34 r = &a.a[9];
35 else
36 r = &a.c[1];
37 if (__builtin_object_size (p, 0)
38 != sizeof (a) - __builtin_offsetof (struct A, a) - 3)
39 abort ();
40 if (__builtin_object_size (&a.c[9], 0)
41 != sizeof (a) - __builtin_offsetof (struct A, c) - 9)
42 abort ();
43 if (__builtin_object_size (q, 0) != (size_t) -1)
44 abort ();
45 #ifdef __builtin_object_size
46 if (__builtin_object_size (r, 0)
47 != (x < 0
48 ? sizeof (a) - __builtin_offsetof (struct A, a) - 9
49 : sizeof (a) - __builtin_offsetof (struct A, c) - 1))
50 abort ();
51 #else
52 if (__builtin_object_size (r, 0)
53 != sizeof (a) - __builtin_offsetof (struct A, a) - 9)
54 abort ();
55 #endif
56 if (x < 6)
57 r = &w[2].a[1];
58 else
59 r = &a.a[6];
60 if (__builtin_object_size (&y, 0)
61 != sizeof (y))
62 abort ();
63 if (__builtin_object_size (w, 0)
64 != sizeof (w))
65 abort ();
66 if (__builtin_object_size (&y.b, 0)
67 != sizeof (a) - __builtin_offsetof (struct A, b))
68 abort ();
69 #ifdef __builtin_object_size
70 if (__builtin_object_size (r, 0)
71 != (x < 6
72 ? 2 * sizeof (w[0]) - __builtin_offsetof (struct A, a) - 1
73 : sizeof (a) - __builtin_offsetof (struct A, a) - 6))
74 abort ();
75 #else
76 if (__builtin_object_size (r, 0)
77 != 2 * sizeof (w[0]) - __builtin_offsetof (struct A, a) - 1)
78 abort ();
79 #endif
80 if (x < 20)
81 r = malloc (30);
82 else
83 r = calloc (2, 16);
84 #ifdef __builtin_object_size
85 if (__builtin_object_size (r, 0) != (x < 20 ? 30 : 2 * 16))
86 abort ();
87 #else
88 /* We may duplicate this test onto the two exit paths. On one path
89 the size will be 32, the other it will be 30. If we don't duplicate
90 this test, then the size will be 32. */
91 if (__builtin_object_size (r, 0) != 2 * 16
92 && __builtin_object_size (r, 0) != 30)
93 abort ();
94 #endif
95 if (x < 20)
96 r = malloc (30);
97 else
98 r = calloc (2, 14);
99 #ifdef __builtin_object_size
100 if (__builtin_object_size (r, 0) != (x < 20 ? 30 : 2 * 14))
101 abort ();
102 #else
103 if (__builtin_object_size (r, 0) != 30)
104 abort ();
105 #endif
106 if (x < 30)
107 r = malloc (sizeof (a));
108 else
109 r = &a.a[3];
110 #ifdef __builtin_object_size
111 if (__builtin_object_size (r, 0) != (x < 30 ? sizeof (a) : sizeof (a) - 3))
112 abort ();
113 #else
114 if (__builtin_object_size (r, 0) != sizeof (a))
115 abort ();
116 #endif
117 r = memcpy (r, "a", 2);
118 #ifdef __builtin_object_size
119 if (__builtin_object_size (r, 0) != (x < 30 ? sizeof (a) : sizeof (a) - 3))
120 abort ();
121 #else
122 if (__builtin_object_size (r, 0) != sizeof (a))
123 abort ();
124 #endif
125 r = memcpy (r + 2, "b", 2) + 2;
126 #ifdef __builtin_object_size
127 if (__builtin_object_size (r, 0)
128 != (x < 30 ? sizeof (a) - 4 : sizeof (a) - 7))
129 abort ();
130 #else
131 if (__builtin_object_size (r, 0) != sizeof (a) - 4)
132 abort ();
133 #endif
134 r = &a.a[4];
135 r = memset (r, 'a', 2);
136 if (__builtin_object_size (r, 0)
137 != sizeof (a) - __builtin_offsetof (struct A, a) - 4)
138 abort ();
139 r = memset (r + 2, 'b', 2) + 2;
140 if (__builtin_object_size (r, 0)
141 != sizeof (a) - __builtin_offsetof (struct A, a) - 8)
142 abort ();
143 r = &a.a[1];
144 r = strcpy (r, "ab");
145 if (__builtin_object_size (r, 0)
146 != sizeof (a) - __builtin_offsetof (struct A, a) - 1)
147 abort ();
148 r = strcpy (r + 2, "cd") + 2;
149 if (__builtin_object_size (r, 0)
150 != sizeof (a) - __builtin_offsetof (struct A, a) - 5)
151 abort ();
152 if (__builtin_object_size (exta, 0) != (size_t) -1)
153 abort ();
154 if (__builtin_object_size (exta + 10, 0) != (size_t) -1)
155 abort ();
156 if (__builtin_object_size (&exta[5], 0) != (size_t) -1)
157 abort ();
158 if (__builtin_object_size (extb, 0) != sizeof (extb))
159 abort ();
160 if (__builtin_object_size (extb + 10, 0) != sizeof (extb) - 10)
161 abort ();
162 if (__builtin_object_size (&extb[5], 0) != sizeof (extb) - 5)
163 abort ();
164 #ifdef __builtin_object_size
165 if (__builtin_object_size (var, 0) != x + 10)
166 abort ();
167 if (__builtin_object_size (var + 10, 0) != x)
168 abort ();
169 if (__builtin_object_size (&var[5], 0) != x + 5)
170 abort ();
171 #else
172 if (__builtin_object_size (var, 0) != (size_t) -1)
173 abort ();
174 if (__builtin_object_size (var + 10, 0) != (size_t) -1)
175 abort ();
176 if (__builtin_object_size (&var[5], 0) != (size_t) -1)
177 abort ();
178 #endif
179 if (__builtin_object_size (zerol, 0) != 0)
180 abort ();
181 if (__builtin_object_size (&zerol, 0) != 0)
182 abort ();
183 if (__builtin_object_size (&zerol[0], 0) != 0)
184 abort ();
185 if (__builtin_object_size (zerol[0].a, 0) != 0)
186 abort ();
187 if (__builtin_object_size (&zerol[0].a[0], 0) != 0)
188 abort ();
189 if (__builtin_object_size (&zerol[0].b, 0) != 0)
190 abort ();
191 if (__builtin_object_size ("abcdefg", 0) != sizeof ("abcdefg"))
192 abort ();
193 if (__builtin_object_size ("abcd\0efg", 0) != sizeof ("abcd\0efg"))
194 abort ();
195 if (__builtin_object_size (&"abcd\0efg", 0) != sizeof ("abcd\0efg"))
196 abort ();
197 if (__builtin_object_size (&"abcd\0efg"[0], 0) != sizeof ("abcd\0efg"))
198 abort ();
199 if (__builtin_object_size (&"abcd\0efg"[4], 0) != sizeof ("abcd\0efg") - 4)
200 abort ();
201 if (__builtin_object_size ("abcd\0efg" + 5, 0) != sizeof ("abcd\0efg") - 5)
202 abort ();
203 if (__builtin_object_size (L"abcdefg", 0) != sizeof (L"abcdefg"))
204 abort ();
205 r = (char *) L"abcd\0efg";
206 if (__builtin_object_size (r + 2, 0) != sizeof (L"abcd\0efg") - 2)
207 abort ();
210 size_t l1 = 1;
212 void
213 __attribute__ ((noinline))
214 test2 (void)
216 struct B { char buf1[10]; char buf2[10]; } a;
217 char *r, buf3[20];
218 int i;
219 size_t res;
221 if (sizeof (a) != 20)
222 return;
224 r = buf3;
225 for (i = 0; i < 4; ++i)
227 if (i == l1 - 1)
228 r = &a.buf1[1];
229 else if (i == l1)
230 r = &a.buf2[7];
231 else if (i == l1 + 1)
232 r = &buf3[5];
233 else if (i == l1 + 2)
234 r = &a.buf1[9];
236 #ifdef __builtin_object_size
237 res = sizeof (buf3);
239 for (i = 0; i < 4; ++i)
241 if (i == l1 - 1)
242 res = sizeof (a) - __builtin_offsetof (struct B, buf1) - 1;
243 else if (i == l1)
244 res = sizeof (a) - __builtin_offsetof (struct B, buf2) - 7;
245 else if (i == l1 + 1)
246 res = sizeof (buf3) - 5;
247 else if (i == l1 + 2)
248 res = sizeof (a) - __builtin_offsetof (struct B, buf1) - 9;
250 #else
251 res = 20;
252 #endif
253 if (__builtin_object_size (r, 0) != res)
254 abort ();
255 r = &buf3[20];
256 for (i = 0; i < 4; ++i)
258 if (i == l1 - 1)
259 r = &a.buf1[7];
260 else if (i == l1)
261 r = &a.buf2[7];
262 else if (i == l1 + 1)
263 r = &buf3[5];
264 else if (i == l1 + 2)
265 r = &a.buf1[9];
267 #ifdef __builtin_object_size
268 res = sizeof (buf3) - 20;
270 for (i = 0; i < 4; ++i)
272 if (i == l1 - 1)
273 res = sizeof (a) - __builtin_offsetof (struct B, buf1) - 7;
274 else if (i == l1)
275 res = sizeof (a) - __builtin_offsetof (struct B, buf2) - 7;
276 else if (i == l1 + 1)
277 res = sizeof (buf3) - 5;
278 else if (i == l1 + 2)
279 res = sizeof (a) - __builtin_offsetof (struct B, buf1) - 9;
281 if (__builtin_object_size (r, 0) != res)
282 abort ();
283 #else
284 res = 15;
285 #endif
286 if (__builtin_object_size (r, 0) != res)
287 abort ();
288 r += 8;
289 #ifdef __builtin_object_size
290 res -= 8;
291 if (__builtin_object_size (r, 0) != res)
292 abort ();
293 if (res >= 6)
295 if (__builtin_object_size (r + 6, 0) != res - 6)
296 abort ();
298 else if (__builtin_object_size (r + 6, 0) != 0)
299 abort ();
300 #else
301 if (__builtin_object_size (r, 0) != 7)
302 abort ();
303 if (__builtin_object_size (r + 6, 0) != 1)
304 abort ();
305 #endif
306 r = &buf3[18];
307 for (i = 0; i < 4; ++i)
309 if (i == l1 - 1)
310 r = &a.buf1[9];
311 else if (i == l1)
312 r = &a.buf2[9];
313 else if (i == l1 + 1)
314 r = &buf3[5];
315 else if (i == l1 + 2)
316 r = &a.buf1[4];
318 #ifdef __builtin_object_size
319 res = sizeof (buf3) - 18;
321 for (i = 0; i < 4; ++i)
323 if (i == l1 - 1)
324 res = sizeof (a) - __builtin_offsetof (struct B, buf1) - 9;
325 else if (i == l1)
326 res = sizeof (a) - __builtin_offsetof (struct B, buf2) - 9;
327 else if (i == l1 + 1)
328 res = sizeof (buf3) - 5;
329 else if (i == l1 + 2)
330 res = sizeof (a) - __builtin_offsetof (struct B, buf1) - 4;
332 if (res >= 12)
334 if (__builtin_object_size (r + 12, 0) != res - 12)
335 abort ();
337 else if (__builtin_object_size (r + 12, 0) != 0)
338 abort ();
339 #else
340 if (__builtin_object_size (r + 12, 0) != 4)
341 abort ();
342 #endif
345 void
346 __attribute__ ((noinline))
347 test3 (void)
349 char buf4[10];
350 struct B { struct A a[2]; struct A b; char c[4]; char d; double e;
351 _Complex double f; } x;
352 double y;
353 _Complex double z;
354 double *dp;
356 if (__builtin_object_size (buf4, 0) != sizeof (buf4))
357 abort ();
358 if (__builtin_object_size (&buf4, 0) != sizeof (buf4))
359 abort ();
360 if (__builtin_object_size (&buf4[0], 0) != sizeof (buf4))
361 abort ();
362 if (__builtin_object_size (&buf4[1], 0) != sizeof (buf4) - 1)
363 abort ();
364 if (__builtin_object_size (&x, 0) != sizeof (x))
365 abort ();
366 if (__builtin_object_size (&x.a, 0) != sizeof (x))
367 abort ();
368 if (__builtin_object_size (&x.a[0], 0) != sizeof (x))
369 abort ();
370 if (__builtin_object_size (&x.a[0].a, 0) != sizeof (x))
371 abort ();
372 if (__builtin_object_size (&x.a[0].a[0], 0) != sizeof (x))
373 abort ();
374 if (__builtin_object_size (&x.a[0].a[3], 0) != sizeof (x) - 3)
375 abort ();
376 if (__builtin_object_size (&x.a[0].b, 0)
377 != sizeof (x) - __builtin_offsetof (struct A, b))
378 abort ();
379 if (__builtin_object_size (&x.a[1].c, 0)
380 != sizeof (x) - sizeof (struct A) - __builtin_offsetof (struct A, c))
381 abort ();
382 if (__builtin_object_size (&x.a[1].c[0], 0)
383 != sizeof (x) - sizeof (struct A) - __builtin_offsetof (struct A, c))
384 abort ();
385 if (__builtin_object_size (&x.a[1].c[3], 0)
386 != sizeof (x) - sizeof (struct A) - __builtin_offsetof (struct A, c) - 3)
387 abort ();
388 if (__builtin_object_size (&x.b, 0)
389 != sizeof (x) - __builtin_offsetof (struct B, b))
390 abort ();
391 if (__builtin_object_size (&x.b.a, 0)
392 != sizeof (x) - __builtin_offsetof (struct B, b))
393 abort ();
394 if (__builtin_object_size (&x.b.a[0], 0)
395 != sizeof (x) - __builtin_offsetof (struct B, b))
396 abort ();
397 if (__builtin_object_size (&x.b.a[3], 0)
398 != sizeof (x) - __builtin_offsetof (struct B, b) - 3)
399 abort ();
400 if (__builtin_object_size (&x.b.b, 0)
401 != sizeof (x) - __builtin_offsetof (struct B, b)
402 - __builtin_offsetof (struct A, b))
403 abort ();
404 if (__builtin_object_size (&x.b.c, 0)
405 != sizeof (x) - __builtin_offsetof (struct B, b)
406 - __builtin_offsetof (struct A, c))
407 abort ();
408 if (__builtin_object_size (&x.b.c[0], 0)
409 != sizeof (x) - __builtin_offsetof (struct B, b)
410 - __builtin_offsetof (struct A, c))
411 abort ();
412 if (__builtin_object_size (&x.b.c[3], 0)
413 != sizeof (x) - __builtin_offsetof (struct B, b)
414 - __builtin_offsetof (struct A, c) - 3)
415 abort ();
416 if (__builtin_object_size (&x.c, 0)
417 != sizeof (x) - __builtin_offsetof (struct B, c))
418 abort ();
419 if (__builtin_object_size (&x.c[0], 0)
420 != sizeof (x) - __builtin_offsetof (struct B, c))
421 abort ();
422 if (__builtin_object_size (&x.c[1], 0)
423 != sizeof (x) - __builtin_offsetof (struct B, c) - 1)
424 abort ();
425 if (__builtin_object_size (&x.d, 0)
426 != sizeof (x) - __builtin_offsetof (struct B, d))
427 abort ();
428 if (__builtin_object_size (&x.e, 0)
429 != sizeof (x) - __builtin_offsetof (struct B, e))
430 abort ();
431 if (__builtin_object_size (&x.f, 0)
432 != sizeof (x) - __builtin_offsetof (struct B, f))
433 abort ();
434 dp = &__real__ x.f;
435 if (__builtin_object_size (dp, 0)
436 != sizeof (x) - __builtin_offsetof (struct B, f))
437 abort ();
438 dp = &__imag__ x.f;
439 if (__builtin_object_size (dp, 0)
440 != sizeof (x) - __builtin_offsetof (struct B, f)
441 - sizeof (x.f) / 2)
442 abort ();
443 dp = &y;
444 if (__builtin_object_size (dp, 0) != sizeof (y))
445 abort ();
446 if (__builtin_object_size (&z, 0) != sizeof (z))
447 abort ();
448 dp = &__real__ z;
449 if (__builtin_object_size (dp, 0) != sizeof (z))
450 abort ();
451 dp = &__imag__ z;
452 if (__builtin_object_size (dp, 0) != sizeof (z) / 2)
453 abort ();
456 struct S { unsigned int a; };
458 char *
459 __attribute__ ((noinline))
460 test4 (char *x, int y)
462 register int i;
463 struct A *p;
465 for (i = 0; i < y; i++)
467 p = (struct A *) x;
468 x = (char *) &p[1];
469 if (__builtin_object_size (p, 0) != (size_t) -1)
470 abort ();
472 return x;
475 void
476 __attribute__ ((noinline))
477 test5 (size_t x)
479 char buf[64];
480 char *p = &buf[8];
481 size_t i;
483 for (i = 0; i < x; ++i)
484 p = p + 4;
485 #ifdef __builtin_object_size
486 if (__builtin_object_size (p, 0) != sizeof (buf) - 8 - 4 * x)
487 abort ();
488 #else
489 /* My understanding of ISO C99 6.5.6 is that a conforming
490 program will not end up with p equal to &buf[0]
491 through &buf[7], i.e. calling this function with say
492 UINTPTR_MAX / 4 results in undefined behavior.
493 If that's true, then the maximum number of remaining
494 bytes from p until end of the object is 56, otherwise
495 it would be 64 (or conservative (size_t) -1 == unknown). */
496 if (__builtin_object_size (p, 0) != sizeof (buf) - 8)
497 abort ();
498 #endif
499 memset (p, ' ', sizeof (buf) - 8 - 4 * 4);
502 void
503 __attribute__ ((noinline))
504 test6 (size_t x)
506 struct T { char buf[64]; char buf2[64]; } t;
507 char *p = &t.buf[8];
508 size_t i;
510 for (i = 0; i < x; ++i)
511 p = p + 4;
512 #ifdef __builtin_object_size
513 if (__builtin_object_size (p, 0) != sizeof (t) - 8 - 4 * x)
514 abort ();
515 #else
516 if (__builtin_object_size (p, 0) != sizeof (t) - 8)
517 abort ();
518 #endif
519 memset (p, ' ', sizeof (t) - 8 - 4 * 4);
522 void
523 __attribute__ ((noinline))
524 test7 (void)
526 char buf[64];
527 struct T { char buf[64]; char buf2[64]; } t;
528 char *p = &buf[64], *q = &t.buf[64];
530 if (__builtin_object_size (p + 64, 0) != 0)
531 abort ();
532 if (__builtin_object_size (q + 63, 0) != sizeof (t) - 64 - 63)
533 abort ();
534 if (__builtin_object_size (q + 64, 0) != sizeof (t) - 64 - 64)
535 abort ();
536 if (__builtin_object_size (q + 256, 0) != 0)
537 abort ();
540 void
541 __attribute__ ((noinline))
542 test8 (void)
544 struct T { char buf[10]; char buf2[10]; } t;
545 char *p = &t.buf2[-4];
546 char *q = &t.buf2[0];
547 if (__builtin_object_size (p, 0) != sizeof (t) - 10 + 4)
548 abort ();
549 if (__builtin_object_size (q, 0) != sizeof (t) - 10)
550 abort ();
551 /* GCC only handles additions, not subtractions. */
552 q = q - 8;
553 if (__builtin_object_size (q, 0) != (size_t) -1
554 && __builtin_object_size (q, 0) != sizeof (t) - 10 + 8)
555 abort ();
556 p = &t.buf[-4];
557 if (__builtin_object_size (p, 0) != 0)
558 abort ();
561 void
562 __attribute__ ((noinline))
563 test9 (unsigned cond)
565 char *buf2 = malloc (10);
566 char *p;
568 if (cond)
569 p = &buf2[8];
570 else
571 p = &buf2[4];
573 #ifdef __builtin_object_size
574 if (__builtin_object_size (&p[-4], 0) != (cond ? 6 : 10))
575 abort ();
576 #else
577 if (__builtin_object_size (&p[-4], 0) != 10)
578 abort ();
579 #endif
581 for (unsigned i = cond; i > 0; i--)
582 p--;
584 #ifdef __builtin_object_size
585 if (__builtin_object_size (p, 0) != ((cond ? 2 : 6) + cond))
586 abort ();
587 #else
588 if (__builtin_object_size (p, 0) != 10)
589 abort ();
590 #endif
592 p = &y.c[8];
593 for (unsigned i = cond; i > 0; i--)
594 p--;
596 #ifdef __builtin_object_size
597 if (__builtin_object_size (p, 0)
598 != sizeof (y) - __builtin_offsetof (struct A, c) - 8 + cond)
599 abort ();
600 #else
601 if (__builtin_object_size (p, 0) != sizeof (y))
602 abort ();
603 #endif
606 void
607 __attribute__ ((noinline))
608 test10 (void)
610 static char buf[255];
611 unsigned int i, len = sizeof (buf);
612 char *p = buf;
614 for (i = 0 ; i < sizeof (buf) ; i++)
616 if (len < 2)
618 #ifdef __builtin_object_size
619 if (__builtin_object_size (p - 3, 0) != sizeof (buf) - i + 3)
620 abort ();
621 #else
622 if (__builtin_object_size (p - 3, 0) != sizeof (buf))
623 abort ();
624 #endif
625 break;
627 p++;
628 len--;
633 main (void)
635 struct S s[10];
636 __asm ("" : "=r" (l1) : "0" (l1));
637 test1 (main, 6);
638 test2 ();
639 test3 ();
640 test4 ((char *) s, 10);
641 test5 (4);
642 test6 (4);
643 test7 ();
644 test8 ();
645 test9 (1);
646 test10 ();
647 exit (0);