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