blob: 7fb96514f1ddff13b346fcf0554abf7625562f39 [file] [log] [blame]
/* PR tree-optimization/35503 - Warning about restricted pointers?
{ dg-do compile }
{ dg-options "-O2 -Wno-format-overflow -Wrestrict -ftrack-macro-expansion=0" }
*/
void sink (int);
#define S10 "0123456789"
extern char a2[2][22];
#define T(d, ...) do { \
char a[22] = S10; \
sink (__builtin_sprintf ((d), __VA_ARGS__)); \
} while (0)
void test_ptr (char *d, int i)
{
T (d, "%s", d); /* { dg-warning "argument 3 overlaps destination object 'd'" } */
T (d, "%s", d + 0); /* { dg-warning "overlaps" } */
/* The following only overlaps if d[1] is non-zero. */
T (d, "%s", d + 1); /* { dg-warning "may overlap" } */
T (d, "%s", d + 2); /* { dg-warning "may overlap" } */
T (d, "%s", d + i); /* { dg-warning "may overlap" } */
T (d, "%s", &d[0]); /* { dg-warning "overlaps" } */
T (d, "%s", &d[1]); /* { dg-warning "may overlap" } */
T (d, "%s", &d[2]); /* { dg-warning "may overlap" } */
T (d, "%s", &d[i]); /* { dg-warning "may overlap" } */
T (d + 0, "%s", d); /* { dg-warning "overlaps" } */
T (d + 1, "%s", d); /* { dg-warning "may overlap" } */
T (d + 2, "%s", d); /* { dg-warning "may overlap" } */
T (d + i, "%s", d); /* { dg-warning "may overlap" } */
T (&d[0], "%s", d); /* { dg-warning "overlaps" } */
T (&d[1], "%s", d); /* { dg-warning "may overlap" } */
T (&d[2], "%s", d); /* { dg-warning "may overlap" } */
T (&d[i], "%s", d); /* { dg-warning "may overlap" } */
const char *s = d;
T (d, "%s", s); /* { dg-warning "overlaps" } */
T (d, "%s", s + 1); /* { dg-warning "may overlap" } */
T (d, "%s", s + 2); /* { dg-warning "may overlap" } */
T (d, "%s", s + i); /* { dg-warning "may overlap" } */
}
void test_ptr_plus (char *d, int i)
{
const char *s = d;
T (d, "%s", s++); /* { dg-warning "overlaps" } */
T (d, "%s", s++); /* { dg-warning "may overlap" } */
T (d, "%s", s++); /* { dg-warning "may overlap" } */
T (d, "%s", s++); /* { dg-warning "may overlap" } */
s += i;
T (d, "%s", s); /* { dg-warning "may overlap" } */
}
void test_array_1_dim (int i)
{
T (a, "%s", a); /* { dg-warning "overlaps" } */
T (a, "%s", a + 0); /* { dg-warning "overlaps" } */
T (a, "%s", a + 1); /* { dg-warning "overlaps" } */
T (a, "%s", a + 2); /* { dg-warning "overlaps" } */
T (a, "%s", a + i); /* { dg-warning "may overlap" } */
T (a, "%s", &a[0]); /* { dg-warning "overlaps" } */
T (a, "%s", &a[1]); /* { dg-warning "overlaps" } */
T (a, "%s", &a[2]); /* { dg-warning "overlaps" } */
T (a, "%s", &a[i]); /* { dg-warning "may overlap" } */
T (a + 0, "%s", a); /* { dg-warning "overlaps" } */
T (a + 1, "%s", a); /* { dg-warning "overlaps" } */
T (a + 2, "%s", a); /* { dg-warning "overlaps" } */
T (a + i, "%s", a); /* { dg-warning "may overlap" } */
T (&a[0], "%s", a); /* { dg-warning "overlaps" } */
T (&a[1], "%s", a); /* { dg-warning "overlaps" } */
T (&a[2], "%s", a); /* { dg-warning "overlaps" } */
T (&a[i], "%s", a); /* { dg-warning "may overlap" } */
}
void test_array_2_dim (int i)
{
T (a2[0], "%s", a2[0]); /* { dg-warning "overlaps" } */
T (a2[0], "%s", a2[0] + 0); /* { dg-warning "overlaps" } */
T (a2[0], "%s", a2[0] + 1); /* { dg-warning "may overlap" } */
T (a2[0], "%s", a2[0] + 2); /* { dg-warning "may overlap" } */
T (a2[0], "%s", a2[0] + i); /* { dg-warning "may overlap" } */
T (a2[0], "%s", &a2[0][0]); /* { dg-warning "overlaps" } */
T (a2[0], "%s", &a2[0][1]); /* { dg-warning "may overlap" } */
T (a2[0], "%s", &a2[0][2]); /* { dg-warning "may overlap" } */
T (a2[0], "%s", &a2[0][i]); /* { dg-warning "may overlap" } */
T (a2[0] + 0, "%s", a2[0]); /* { dg-warning "overlaps" } */
T (a2[0] + 1, "%s", a2[0]); /* { dg-warning "may overlap" } */
T (a2[0] + 2, "%s", a2[0]); /* { dg-warning "may overlap" } */
T (a2[0] + i, "%s", a2[0]); /* { dg-warning "may overlap" } */
T (&a2[0][0], "%s", a2[0]); /* { dg-warning "overlaps" } */
T (&a2[0][1], "%s", a2[0]); /* { dg-warning "may overlap" } */
T (&a2[0][2], "%s", a2[0]); /* { dg-warning "may overlap" } */
T (&a2[0][i], "%s", a2[0]); /* { dg-warning "may overlap" } */
T (a2[0], "%s", a2[1]);
T (a2[0], "%s", a2[1] + 0);
T (a2[0], "%s", a2[1] + 1);
T (a2[0], "%s", a2[1] + 2);
T (a2[0], "%s", a2[1] + i);
T (a2[0], "%s", &a2[1][0]);
T (a2[0], "%s", &a2[1][1]);
T (a2[0], "%s", &a2[1][2]);
/* a2[0] is represented as &a in Gimple, and &a2[1][i] as &a + _2,
with _1 defined to something like 10 + _1, and _1 to i. That
makes it virtually impossible to reliably determine that the
two pointers refer to distinct sub-arrays of the same multi-
dimensional array. */
T (a2[0], "%s", &a2[1][i]); /* { dg-bogus "overlap" "" { xfail *-*-* } } */
T (a2[0] + 0, "%s", a2[1]);
T (a2[0] + 1, "%s", a2[1]);
T (a2[0] + 2, "%s", a2[1]);
T (a2[0] + i, "%s", a2[1]);
T (&a2[0][0], "%s", a2[1]);
T (&a2[0][1], "%s", a2[1]);
T (&a2[0][2], "%s", a2[1]);
T (&a2[0][i], "%s", a2[1]);
T (a2[1], "%s", a2[0]);
T (a2[1], "%s", a2[0] + 0);
T (a2[1], "%s", a2[0] + 1);
T (a2[1], "%s", a2[0] + 2);
T (a2[1], "%s", a2[0] + i);
T (a2[1], "%s", &a2[0][0]);
T (a2[1], "%s", &a2[0][1]);
T (a2[1], "%s", &a2[0][2]);
T (a2[1], "%s", &a2[0][i]);
T (a2[1] + 0, "%s", a2[0]);
T (a2[1] + 1, "%s", a2[0]);
T (a2[1] + 2, "%s", a2[0]);
T (a2[1] + i, "%s", a2[0]);
T (&a2[1][0], "%s", a2[0]);
T (&a2[1][1], "%s", a2[0]);
T (&a2[1][2], "%s", a2[0]);
T (&a2[1][i], "%s", a2[0]); /* { dg-bogus "overlap" "" { xfail *-*-* } } */
T (a2[1], "%s", a2[1]); /* { dg-warning "overlaps" } */
T (a2[1], "%s", a2[1] + 0); /* { dg-warning "overlaps" } */
T (a2[1], "%s", a2[1] + 1); /* { dg-warning "may overlap" } */
T (a2[1], "%s", a2[1] + 2); /* { dg-warning "may overlap" } */
T (a2[1], "%s", a2[1] + i); /* { dg-warning "may overlap" } */
T (a2[1], "%s", &a2[1][0]); /* { dg-warning "overlaps" } */
T (a2[1], "%s", &a2[1][1]); /* { dg-warning "may overlap" } */
T (a2[1], "%s", &a2[1][2]); /* { dg-warning "may overlap" } */
T (a2[1], "%s", &a2[1][i]); /* { dg-warning "may overlap" "" { xfail *-*-* } } */
T (a2[1] + 0, "%s", a2[1]); /* { dg-warning "overlaps" } */
T (a2[1] + 1, "%s", a2[1]); /* { dg-warning "may overlap" } */
T (a2[1] + 2, "%s", a2[1]); /* { dg-warning "may overlap" } */
T (a2[1] + i, "%s", a2[1]); /* { dg-warning "may overlap" } */
T (&a2[1][0], "%s", a2[1]); /* { dg-warning "overlaps" } */
T (&a2[1][1], "%s", a2[1]); /* { dg-warning "may overlap" } */
T (&a2[1][2], "%s", a2[1]); /* { dg-warning "may overlap" } */
T (&a2[1][i], "%s", a2[1]); /* { dg-warning "may overlap" "" { xfail *-*-* } } */
}
struct S {
char a[4];
char b[4];
};
struct S2 {
struct S s_1;
struct S s_2;
struct S sa3[3];
};
struct S3 {
struct S2 s2_1;
struct S2 s2_2;
struct {
struct {
struct {
struct S sa_3[3];
} a_1[3];
} a_2[3][3];
} a_3[3][3][3];
char fa[];
};
void test_struct_member_array (struct S3 *s3, int i)
{
char *d = s3->s2_1.s_1.a;
T (d, "%s", d); /* { dg-warning "overlaps" } */
T (d, "%s", d + 0); /* { dg-warning "overlaps" } */
T (d, "%s", d + 1); /* { dg-warning "may overlap" } */
T (d, "%s", d + 2); /* { dg-warning "may overlap" } */
T (d, "%s", d + i); /* { dg-warning "may overlap" } */
T (d, "%s", &d[0]); /* { dg-warning "overlaps" } */
T (d, "%s", &d[1]); /* { dg-warning "may overlap" } */
T (d, "%s", &d[2]); /* { dg-warning "may overlap" } */
T (d, "%s", &d[i]); /* { dg-warning "may overlap" } */
T (d + 0, "%s", d); /* { dg-warning "overlaps" } */
T (d + 1, "%s", d); /* { dg-warning "may overlap" } */
T (d + 2, "%s", d); /* { dg-warning "may overlap" } */
T (d + i, "%s", d); /* { dg-warning "may overlap" } */
T (&d[0], "%s", d); /* { dg-warning "overlaps" } */
T (&d[1], "%s", d); /* { dg-warning "may overlap" } */
T (&d[2], "%s", d); /* { dg-warning "may overlap" } */
T (&d[i], "%s", d); /* { dg-warning "may overlap" } */
const char *s = d;
T (d, "%s", s); /* { dg-warning "overlaps" } */
T (d, "%s", s + 1); /* { dg-warning "may overlap" } */
T (d, "%s", s + 2); /* { dg-warning "may overlap" } */
T (d, "%s", s + i); /* { dg-warning "may overlap" } */
s = s3->s2_1.s_1.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_1.s_2.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_1.s_2.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
d = s3->s2_1.s_1.b;
s = s3->s2_1.s_2.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_1.s_2.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_2.s_1.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_2.s_1.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_2.s_2.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_2.s_2.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
d = s3->s2_2.s_1.a;
s = s3->s2_1.s_1.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_1.s_1.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_2.s_1.a;
T (d, "%s", s); /* { dg-warning "overlaps" } */
T (d, "%s", s + 1); /* { dg-warning "may overlap" } */
T (d, "%s", s + 2); /* { dg-warning "may overlap" } */
T (d, "%s", s + i); /* { dg-warning "may overlap" } */
s = s3->s2_2.s_2.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_2.s_2.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
d = s3->s2_2.s_1.b;
s = s3->s2_1.s_1.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_1.s_1.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_2.s_1.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_2.s_1.b;
T (d, "%s", s); /* { dg-warning "overlaps" } */
T (d, "%s", s + 1); /* { dg-warning "may overlap" } */
T (d, "%s", s + 2); /* { dg-warning "may overlap" } */
T (d, "%s", s + i); /* { dg-warning "may overlap" } */
s = s3->s2_2.s_2.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = s3->s2_2.s_2.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
}
void test_struct_member_array_array (struct S3 *s3, int i)
{
char *d = s3->s2_1.sa3[0].a;
char *s = s3->s2_1.sa3[0].a;
T (d, "%s", s); /* { dg-warning "overlaps" } */
T (d, "%s", s + 0); /* { dg-warning "overlaps" } */
T (d, "%s", s + 1); /* { dg-warning "may overlap" } */
T (d, "%s", s + 2); /* { dg-warning "may overlap" } */
T (d, "%s", s + i); /* { dg-warning "may overlap" } */
T (d, "%s", &s[0]); /* { dg-warning "overlaps" } */
T (d, "%s", &s[1]); /* { dg-warning "may overlap" } */
T (d, "%s", &s[2]); /* { dg-warning "may overlap" } */
T (d, "%s", &s[i]); /* { dg-warning "may overlap" } */
T (d + 0, "%s", s); /* { dg-warning "overlaps" } */
T (d + 1, "%s", s); /* { dg-warning "may overlap" } */
T (d + 2, "%s", s); /* { dg-warning "may overlap" } */
T (d + i, "%s", s); /* { dg-warning "may overlap" } */
T (&d[0], "%s", s); /* { dg-warning "overlaps" } */
T (&d[1], "%s", s); /* { dg-warning "may overlap" } */
T (&d[2], "%s", s); /* { dg-warning "may overlap" } */
T (&d[i], "%s", s); /* { dg-warning "may overlap" } */
s = s3->s2_1.sa3[0].b;
T (d, "%s", s);
T (d, "%s", s + 0);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
T (d, "%s", &s[0]);
T (d, "%s", &s[1]);
T (d, "%s", &s[2]);
T (d, "%s", &s[i]);
T (d + 0, "%s", s);
T (d + 1, "%s", s);
T (d + 2, "%s", s);
T (d + i, "%s", s);
T (&d[0], "%s", s);
T (&d[1], "%s", s);
T (&d[2], "%s", s);
T (&d[i], "%s", s);
}
void test_struct_member_nested_array (struct S3 *s3, int i)
{
#define PFX(sfx) s3->a_3[i3_0][i3_1][i3_2] \
.a_2[i2_0][i2_1] \
.a_1[i1_0].sfx
#define TT(d, s) \
T (PFX (d), "%s", PFX (s)); \
T (PFX (d), "%s", &PFX (s)[0]); \
T (PFX (d), "%s", &PFX (s)[1]); \
T (PFX (d), "%s", &PFX (s)[2]); \
T (PFX (d), "%s", &PFX (s)[i]) \
#define T1(i0) do \
{ \
enum {i1_0 = i0 }; \
\
TT (sa_3[0].a, sa_3[0].b); TT (sa_3[0].b, sa_3[0].a); \
\
TT (sa_3[0].a, sa_3[1].a); TT (sa_3[0].a, sa_3[1].b); \
TT (sa_3[0].b, sa_3[1].a); TT (sa_3[0].b, sa_3[1].b); \
\
TT (sa_3[0].a, sa_3[2].a); TT (sa_3[0].a, sa_3[2].b); \
TT (sa_3[0].b, sa_3[2].a); TT (sa_3[0].b, sa_3[2].b); \
\
TT (sa_3[1].a, sa_3[0].a); TT (sa_3[1].a, sa_3[0].b); \
TT (sa_3[1].b, sa_3[0].a); TT (sa_3[1].b, sa_3[0].b); \
\
TT (sa_3[1].a, sa_3[1].b); TT (sa_3[1].b, sa_3[1].a); \
\
TT (sa_3[1].a, sa_3[2].a); TT (sa_3[1].a, sa_3[2].b); \
TT (sa_3[1].b, sa_3[2].a); TT (sa_3[1].b, sa_3[2].b); \
} while (0)
#define T2(i0, i1) do \
{ \
enum { i2_0 = i0, i2_1 = i1 }; \
T1 (0); T1 (1); T1 (2); \
} while (0)
#define T3(i0, i1, i2) do \
{ \
enum { i3_0 = i0, i3_1 = i1, i3_2 = i2 }; \
T2 (0, 0); T2 (0, 1); T2 (0, 2); \
T2 (1, 0); T2 (1, 1); T2 (1, 2); \
T2 (2, 0); T2 (2, 1); T2 (2, 2); \
} while (0)
#if 0
/* These tests take forever and a day to compile. Enable them only
during the development of this feature but leave them otherwise
disabled to avoid slowing everything down for others. */
T3 (0, 0, 0); T3 (0, 0, 1); T3 (0, 0, 2);
T3 (0, 1, 0); T3 (0, 1, 1); T3 (0, 1, 2);
T3 (0, 2, 0); T3 (0, 2, 1); T3 (0, 2, 2);
T3 (1, 0, 0); T3 (1, 0, 1); T3 (1, 0, 2);
T3 (1, 1, 0); T3 (1, 1, 1); T3 (1, 1, 2);
T3 (1, 2, 0); T3 (1, 2, 1); T3 (1, 2, 2);
T3 (2, 0, 0); T3 (2, 0, 1); T3 (2, 0, 2);
T3 (2, 1, 0); T3 (2, 1, 1); T3 (2, 1, 2);
T3 (2, 2, 0); T3 (2, 2, 1); T3 (2, 2, 2);
#endif
}
void test_struct_member_flexarray (struct S3 *s3, int i, int j)
{
char *d = s3->fa;
char *s = s3->fa;
T (d, "%s", s); /* { dg-warning "overlaps" } */
T (d, "%s", s + 0); /* { dg-warning "overlaps" } */
T (d, "%s", s + 1); /* { dg-warning "may overlap" } */
T (d, "%s", s + 2); /* { dg-warning "may overlap" } */
T (d, "%s", s + i); /* { dg-warning "may overlap" } */
T (d, "%s", &s[0]); /* { dg-warning "overlaps" } */
T (d, "%s", &s[1]); /* { dg-warning "may overlap" } */
T (d, "%s", &s[2]); /* { dg-warning "may overlap" } */
T (d, "%s", &s[i]); /* { dg-warning "may overlap" } */
T (d + 0, "%s", s); /* { dg-warning "overlaps" } */
T (d + 1, "%s", s); /* { dg-warning "may overlap" } */
T (d + 2, "%s", s); /* { dg-warning "may overlap" } */
T (d + i, "%s", s); /* { dg-warning "may overlap" } */
T (&d[0], "%s", s); /* { dg-warning "overlaps" } */
T (&d[1], "%s", s); /* { dg-warning "may overlap" } */
T (&d[2], "%s", s); /* { dg-warning "may overlap" } */
T (&d[i], "%s", s); /* { dg-warning "may overlap" } */
d = s3->fa + i;
s = s3->fa + j;
T (d, "%s", s); /* { dg-warning "may overlap" } */
T (d, "%s", s + 0); /* { dg-warning "may overlap" } */
T (d, "%s", s + 1); /* { dg-warning "may overlap" } */
T (d, "%s", s + 2); /* { dg-warning "may overlap" } */
T (d, "%s", s + i); /* { dg-warning "may overlap" } */
T (d, "%s", &s[0]); /* { dg-warning "may overlap" } */
T (d, "%s", &s[1]); /* { dg-warning "may overlap" } */
T (d, "%s", &s[2]); /* { dg-warning "may overlap" } */
T (d, "%s", &s[i]); /* { dg-warning "may overlap" } */
T (d + 0, "%s", s); /* { dg-warning "may overlap" } */
T (d + 1, "%s", s); /* { dg-warning "may overlap" } */
T (d + 2, "%s", s); /* { dg-warning "may overlap" } */
T (d + j, "%s", s); /* { dg-warning "may overlap" } */
T (&d[0], "%s", s); /* { dg-warning "may overlap" } */
T (&d[1], "%s", s); /* { dg-warning "may overlap" } */
T (&d[2], "%s", s); /* { dg-warning "may overlap" } */
T (&d[j], "%s", s); /* { dg-warning "may overlap" } */
}
union U
{
struct S2 s2_1;
struct S2 s2_2;
};
void test_union_member_array (union U *un, int i)
{
char *d = un->s2_1.s_1.a;
T (d, "%s", d); /* { dg-warning "overlaps" } */
T (d, "%s", d + 0); /* { dg-warning "overlaps" } */
T (d, "%s", d + 1); /* { dg-warning "may overlap" } */
T (d, "%s", d + 2); /* { dg-warning "may overlap" } */
T (d, "%s", d + i); /* { dg-warning "may overlap" } */
T (d, "%s", &d[0]); /* { dg-warning "overlaps" } */
T (d, "%s", &d[1]); /* { dg-warning "may overlap" } */
T (d, "%s", &d[2]); /* { dg-warning "may overlap" } */
T (d, "%s", &d[i]); /* { dg-warning "may overlap" } */
T (d + 0, "%s", d); /* { dg-warning "overlaps" } */
T (d + 1, "%s", d); /* { dg-warning "may overlap" } */
T (d + 2, "%s", d); /* { dg-warning "may overlap" } */
T (d + i, "%s", d); /* { dg-warning "may overlap" } */
T (&d[0], "%s", d); /* { dg-warning "overlaps" } */
T (&d[1], "%s", d); /* { dg-warning "may overlap" } */
T (&d[2], "%s", d); /* { dg-warning "may overlap" } */
T (&d[i], "%s", d); /* { dg-warning "may overlap" } */
const char *s = d;
T (d, "%s", s); /* { dg-warning "overlaps" } */
T (d, "%s", s + 1); /* { dg-warning "may overlap" } */
T (d, "%s", s + 2); /* { dg-warning "may overlap" } */
T (d, "%s", s + i); /* { dg-warning "may overlap" } */
s = un->s2_1.s_1.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = un->s2_1.s_2.a;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = un->s2_1.s_2.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
s = un->s2_2.s_1.a;
T (d, "%s", s); /* { dg-warning "overlaps" } */
T (d, "%s", s + 1); /* { dg-warning "may overlap" } */
T (d, "%s", s + 2); /* { dg-warning "may overlap" } */
T (d, "%s", s + i); /* { dg-warning "may overlap" } */
s = un->s2_2.s_1.b;
T (d, "%s", s);
T (d, "%s", s + 1);
T (d, "%s", s + 2);
T (d, "%s", s + i);
}
void test_multiple_overlap (int i)
{
{
char a[3] = ""; /* { dg-message "declared here" } */
/* Both a3 and a4 definitely overlap the output even if the are
empty because of the terminating nul. */
char *d = a;
char *a3 = a + 0;
char *a4 = a - 0;
T (d, "%s%s", a3, a4); /* { dg-warning "arguments 3, 4 overlap destination object .a." }*/
}
{
char a[4];
/* There is no overlap here because the length of a3 is at most 1
and a4 is necessarily the empty string. */
char *d = a;
char *a3 = a + 2;
char *a4 = a + 3;
T (d, "%s%s", a3, a4);
}
{
char a[5]; /* { dg-message "declared here" } */
/* a3 and a4 may overlap the output. They will only not overlap
it when a3 is empty, and a4 is at most 1 character long. */
char *d = a;
char *a3 = a + 2;
char *a4 = a + 3;
T (d, "%s%s", a3, a4); /* { dg-warning "arguments 3, 4 may overlap destination object .a." }*/
}
{
char a[5]; /* { dg-message "declared here" } */
/* a3 certaibly overlaps the output, but a4 may or may not depending
in the value of i. */
char *d = a;
char *a3 = a + 0;
char *a4 = a + i;
T (d, "%s%s", a3, a4); /* { dg-warning "arguments 3 and maybe 4 overlap destination object .a." }*/
}
}
void test_overlap_with_precision (char *d, int i, int j)
{
/* None of the following is diagnosed because no copying takes place
between the %s argument and the destination. */
T (d, "%.0s", d + 0);
T (d, "%.0s", d + 1);
T (d, "%.0s", d + 2);
T (d, "%.0s", d + i);
T (d, "%.1s", d + 0); /* { dg-warning "overlaps" } */
/* Unlike the %.0s case the following deserves a warning because
when d[1] isn't nul, it will be overwritten by the terminating
nul added by sprintf. */
T (d, "%.1s", d + 1); /* { dg-warning "may overlap" } */
T (d, "%.1s", d + 2);
T (d, "%.1s", d + i); /* { dg-warning "may overlap" } */
T (d + 1, "%.0s", d);
T (d + 2, "%.0s", d);
T (d + 1, "%.1s", d); /* { dg-warning "may overlap" } */
T (d + 2, "%.1s", d);
T (d + 2, "%.1s", d + 1); /* { dg-warning "may overlap" } */
T (d + 2, "%.1s", d + i); /* { dg-warning "may overlap" } */
/* The following should be "overlaps" but tracking that the offset
is the same variable doesn't seem worth the effort. */
T (d + i, "%.1s", d + i); /* { dg-warning "overlap" } */
T (d + i, "%.1s", d + j); /* { dg-warning "may overlap" } */
/* Exercise overlap with precison in the range [0, 1]. */
if (i < 0 || 1 < i)
i = 0;
T (d, "%.*s", i, d + 0); /* { dg-warning "may overlap" } */
T (d, "%.*s", i, d + 1); /* { dg-warning "may overlap" } */
T (d, "%.*s", i, d + 2);
T (d, "%.*s", i, d + i); /* { dg-warning "may overlap" "" { xfail *-*-* } } */
}