| /* 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 *-*-* } } */ |
| } |