|  | /* Exercise that -Warray-bounds is issued for out-of-bounds offsets | 
|  | in calls to built-in functions. | 
|  | { dg-do compile } | 
|  | { dg-options "-O2 -Warray-bounds=2 -Wno-stringop-overflow -ftrack-macro-expansion=0" }  */ | 
|  |  | 
|  | #include "../gcc.dg/range.h" | 
|  |  | 
|  | #if __cplusplus | 
|  | #  define restrict __restrict | 
|  | extern "C" { | 
|  | #endif | 
|  |  | 
|  | extern void* memcpy (void* restrict, const void* restrict, size_t); | 
|  | extern void* mempcpy (void* restrict, const void* restrict, size_t); | 
|  | extern void* memmove (void*, const void*, size_t); | 
|  |  | 
|  | extern char* stpcpy (char* restrict, const char* restrict); | 
|  |  | 
|  | extern char* strcat (char* restrict, const char* restrict); | 
|  | extern char* strcpy (char* restrict, const char* restrict); | 
|  | extern char* strncpy (char* restrict, const char* restrict, size_t); | 
|  |  | 
|  | #if __cplusplus | 
|  | }   /* extern "C" */ | 
|  | #endif | 
|  |  | 
|  | struct MA { char a5[5], a7[7]; }; | 
|  |  | 
|  | void sink (void*, ...); | 
|  |  | 
|  | void test_memcpy_bounds_memarray_range (void) | 
|  | { | 
|  | #undef TM | 
|  | #define TM(mem, dst, src, n)			\ | 
|  | do {						\ | 
|  | struct MA ma;				\ | 
|  | sink (&ma);   /* Initialize arrays.  */	\ | 
|  | memcpy (dst, src, n);			\ | 
|  | sink (&ma);					\ | 
|  | } while (0) | 
|  |  | 
|  | ptrdiff_t j = SR (1, 2); | 
|  |  | 
|  | TM (ma.a5, ma.a5 + j, ma.a5, 1); | 
|  | TM (ma.a5, ma.a5 + j, ma.a5, 3); | 
|  |  | 
|  | /* The copy below is invalid for two reasons: 1) it overlaps and 2) it | 
|  | writes past the end of ma.a5.  The warning is a little cryptic here | 
|  | because the GIMPLE is: | 
|  | _4 = &ma.a5 + prephitmp_14; | 
|  | MEM <unsigned char[5]> [(char * {ref-all})_4] | 
|  | = MEM <unsigned char[5]> [(char * {ref-all})&ma]; | 
|  | and could be improved.  Just verify that one is issued but not its | 
|  | full text.  */ | 
|  | TM (ma.a5, ma.a5 + j, ma.a5, 5);        /* { dg-warning "\\\[-Warray-bounds" "pr101374" { xfail *-*-* } } */ | 
|  |  | 
|  | TM (ma.a5, ma.a5 + j, ma.a5, 7);        /* { dg-warning "offset \\\[5, 7] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */ | 
|  | TM (ma.a5, ma.a5 + j, ma.a5, 9);        /* { dg-warning "offset \\\[5, 9] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */ | 
|  | } | 
|  |  | 
|  | #if __i386__ || __x86_64__ | 
|  |  | 
|  | /* Disabled for non-x86 targets due to bug 83543.  */ | 
|  |  | 
|  | void test_strcpy_bounds_memarray_range (void) | 
|  | { | 
|  | #undef TM | 
|  | #define TM(a5init, a7init, dst, src)		\ | 
|  | do {						\ | 
|  | struct MA ma = { a5init, a7init };		\ | 
|  | strcpy (dst, src);				\ | 
|  | sink (&ma);					\ | 
|  | } while (0) | 
|  |  | 
|  | ptrdiff_t i = SR (1, 2); | 
|  |  | 
|  | TM ("0", "",     ma.a5 + i, ma.a5); | 
|  | TM ("01", "",    ma.a5 + i, ma.a5); | 
|  | TM ("012", "",   ma.a5 + i, ma.a5); | 
|  | TM ("0123", "",  ma.a5 + i, ma.a5);     /* { dg-warning "offset 5 from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char *\\\[5]. at offset 0" "pr83543" { xfail { ! { i?86-*-* x86_64-*-* } } } } */ | 
|  |  | 
|  | TM ("", "012345", ma.a7 + i, ma.a7);    /* { dg-warning "offset 12 from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a7. with type .char ?\\\[7]. at offset 5" "pr83543" { xfail { ! { i?86-*-* x86_64-*-* } } } } */ | 
|  | } | 
|  | #endif |