1 /* { dg-do run } */
2 /* { dg-options "-O2" } */
3 
4 typedef __SIZE_TYPE__ size_t;
5 extern void abort (void);
6 extern void exit (int);
7 extern void *malloc (size_t);
8 extern void *calloc (size_t, size_t);
9 extern void *alloca (size_t);
10 extern void *memcpy (void *, const void *, size_t);
11 extern void *memset (void *, int, size_t);
12 extern char *strcpy (char *, const char *);
13 
14 struct A
15 {
16   char a[10];
17   int b;
18   char c[10];
19 } y, w[4];
20 
21 extern char exta[];
22 extern char extb[30];
23 extern struct A zerol[0];
24 
25 void
26 __attribute__ ((noinline))
test1(void * q,int x)27 test1 (void *q, int x)
28 {
29   struct A a;
30   void *p = &a.a[3], *r;
31   char var[x + 10];
32   if (x < 0)
33     r = &a.a[9];
34   else
35     r = &a.c[1];
36   if (__builtin_object_size (p, 0)
37       != sizeof (a) - __builtin_offsetof (struct A, a) - 3)
38     abort ();
39   if (__builtin_object_size (&a.c[9], 0)
40       != sizeof (a) - __builtin_offsetof (struct A, c) - 9)
41     abort ();
42   if (__builtin_object_size (q, 0) != (size_t) -1)
43     abort ();
44   if (__builtin_object_size (r, 0)
45       != sizeof (a) - __builtin_offsetof (struct A, a) - 9)
46     abort ();
47   if (x < 6)
48     r = &w[2].a[1];
49   else
50     r = &a.a[6];
51   if (__builtin_object_size (&y, 0)
52       != sizeof (y))
53     abort ();
54   if (__builtin_object_size (w, 0)
55       != sizeof (w))
56     abort ();
57   if (__builtin_object_size (&y.b, 0)
58       != sizeof (a) - __builtin_offsetof (struct A, b))
59     abort ();
60   if (__builtin_object_size (r, 0)
61       != 2 * sizeof (w[0]) - __builtin_offsetof (struct A, a) - 1)
62     abort ();
63   if (x < 20)
64     r = malloc (30);
65   else
66     r = calloc (2, 16);
67   /* We may duplicate this test onto the two exit paths.  On one path
68      the size will be 32, the other it will be 30.  If we don't duplicate
69      this test, then the size will be 32.  */
70   if (__builtin_object_size (r, 0) != 2 * 16
71       && __builtin_object_size (r, 0) != 30)
72     abort ();
73   if (x < 20)
74     r = malloc (30);
75   else
76     r = calloc (2, 14);
77   if (__builtin_object_size (r, 0) != 30)
78     abort ();
79   if (x < 30)
80     r = malloc (sizeof (a));
81   else
82     r = &a.a[3];
83   if (__builtin_object_size (r, 0) != sizeof (a))
84     abort ();
85   r = memcpy (r, "a", 2);
86   if (__builtin_object_size (r, 0) != sizeof (a))
87     abort ();
88   r = memcpy (r + 2, "b", 2) + 2;
89   if (__builtin_object_size (r, 0) != sizeof (a) - 4)
90     abort ();
91   r = &a.a[4];
92   r = memset (r, 'a', 2);
93   if (__builtin_object_size (r, 0)
94       != sizeof (a) - __builtin_offsetof (struct A, a) - 4)
95     abort ();
96   r = memset (r + 2, 'b', 2) + 2;
97   if (__builtin_object_size (r, 0)
98       != sizeof (a) - __builtin_offsetof (struct A, a) - 8)
99     abort ();
100   r = &a.a[1];
101   r = strcpy (r, "ab");
102   if (__builtin_object_size (r, 0)
103       != sizeof (a) - __builtin_offsetof (struct A, a) - 1)
104     abort ();
105   r = strcpy (r + 2, "cd") + 2;
106   if (__builtin_object_size (r, 0)
107       != sizeof (a) - __builtin_offsetof (struct A, a) - 5)
108     abort ();
109   if (__builtin_object_size (exta, 0) != (size_t) -1)
110     abort ();
111   if (__builtin_object_size (exta + 10, 0) != (size_t) -1)
112     abort ();
113   if (__builtin_object_size (&exta[5], 0) != (size_t) -1)
114     abort ();
115   if (__builtin_object_size (extb, 0) != sizeof (extb))
116     abort ();
117   if (__builtin_object_size (extb + 10, 0) != sizeof (extb) - 10)
118     abort ();
119   if (__builtin_object_size (&extb[5], 0) != sizeof (extb) - 5)
120     abort ();
121   if (__builtin_object_size (var, 0) != (size_t) -1)
122     abort ();
123   if (__builtin_object_size (var + 10, 0) != (size_t) -1)
124     abort ();
125   if (__builtin_object_size (&var[5], 0) != (size_t) -1)
126     abort ();
127   if (__builtin_object_size (zerol, 0) != 0)
128     abort ();
129   if (__builtin_object_size (&zerol, 0) != 0)
130     abort ();
131   if (__builtin_object_size (&zerol[0], 0) != 0)
132     abort ();
133   if (__builtin_object_size (zerol[0].a, 0) != 0)
134     abort ();
135   if (__builtin_object_size (&zerol[0].a[0], 0) != 0)
136     abort ();
137   if (__builtin_object_size (&zerol[0].b, 0) != 0)
138     abort ();
139   if (__builtin_object_size ("abcdefg", 0) != sizeof ("abcdefg"))
140     abort ();
141   if (__builtin_object_size ("abcd\0efg", 0) != sizeof ("abcd\0efg"))
142     abort ();
143   if (__builtin_object_size (&"abcd\0efg", 0) != sizeof ("abcd\0efg"))
144     abort ();
145   if (__builtin_object_size (&"abcd\0efg"[0], 0) != sizeof ("abcd\0efg"))
146     abort ();
147   if (__builtin_object_size (&"abcd\0efg"[4], 0) != sizeof ("abcd\0efg") - 4)
148     abort ();
149   if (__builtin_object_size ("abcd\0efg" + 5, 0) != sizeof ("abcd\0efg") - 5)
150     abort ();
151   if (__builtin_object_size (L"abcdefg", 0) != sizeof (L"abcdefg"))
152     abort ();
153   r = (char *) L"abcd\0efg";
154   if (__builtin_object_size (r + 2, 0) != sizeof (L"abcd\0efg") - 2)
155     abort ();
156 }
157 
158 size_t l1 = 1;
159 
160 void
161 __attribute__ ((noinline))
test2(void)162 test2 (void)
163 {
164   struct B { char buf1[10]; char buf2[10]; } a;
165   char *r, buf3[20];
166   int i;
167 
168   if (sizeof (a) != 20)
169     return;
170 
171   r = buf3;
172   for (i = 0; i < 4; ++i)
173     {
174       if (i == l1 - 1)
175 	r = &a.buf1[1];
176       else if (i == l1)
177 	r = &a.buf2[7];
178       else if (i == l1 + 1)
179 	r = &buf3[5];
180       else if (i == l1 + 2)
181 	r = &a.buf1[9];
182     }
183   if (__builtin_object_size (r, 0) != 20)
184     abort ();
185   r = &buf3[20];
186   for (i = 0; i < 4; ++i)
187     {
188       if (i == l1 - 1)
189 	r = &a.buf1[7];
190       else if (i == l1)
191 	r = &a.buf2[7];
192       else if (i == l1 + 1)
193 	r = &buf3[5];
194       else if (i == l1 + 2)
195 	r = &a.buf1[9];
196     }
197   if (__builtin_object_size (r, 0) != 15)
198     abort ();
199   r += 8;
200   if (__builtin_object_size (r, 0) != 7)
201     abort ();
202   if (__builtin_object_size (r + 6, 0) != 1)
203     abort ();
204   r = &buf3[18];
205   for (i = 0; i < 4; ++i)
206     {
207       if (i == l1 - 1)
208 	r = &a.buf1[9];
209       else if (i == l1)
210 	r = &a.buf2[9];
211       else if (i == l1 + 1)
212 	r = &buf3[5];
213       else if (i == l1 + 2)
214 	r = &a.buf1[4];
215     }
216   if (__builtin_object_size (r + 12, 0) != 4)
217     abort ();
218 }
219 
220 void
221 __attribute__ ((noinline))
test3(void)222 test3 (void)
223 {
224   char buf4[10];
225   struct B { struct A a[2]; struct A b; char c[4]; char d; double e;
226 	     _Complex double f; } x;
227   double y;
228   _Complex double z;
229   double *dp;
230 
231   if (__builtin_object_size (buf4, 0) != sizeof (buf4))
232     abort ();
233   if (__builtin_object_size (&buf4, 0) != sizeof (buf4))
234     abort ();
235   if (__builtin_object_size (&buf4[0], 0) != sizeof (buf4))
236     abort ();
237   if (__builtin_object_size (&buf4[1], 0) != sizeof (buf4) - 1)
238     abort ();
239   if (__builtin_object_size (&x, 0) != sizeof (x))
240     abort ();
241   if (__builtin_object_size (&x.a, 0) != sizeof (x))
242     abort ();
243   if (__builtin_object_size (&x.a[0], 0) != sizeof (x))
244     abort ();
245   if (__builtin_object_size (&x.a[0].a, 0) != sizeof (x))
246     abort ();
247   if (__builtin_object_size (&x.a[0].a[0], 0) != sizeof (x))
248     abort ();
249   if (__builtin_object_size (&x.a[0].a[3], 0) != sizeof (x) - 3)
250     abort ();
251   if (__builtin_object_size (&x.a[0].b, 0)
252       != sizeof (x) - __builtin_offsetof (struct A, b))
253     abort ();
254   if (__builtin_object_size (&x.a[1].c, 0)
255       != sizeof (x) - sizeof (struct A) - __builtin_offsetof (struct A, c))
256     abort ();
257   if (__builtin_object_size (&x.a[1].c[0], 0)
258       != sizeof (x) - sizeof (struct A) - __builtin_offsetof (struct A, c))
259     abort ();
260   if (__builtin_object_size (&x.a[1].c[3], 0)
261       != sizeof (x) - sizeof (struct A) - __builtin_offsetof (struct A, c) - 3)
262     abort ();
263   if (__builtin_object_size (&x.b, 0)
264       != sizeof (x) - __builtin_offsetof (struct B, b))
265     abort ();
266   if (__builtin_object_size (&x.b.a, 0)
267       != sizeof (x) - __builtin_offsetof (struct B, b))
268     abort ();
269   if (__builtin_object_size (&x.b.a[0], 0)
270       != sizeof (x) - __builtin_offsetof (struct B, b))
271     abort ();
272   if (__builtin_object_size (&x.b.a[3], 0)
273       != sizeof (x) - __builtin_offsetof (struct B, b) - 3)
274     abort ();
275   if (__builtin_object_size (&x.b.b, 0)
276       != sizeof (x) - __builtin_offsetof (struct B, b)
277 	 - __builtin_offsetof (struct A, b))
278     abort ();
279   if (__builtin_object_size (&x.b.c, 0)
280       != sizeof (x) - __builtin_offsetof (struct B, b)
281 	 - __builtin_offsetof (struct A, c))
282     abort ();
283   if (__builtin_object_size (&x.b.c[0], 0)
284       != sizeof (x) - __builtin_offsetof (struct B, b)
285 	 - __builtin_offsetof (struct A, c))
286     abort ();
287   if (__builtin_object_size (&x.b.c[3], 0)
288       != sizeof (x) - __builtin_offsetof (struct B, b)
289 	 - __builtin_offsetof (struct A, c) - 3)
290     abort ();
291   if (__builtin_object_size (&x.c, 0)
292       != sizeof (x) - __builtin_offsetof (struct B, c))
293     abort ();
294   if (__builtin_object_size (&x.c[0], 0)
295       != sizeof (x) - __builtin_offsetof (struct B, c))
296     abort ();
297   if (__builtin_object_size (&x.c[1], 0)
298       != sizeof (x) - __builtin_offsetof (struct B, c) - 1)
299     abort ();
300   if (__builtin_object_size (&x.d, 0)
301       != sizeof (x) - __builtin_offsetof (struct B, d))
302     abort ();
303   if (__builtin_object_size (&x.e, 0)
304       != sizeof (x) - __builtin_offsetof (struct B, e))
305     abort ();
306   if (__builtin_object_size (&x.f, 0)
307       != sizeof (x) - __builtin_offsetof (struct B, f))
308     abort ();
309   dp = &__real__ x.f;
310   if (__builtin_object_size (dp, 0)
311       != sizeof (x) - __builtin_offsetof (struct B, f))
312     abort ();
313   dp = &__imag__ x.f;
314   if (__builtin_object_size (dp, 0)
315       != sizeof (x) - __builtin_offsetof (struct B, f)
316 	 - sizeof (x.f) / 2)
317     abort ();
318   dp = &y;
319   if (__builtin_object_size (dp, 0) != sizeof (y))
320     abort ();
321   if (__builtin_object_size (&z, 0) != sizeof (z))
322     abort ();
323   dp = &__real__ z;
324   if (__builtin_object_size (dp, 0) != sizeof (z))
325     abort ();
326   dp = &__imag__ z;
327   if (__builtin_object_size (dp, 0) != sizeof (z) / 2)
328     abort ();
329 }
330 
331 struct S { unsigned int a; };
332 
333 char *
334 __attribute__ ((noinline))
test4(char * x,int y)335 test4 (char *x, int y)
336 {
337   register int i;
338   struct A *p;
339 
340   for (i = 0; i < y; i++)
341     {
342       p = (struct A *) x;
343       x = (char *) &p[1];
344       if (__builtin_object_size (p, 0) != (size_t) -1)
345 	abort ();
346     }
347   return x;
348 }
349 
350 void
351 __attribute__ ((noinline))
test5(size_t x)352 test5 (size_t x)
353 {
354   char buf[64];
355   char *p = &buf[8];
356   size_t i;
357 
358   for (i = 0; i < x; ++i)
359     p = p + 4;
360   /* My understanding of ISO C99 6.5.6 is that a conforming
361      program will not end up with p equal to &buf[0]
362      through &buf[7], i.e. calling this function with say
363      UINTPTR_MAX / 4 results in undefined behaviour.
364      If that's true, then the maximum number of remaining
365      bytes from p until end of the object is 56, otherwise
366      it would be 64 (or conservative (size_t) -1 == unknown).  */
367   if (__builtin_object_size (p, 0) != sizeof (buf) - 8)
368     abort ();
369   memset (p, ' ', sizeof (buf) - 8 - 4 * 4);
370 }
371 
372 void
373 __attribute__ ((noinline))
test6(size_t x)374 test6 (size_t x)
375 {
376   struct T { char buf[64]; char buf2[64]; } t;
377   char *p = &t.buf[8];
378   size_t i;
379 
380   for (i = 0; i < x; ++i)
381     p = p + 4;
382   if (__builtin_object_size (p, 0) != sizeof (t) - 8)
383     abort ();
384   memset (p, ' ', sizeof (t) - 8 - 4 * 4);
385 }
386 
387 void
388 __attribute__ ((noinline))
test7(void)389 test7 (void)
390 {
391   char buf[64];
392   struct T { char buf[64]; char buf2[64]; } t;
393   char *p = &buf[64], *q = &t.buf[64];
394 
395   if (__builtin_object_size (p + 64, 0) != 0)
396     abort ();
397   if (__builtin_object_size (q + 63, 0) != sizeof (t) - 64 - 63)
398     abort ();
399   if (__builtin_object_size (q + 64, 0) != sizeof (t) - 64 - 64)
400     abort ();
401   if (__builtin_object_size (q + 256, 0) != 0)
402     abort ();
403 }
404 
405 void
406 __attribute__ ((noinline))
test8(void)407 test8 (void)
408 {
409   struct T { char buf[10]; char buf2[10]; } t;
410   char *p = &t.buf2[-4];
411   char *q = &t.buf2[0];
412   if (__builtin_object_size (p, 0) != sizeof (t) - 10 + 4)
413     abort ();
414   if (__builtin_object_size (q, 0) != sizeof (t) - 10)
415     abort ();
416   /* GCC only handles additions, not subtractions.  */
417   q = q - 8;
418   if (__builtin_object_size (q, 0) != (size_t) -1
419       && __builtin_object_size (q, 0) != sizeof (t) - 10 + 8)
420     abort ();
421   p = &t.buf[-4];
422   if (__builtin_object_size (p, 0) != 0)
423     abort ();
424 }
425 
426 int
main(void)427 main (void)
428 {
429   struct S s[10];
430   __asm ("" : "=r" (l1) : "0" (l1));
431   test1 (main, 6);
432   test2 ();
433   test3 ();
434   test4 ((char *) s, 10);
435   test5 (4);
436   test6 (4);
437   test7 ();
438   test8 ();
439   exit (0);
440 }
441