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