(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
tree-ssa/
builtin-sprintf-warn-23.c
       1  /* PR tree-optimization/35503 - Warning about restricted pointers?
       2     { dg-do compile }
       3     { dg-options "-O2 -Wno-format-overflow -Wrestrict -ftrack-macro-expansion=0" }
       4  */
       5  
       6  void sink (int);
       7  
       8  #define S10 "0123456789"
       9  
      10  extern char a2[2][22];
      11  
      12  #define T(d, ...) do {					\
      13      char a[22] = S10;					\
      14      sink (__builtin_sprintf ((d), __VA_ARGS__));	\
      15    } while (0)
      16  
      17  void test_ptr (char *d, int i)
      18  {
      19    T (d, "%s", d);       /* { dg-warning "argument 3 overlaps destination object 'd'" } */
      20    T (d, "%s", d + 0);   /* { dg-warning "overlaps" } */
      21  
      22    /* The following only overlaps if d[1] is non-zero.  */
      23    T (d, "%s", d + 1);   /* { dg-warning "may overlap" } */
      24    T (d, "%s", d + 2);   /* { dg-warning "may overlap" } */
      25    T (d, "%s", d + i);   /* { dg-warning "may overlap" } */
      26  
      27    T (d, "%s", &d[0]);   /* { dg-warning "overlaps" } */
      28    T (d, "%s", &d[1]);   /* { dg-warning "may overlap" } */
      29    T (d, "%s", &d[2]);   /* { dg-warning "may overlap" } */
      30    T (d, "%s", &d[i]);   /* { dg-warning "may overlap" } */
      31  
      32    T (d + 0, "%s", d);   /* { dg-warning "overlaps" } */
      33    T (d + 1, "%s", d);   /* { dg-warning "may overlap" } */
      34    T (d + 2, "%s", d);   /* { dg-warning "may overlap" } */
      35    T (d + i, "%s", d);   /* { dg-warning "may overlap" } */
      36  
      37    T (&d[0], "%s", d);   /* { dg-warning "overlaps" } */
      38    T (&d[1], "%s", d);   /* { dg-warning "may overlap" } */
      39    T (&d[2], "%s", d);   /* { dg-warning "may overlap" } */
      40    T (&d[i], "%s", d);   /* { dg-warning "may overlap" } */
      41  
      42    const char *s = d;
      43  
      44    T (d, "%s", s);       /* { dg-warning "overlaps" } */
      45    T (d, "%s", s + 1);   /* { dg-warning "may overlap" } */
      46    T (d, "%s", s + 2);   /* { dg-warning "may overlap" } */
      47    T (d, "%s", s + i);   /* { dg-warning "may overlap" } */
      48  }
      49  
      50  void test_ptr_plus (char *d, int i)
      51  {
      52    const char *s = d;
      53  
      54    T (d, "%s", s++);     /* { dg-warning "overlaps" } */
      55    T (d, "%s", s++);     /* { dg-warning "may overlap" } */
      56    T (d, "%s", s++);     /* { dg-warning "may overlap" } */
      57    T (d, "%s", s++);     /* { dg-warning "may overlap" } */
      58  
      59    s += i;
      60    T (d, "%s", s);       /* { dg-warning "may overlap" } */
      61  }
      62  
      63  void test_array_1_dim (int i)
      64  {
      65    T (a, "%s", a);       /* { dg-warning "overlaps" } */
      66    T (a, "%s", a + 0);   /* { dg-warning "overlaps" } */
      67    T (a, "%s", a + 1);   /* { dg-warning "overlaps" } */
      68    T (a, "%s", a + 2);   /* { dg-warning "overlaps" } */
      69    T (a, "%s", a + i);   /* { dg-warning "may overlap" } */
      70  
      71    T (a, "%s", &a[0]);   /* { dg-warning "overlaps" } */
      72    T (a, "%s", &a[1]);   /* { dg-warning "overlaps" } */
      73    T (a, "%s", &a[2]);   /* { dg-warning "overlaps" } */
      74    T (a, "%s", &a[i]);   /* { dg-warning "may overlap" } */
      75  
      76    T (a + 0, "%s", a);   /* { dg-warning "overlaps" } */
      77    T (a + 1, "%s", a);   /* { dg-warning "overlaps" } */
      78    T (a + 2, "%s", a);   /* { dg-warning "overlaps" } */
      79    T (a + i, "%s", a);   /* { dg-warning "may overlap" } */
      80  
      81    T (&a[0], "%s", a);   /* { dg-warning "overlaps" } */
      82    T (&a[1], "%s", a);   /* { dg-warning "overlaps" } */
      83    T (&a[2], "%s", a);   /* { dg-warning "overlaps" } */
      84    T (&a[i], "%s", a);   /* { dg-warning "may overlap" } */
      85  }
      86  
      87  
      88  void test_array_2_dim (int i)
      89  {
      90    T (a2[0], "%s", a2[0]);       /* { dg-warning "overlaps" } */
      91    T (a2[0], "%s", a2[0] + 0);   /* { dg-warning "overlaps" } */
      92    T (a2[0], "%s", a2[0] + 1);   /* { dg-warning "may overlap" } */
      93    T (a2[0], "%s", a2[0] + 2);   /* { dg-warning "may overlap" } */
      94    T (a2[0], "%s", a2[0] + i);   /* { dg-warning "may overlap" } */
      95  
      96    T (a2[0], "%s", &a2[0][0]);   /* { dg-warning "overlaps" } */
      97    T (a2[0], "%s", &a2[0][1]);   /* { dg-warning "may overlap" } */
      98    T (a2[0], "%s", &a2[0][2]);   /* { dg-warning "may overlap" } */
      99    T (a2[0], "%s", &a2[0][i]);   /* { dg-warning "may overlap" } */
     100  
     101    T (a2[0] + 0, "%s", a2[0]);   /* { dg-warning "overlaps" } */
     102    T (a2[0] + 1, "%s", a2[0]);   /* { dg-warning "may overlap" } */
     103    T (a2[0] + 2, "%s", a2[0]);   /* { dg-warning "may overlap" } */
     104    T (a2[0] + i, "%s", a2[0]);   /* { dg-warning "may overlap" } */
     105  
     106    T (&a2[0][0], "%s", a2[0]);   /* { dg-warning "overlaps" } */
     107    T (&a2[0][1], "%s", a2[0]);   /* { dg-warning "may overlap" } */
     108    T (&a2[0][2], "%s", a2[0]);   /* { dg-warning "may overlap" } */
     109    T (&a2[0][i], "%s", a2[0]);   /* { dg-warning "may overlap" } */
     110  
     111  
     112    T (a2[0], "%s", a2[1]);
     113    T (a2[0], "%s", a2[1] + 0);
     114    T (a2[0], "%s", a2[1] + 1);
     115    T (a2[0], "%s", a2[1] + 2);
     116    T (a2[0], "%s", a2[1] + i);
     117  
     118    T (a2[0], "%s", &a2[1][0]);
     119    T (a2[0], "%s", &a2[1][1]);
     120    T (a2[0], "%s", &a2[1][2]);
     121  
     122    /* a2[0] is represented as &a in Gimple, and &a2[1][i] as &a + _2,
     123       with _1 defined to something like 10 + _1, and _1 to i.  That
     124       makes it virtually impossible to reliably determine that the
     125       two pointers refer to distinct sub-arrays of the same multi-
     126       dimensional array.  */
     127    T (a2[0], "%s", &a2[1][i]);   /* { dg-bogus "overlap" "" { xfail *-*-* } } */
     128  
     129    T (a2[0] + 0, "%s", a2[1]);
     130    T (a2[0] + 1, "%s", a2[1]);
     131    T (a2[0] + 2, "%s", a2[1]);
     132    T (a2[0] + i, "%s", a2[1]);
     133  
     134    T (&a2[0][0], "%s", a2[1]);
     135    T (&a2[0][1], "%s", a2[1]);
     136    T (&a2[0][2], "%s", a2[1]);
     137    T (&a2[0][i], "%s", a2[1]);
     138  
     139  
     140    T (a2[1], "%s", a2[0]);
     141    T (a2[1], "%s", a2[0] + 0);
     142    T (a2[1], "%s", a2[0] + 1);
     143    T (a2[1], "%s", a2[0] + 2);
     144    T (a2[1], "%s", a2[0] + i);
     145  
     146    T (a2[1], "%s", &a2[0][0]);
     147    T (a2[1], "%s", &a2[0][1]);
     148    T (a2[1], "%s", &a2[0][2]);
     149    T (a2[1], "%s", &a2[0][i]);
     150  
     151    T (a2[1] + 0, "%s", a2[0]);
     152    T (a2[1] + 1, "%s", a2[0]);
     153    T (a2[1] + 2, "%s", a2[0]);
     154    T (a2[1] + i, "%s", a2[0]);
     155  
     156    T (&a2[1][0], "%s", a2[0]);
     157    T (&a2[1][1], "%s", a2[0]);
     158    T (&a2[1][2], "%s", a2[0]);
     159    T (&a2[1][i], "%s", a2[0]);   /* { dg-bogus "overlap" "" { xfail *-*-* } } */
     160  
     161  
     162    T (a2[1], "%s", a2[1]);       /* { dg-warning "overlaps" } */
     163    T (a2[1], "%s", a2[1] + 0);   /* { dg-warning "overlaps" } */
     164    T (a2[1], "%s", a2[1] + 1);   /* { dg-warning "may overlap" } */
     165    T (a2[1], "%s", a2[1] + 2);   /* { dg-warning "may overlap" } */
     166    T (a2[1], "%s", a2[1] + i);   /* { dg-warning "may overlap" } */
     167  
     168    T (a2[1], "%s", &a2[1][0]);   /* { dg-warning "overlaps" } */
     169    T (a2[1], "%s", &a2[1][1]);   /* { dg-warning "may overlap" } */
     170    T (a2[1], "%s", &a2[1][2]);   /* { dg-warning "may overlap" } */
     171    T (a2[1], "%s", &a2[1][i]);   /* { dg-warning "may overlap" "" { xfail *-*-* } } */
     172  
     173    T (a2[1] + 0, "%s", a2[1]);   /* { dg-warning "overlaps" } */
     174    T (a2[1] + 1, "%s", a2[1]);   /* { dg-warning "may overlap" } */
     175    T (a2[1] + 2, "%s", a2[1]);   /* { dg-warning "may overlap" } */
     176    T (a2[1] + i, "%s", a2[1]);   /* { dg-warning "may overlap" } */
     177  
     178    T (&a2[1][0], "%s", a2[1]);   /* { dg-warning "overlaps" } */
     179    T (&a2[1][1], "%s", a2[1]);   /* { dg-warning "may overlap" } */
     180    T (&a2[1][2], "%s", a2[1]);   /* { dg-warning "may overlap" } */
     181    T (&a2[1][i], "%s", a2[1]);   /* { dg-warning "may overlap" "" { xfail *-*-* } } */
     182  }
     183  
     184  struct S {
     185    char a[4];
     186    char b[4];
     187  };
     188  
     189  struct S2 {
     190    struct S s_1;
     191    struct S s_2;
     192    struct S sa3[3];
     193  };
     194  
     195  struct S3 {
     196    struct S2 s2_1;
     197    struct S2 s2_2;
     198  
     199    struct {
     200      struct {
     201        struct {
     202  	struct S sa_3[3];
     203        } a_1[3];
     204      } a_2[3][3];
     205    } a_3[3][3][3];
     206  
     207    char fa[];
     208  };
     209  
     210  void test_struct_member_array (struct S3 *s3, int i)
     211  {
     212    char *d = s3->s2_1.s_1.a;
     213  
     214    T (d, "%s", d);       /* { dg-warning "overlaps" } */
     215    T (d, "%s", d + 0);   /* { dg-warning "overlaps" } */
     216    T (d, "%s", d + 1);   /* { dg-warning "may overlap" } */
     217    /* Since d below points to char[4], strlen(d + 2) must be at most 1
     218       and so the call cannot overlap. */
     219    T (d, "%s", d + 2);
     220    T (d, "%s", d + i);   /* { dg-warning "may overlap" } */
     221  
     222    T (d, "%s", &d[0]);   /* { dg-warning "overlaps" } */
     223    T (d, "%s", &d[1]);   /* { dg-warning "may overlap" } */
     224    T (d, "%s", &d[2]);
     225    T (d, "%s", &d[i]);   /* { dg-warning "may overlap" } */
     226  
     227    T (d + 0, "%s", d);   /* { dg-warning "overlaps" } */
     228    T (d + 1, "%s", d);   /* { dg-warning "may overlap" } */
     229    T (d + 2, "%s", d);   /* { dg-warning "may overlap" } */
     230    T (d + i, "%s", d);   /* { dg-warning "may overlap" } */
     231  
     232    T (&d[0], "%s", d);   /* { dg-warning "overlaps" } */
     233    T (&d[1], "%s", d);   /* { dg-warning "may overlap" } */
     234    T (&d[2], "%s", d);   /* { dg-warning "may overlap" } */
     235    T (&d[i], "%s", d);   /* { dg-warning "may overlap" } */
     236  
     237    const char *s = d;
     238  
     239    T (d, "%s", s);       /* { dg-warning "overlaps" } */
     240    T (d, "%s", s + 1);   /* { dg-warning "may overlap" } */
     241    T (d, "%s", s + 2);
     242    T (d, "%s", s + i);   /* { dg-warning "may overlap" } */
     243  
     244    s = s3->s2_1.s_1.b;
     245  
     246    T (d, "%s", s);
     247    T (d, "%s", s + 1);
     248    T (d, "%s", s + 2);
     249    T (d, "%s", s + i);
     250  
     251    s = s3->s2_1.s_2.a;
     252  
     253    T (d, "%s", s);
     254    T (d, "%s", s + 1);
     255    T (d, "%s", s + 2);
     256    T (d, "%s", s + i);
     257  
     258    s = s3->s2_1.s_2.b;
     259  
     260    T (d, "%s", s);
     261    T (d, "%s", s + 1);
     262    T (d, "%s", s + 2);
     263    T (d, "%s", s + i);
     264  
     265    d = s3->s2_1.s_1.b;
     266  
     267    s = s3->s2_1.s_2.a;
     268  
     269    T (d, "%s", s);
     270    T (d, "%s", s + 1);
     271    T (d, "%s", s + 2);
     272    T (d, "%s", s + i);
     273  
     274    s = s3->s2_1.s_2.b;
     275  
     276    T (d, "%s", s);
     277    T (d, "%s", s + 1);
     278    T (d, "%s", s + 2);
     279    T (d, "%s", s + i);
     280  
     281    s = s3->s2_2.s_1.a;
     282  
     283    T (d, "%s", s);
     284    T (d, "%s", s + 1);
     285    T (d, "%s", s + 2);
     286    T (d, "%s", s + i);
     287  
     288    s = s3->s2_2.s_1.b;
     289  
     290    T (d, "%s", s);
     291    T (d, "%s", s + 1);
     292    T (d, "%s", s + 2);
     293    T (d, "%s", s + i);
     294  
     295    s = s3->s2_2.s_2.a;
     296  
     297    T (d, "%s", s);
     298    T (d, "%s", s + 1);
     299    T (d, "%s", s + 2);
     300    T (d, "%s", s + i);
     301  
     302    s = s3->s2_2.s_2.b;
     303  
     304    T (d, "%s", s);
     305    T (d, "%s", s + 1);
     306    T (d, "%s", s + 2);
     307    T (d, "%s", s + i);
     308  
     309    d = s3->s2_2.s_1.a;
     310  
     311    s = s3->s2_1.s_1.a;
     312  
     313    T (d, "%s", s);
     314    T (d, "%s", s + 1);
     315    T (d, "%s", s + 2);
     316    T (d, "%s", s + i);
     317  
     318    s = s3->s2_1.s_1.b;
     319  
     320    T (d, "%s", s);
     321    T (d, "%s", s + 1);
     322    T (d, "%s", s + 2);
     323    T (d, "%s", s + i);
     324  
     325    s = s3->s2_2.s_1.a;
     326  
     327    T (d, "%s", s);       /* { dg-warning "overlaps" } */
     328    T (d, "%s", s + 1);   /* { dg-warning "may overlap" } */
     329    T (d, "%s", s + 2);
     330    T (d, "%s", s + i);   /* { dg-warning "may overlap" } */
     331  
     332    s = s3->s2_2.s_2.a;
     333  
     334    T (d, "%s", s);
     335    T (d, "%s", s + 1);
     336    T (d, "%s", s + 2);
     337    T (d, "%s", s + i);
     338  
     339    s = s3->s2_2.s_2.b;
     340  
     341    T (d, "%s", s);
     342    T (d, "%s", s + 1);
     343    T (d, "%s", s + 2);
     344    T (d, "%s", s + i);
     345  
     346    d = s3->s2_2.s_1.b;
     347  
     348    s = s3->s2_1.s_1.a;
     349  
     350    T (d, "%s", s);
     351    T (d, "%s", s + 1);
     352    T (d, "%s", s + 2);
     353    T (d, "%s", s + i);
     354  
     355    s = s3->s2_1.s_1.b;
     356  
     357    T (d, "%s", s);
     358    T (d, "%s", s + 1);
     359    T (d, "%s", s + 2);
     360    T (d, "%s", s + i);
     361  
     362    s = s3->s2_2.s_1.a;
     363  
     364    T (d, "%s", s);
     365    T (d, "%s", s + 1);
     366    T (d, "%s", s + 2);
     367    T (d, "%s", s + i);
     368  
     369    s = s3->s2_2.s_1.b;
     370  
     371    T (d, "%s", s);       /* { dg-warning "overlaps" } */
     372    T (d, "%s", s + 1);   /* { dg-warning "may overlap" } */
     373    T (d, "%s", s + 2);
     374    T (d, "%s", s + i);   /* { dg-warning "may overlap" } */
     375  
     376    s = s3->s2_2.s_2.a;
     377  
     378    T (d, "%s", s);
     379    T (d, "%s", s + 1);
     380    T (d, "%s", s + 2);
     381    T (d, "%s", s + i);
     382  
     383    s = s3->s2_2.s_2.b;
     384  
     385    T (d, "%s", s);
     386    T (d, "%s", s + 1);
     387    T (d, "%s", s + 2);
     388    T (d, "%s", s + i);
     389  }
     390  
     391  void test_struct_member_array_array (struct S3 *s3, int i)
     392  {
     393    char *d = s3->s2_1.sa3[0].a;
     394    char *s = s3->s2_1.sa3[0].a;
     395  
     396    T (d, "%s", s);       /* { dg-warning "overlaps" } */
     397    T (d, "%s", s + 0);   /* { dg-warning "overlaps" } */
     398    T (d, "%s", s + 1);   /* { dg-warning "may overlap" } */
     399    T (d, "%s", s + 2);
     400    T (d, "%s", s + i);   /* { dg-warning "may overlap" } */
     401  
     402    T (d, "%s", &s[0]);   /* { dg-warning "overlaps" } */
     403    T (d, "%s", &s[1]);   /* { dg-warning "may overlap" } */
     404    T (d, "%s", &s[2]);
     405    T (d, "%s", &s[i]);   /* { dg-warning "may overlap" } */
     406  
     407    T (d + 0, "%s", s);   /* { dg-warning "overlaps" } */
     408    T (d + 1, "%s", s);   /* { dg-warning "may overlap" } */
     409    T (d + 2, "%s", s);   /* { dg-warning "may overlap" } */
     410    T (d + i, "%s", s);   /* { dg-warning "may overlap" } */
     411  
     412    T (&d[0], "%s", s);   /* { dg-warning "overlaps" } */
     413    T (&d[1], "%s", s);   /* { dg-warning "may overlap" } */
     414    T (&d[2], "%s", s);   /* { dg-warning "may overlap" } */
     415    T (&d[i], "%s", s);   /* { dg-warning "may overlap" } */
     416  
     417    s = s3->s2_1.sa3[0].b;
     418  
     419    T (d, "%s", s);
     420    T (d, "%s", s + 0);
     421    T (d, "%s", s + 1);
     422    T (d, "%s", s + 2);
     423    T (d, "%s", s + i);
     424  
     425    T (d, "%s", &s[0]);
     426    T (d, "%s", &s[1]);
     427    T (d, "%s", &s[2]);
     428    T (d, "%s", &s[i]);
     429  
     430    T (d + 0, "%s", s);
     431    T (d + 1, "%s", s);
     432    T (d + 2, "%s", s);
     433    T (d + i, "%s", s);
     434  
     435    T (&d[0], "%s", s);
     436    T (&d[1], "%s", s);
     437    T (&d[2], "%s", s);
     438    T (&d[i], "%s", s);
     439  }
     440  
     441  void test_struct_member_nested_array (struct S3 *s3, int i)
     442  {
     443  #define PFX(sfx) s3->a_3[i3_0][i3_1][i3_2]	\
     444      .a_2[i2_0][i2_1]				\
     445      .a_1[i1_0].sfx
     446  
     447  #define TT(d, s)				\
     448    T (PFX (d), "%s", PFX (s));			\
     449    T (PFX (d), "%s", &PFX (s)[0]);		\
     450    T (PFX (d), "%s", &PFX (s)[1]);		\
     451    T (PFX (d), "%s", &PFX (s)[2]);		\
     452    T (PFX (d), "%s", &PFX (s)[i])		\
     453  
     454  #define T1(i0)	do						\
     455      {								\
     456        enum {i1_0 = i0 };					\
     457  								\
     458        TT (sa_3[0].a, sa_3[0].b); TT (sa_3[0].b, sa_3[0].a);	\
     459        								\
     460        TT (sa_3[0].a, sa_3[1].a); TT (sa_3[0].a, sa_3[1].b);	\
     461        TT (sa_3[0].b, sa_3[1].a); TT (sa_3[0].b, sa_3[1].b);	\
     462      								\
     463        TT (sa_3[0].a, sa_3[2].a); TT (sa_3[0].a, sa_3[2].b);	\
     464        TT (sa_3[0].b, sa_3[2].a); TT (sa_3[0].b, sa_3[2].b);	\
     465  								\
     466        TT (sa_3[1].a, sa_3[0].a); TT (sa_3[1].a, sa_3[0].b);	\
     467        TT (sa_3[1].b, sa_3[0].a); TT (sa_3[1].b, sa_3[0].b);	\
     468  								\
     469        TT (sa_3[1].a, sa_3[1].b); TT (sa_3[1].b, sa_3[1].a);	\
     470  								\
     471        TT (sa_3[1].a, sa_3[2].a); TT (sa_3[1].a, sa_3[2].b);	\
     472        TT (sa_3[1].b, sa_3[2].a); TT (sa_3[1].b, sa_3[2].b);	\
     473      } while (0)
     474  
     475  #define T2(i0, i1) do				\
     476      {						\
     477        enum { i2_0 = i0, i2_1 = i1 };		\
     478        T1 (0); T1 (1); T1 (2);			\
     479      } while (0)
     480  
     481  #define T3(i0, i1, i2) do			\
     482      {						\
     483        enum { i3_0 = i0, i3_1 = i1, i3_2 = i2 };	\
     484        T2 (0, 0); T2 (0, 1); T2 (0, 2);		\
     485        T2 (1, 0); T2 (1, 1); T2 (1, 2);		\
     486        T2 (2, 0); T2 (2, 1); T2 (2, 2);		\
     487      } while (0)
     488  
     489  #if 0
     490    /* These tests take forever and a day to compile.  Enable them only
     491       during the development of this feature but leave them otherwise
     492       disabled to avoid slowing everything down for others.  */
     493    T3 (0, 0, 0); T3 (0, 0, 1); T3 (0, 0, 2);
     494    T3 (0, 1, 0); T3 (0, 1, 1); T3 (0, 1, 2);
     495    T3 (0, 2, 0); T3 (0, 2, 1); T3 (0, 2, 2);
     496  
     497    T3 (1, 0, 0); T3 (1, 0, 1); T3 (1, 0, 2);
     498    T3 (1, 1, 0); T3 (1, 1, 1); T3 (1, 1, 2);
     499    T3 (1, 2, 0); T3 (1, 2, 1); T3 (1, 2, 2);
     500  
     501    T3 (2, 0, 0); T3 (2, 0, 1); T3 (2, 0, 2);
     502    T3 (2, 1, 0); T3 (2, 1, 1); T3 (2, 1, 2);
     503    T3 (2, 2, 0); T3 (2, 2, 1); T3 (2, 2, 2);
     504  #endif
     505  }
     506  
     507  void test_struct_member_flexarray (struct S3 *s3, int i, int j)
     508  {
     509    char *d = s3->fa;
     510    char *s = s3->fa;
     511  
     512    T (d, "%s", s);       /* { dg-warning "overlaps" } */
     513    T (d, "%s", s + 0);   /* { dg-warning "overlaps" } */
     514    T (d, "%s", s + 1);   /* { dg-warning "may overlap" } */
     515    T (d, "%s", s + 2);   /* { dg-warning "may overlap" } */
     516    T (d, "%s", s + i);   /* { dg-warning "may overlap" } */
     517  
     518    T (d, "%s", &s[0]);   /* { dg-warning "overlaps" } */
     519    T (d, "%s", &s[1]);   /* { dg-warning "may overlap" } */
     520    T (d, "%s", &s[2]);   /* { dg-warning "may overlap" } */
     521    T (d, "%s", &s[i]);   /* { dg-warning "may overlap" } */
     522  
     523    T (d + 0, "%s", s);   /* { dg-warning "overlaps" } */
     524    T (d + 1, "%s", s);   /* { dg-warning "may overlap" } */
     525    T (d + 2, "%s", s);   /* { dg-warning "may overlap" } */
     526    T (d + i, "%s", s);   /* { dg-warning "may overlap" } */
     527  
     528    T (&d[0], "%s", s);   /* { dg-warning "overlaps" } */
     529    T (&d[1], "%s", s);   /* { dg-warning "may overlap" } */
     530    T (&d[2], "%s", s);   /* { dg-warning "may overlap" } */
     531    T (&d[i], "%s", s);   /* { dg-warning "may overlap" } */
     532  
     533    d = s3->fa + i;
     534    s = s3->fa + j;
     535  
     536    T (d, "%s", s);       /* { dg-warning "may overlap" } */
     537    T (d, "%s", s + 0);   /* { dg-warning "may overlap" } */
     538    T (d, "%s", s + 1);   /* { dg-warning "may overlap" } */
     539    T (d, "%s", s + 2);   /* { dg-warning "may overlap" } */
     540    T (d, "%s", s + i);   /* { dg-warning "may overlap" } */
     541  
     542    T (d, "%s", &s[0]);   /* { dg-warning "may overlap" } */
     543    T (d, "%s", &s[1]);   /* { dg-warning "may overlap" } */
     544    T (d, "%s", &s[2]);   /* { dg-warning "may overlap" } */
     545    T (d, "%s", &s[i]);   /* { dg-warning "may overlap" } */
     546  
     547    T (d + 0, "%s", s);   /* { dg-warning "may overlap" } */
     548    T (d + 1, "%s", s);   /* { dg-warning "may overlap" } */
     549    T (d + 2, "%s", s);   /* { dg-warning "may overlap" } */
     550    T (d + j, "%s", s);   /* { dg-warning "may overlap" } */
     551  
     552    T (&d[0], "%s", s);   /* { dg-warning "may overlap" } */
     553    T (&d[1], "%s", s);   /* { dg-warning "may overlap" } */
     554    T (&d[2], "%s", s);   /* { dg-warning "may overlap" } */
     555    T (&d[j], "%s", s);   /* { dg-warning "may overlap" } */
     556  }
     557  
     558  union U
     559  {
     560    struct S2 s2_1;
     561    struct S2 s2_2;
     562  };
     563  
     564  void test_union_member_array (union U *un, int i)
     565  {
     566    char *d = un->s2_1.s_1.a;
     567  
     568    T (d, "%s", d);       /* { dg-warning "overlaps" } */
     569    T (d, "%s", d + 0);   /* { dg-warning "overlaps" } */
     570    T (d, "%s", d + 1);   /* { dg-warning "may overlap" } */
     571    T (d, "%s", d + 2);
     572    T (d, "%s", d + i);   /* { dg-warning "may overlap" } */
     573  
     574    T (d, "%s", &d[0]);   /* { dg-warning "overlaps" } */
     575    T (d, "%s", &d[1]);   /* { dg-warning "may overlap" } */
     576    T (d, "%s", &d[2]);
     577    T (d, "%s", &d[i]);   /* { dg-warning "may overlap" } */
     578  
     579    T (d + 0, "%s", d);   /* { dg-warning "overlaps" } */
     580    T (d + 1, "%s", d);   /* { dg-warning "may overlap" } */
     581    T (d + 2, "%s", d);   /* { dg-warning "may overlap" } */
     582    T (d + i, "%s", d);   /* { dg-warning "may overlap" } */
     583  
     584    T (&d[0], "%s", d);   /* { dg-warning "overlaps" } */
     585    T (&d[1], "%s", d);   /* { dg-warning "may overlap" } */
     586    T (&d[2], "%s", d);   /* { dg-warning "may overlap" } */
     587    T (&d[i], "%s", d);   /* { dg-warning "may overlap" } */
     588  
     589    const char *s = d;
     590  
     591    T (d, "%s", s);       /* { dg-warning "overlaps" } */
     592    T (d, "%s", s + 1);   /* { dg-warning "may overlap" } */
     593    T (d, "%s", s + 2);
     594    T (d, "%s", s + i);   /* { dg-warning "may overlap" } */
     595  
     596    s = un->s2_1.s_1.b;
     597  
     598    T (d, "%s", s);
     599    T (d, "%s", s + 1);
     600    T (d, "%s", s + 2);
     601    T (d, "%s", s + i);
     602  
     603    s = un->s2_1.s_2.a;
     604  
     605    T (d, "%s", s);
     606    T (d, "%s", s + 1);
     607    T (d, "%s", s + 2);
     608    T (d, "%s", s + i);
     609  
     610    s = un->s2_1.s_2.b;
     611  
     612    T (d, "%s", s);
     613    T (d, "%s", s + 1);
     614    T (d, "%s", s + 2);
     615    T (d, "%s", s + i);
     616  
     617    s = un->s2_2.s_1.a;
     618  
     619    T (d, "%s", s);       /* { dg-warning "overlaps" } */
     620    T (d, "%s", s + 1);   /* { dg-warning "may overlap" } */
     621    T (d, "%s", s + 2);
     622    T (d, "%s", s + i);   /* { dg-warning "may overlap" } */
     623  
     624    s = un->s2_2.s_1.b;
     625  
     626    T (d, "%s", s);
     627    T (d, "%s", s + 1);
     628    T (d, "%s", s + 2);
     629    T (d, "%s", s + i);
     630  }
     631  
     632  void test_multiple_overlap (int i)
     633  {
     634    {
     635      char a[3] = "";           /* { dg-message "declared here" } */
     636  
     637      /* Both a3 and a4 definitely overlap the output even if the are
     638         empty because of the terminating nul.  */
     639      char *d = a;
     640      char *a3 = a + 0;
     641      char *a4 = a - 0;
     642  
     643      T (d, "%s%s", a3, a4);    /* { dg-warning "arguments 3, 4 overlap destination object .a." }*/
     644    }
     645  
     646    {
     647      char a[4];
     648  
     649      /* There is no overlap here because the length of a3 is at most 1
     650         and a4 is necessarily the empty string.  */
     651      char *d = a;
     652      char *a3 = a + 2;
     653      char *a4 = a + 3;
     654  
     655      T (d, "%s%s", a3, a4);
     656    }
     657  
     658    {
     659      char a[5];                /* { dg-message "declared here" } */
     660  
     661      /* a3 and a4 may overlap the output.  They will only not overlap
     662         it when a3 is empty, and a4 is at most 1 character long.  */
     663      char *d = a;
     664      char *a3 = a + 2;
     665      char *a4 = a + 3;
     666  
     667      T (d, "%s%s", a3, a4);    /* { dg-warning "arguments 3, 4 may overlap destination object .a." }*/
     668    }
     669  
     670    {
     671      char a[5];                /* { dg-message "declared here" } */
     672  
     673      /* a3 certaibly overlaps the output, but a4 may or may not depending
     674         in the value of i.  */
     675      char *d = a;
     676      char *a3 = a + 0;
     677      char *a4 = a + i;
     678  
     679      T (d, "%s%s", a3, a4);    /* { dg-warning "arguments 3 and maybe 4 overlap destination object .a." }*/
     680    }
     681  }
     682  
     683  void test_overlap_with_precision (char *d, int i, int j)
     684  {
     685    /* None of the following is diagnosed because no copying takes place
     686       between the %s argument and the destination.  */
     687    T (d, "%.0s", d + 0);
     688    T (d, "%.0s", d + 1);
     689    T (d, "%.0s", d + 2);
     690    T (d, "%.0s", d + i);
     691  
     692    T (d, "%.1s", d + 0);       /* { dg-warning "overlaps" } */
     693    /* Unlike the %.0s case the following deserves a warning because
     694       when d[1] isn't nul, it will be overwritten by the terminating
     695       nul added by sprintf.  */
     696    T (d, "%.1s", d + 1);       /* { dg-warning "may overlap" } */
     697    T (d, "%.1s", d + 2);
     698    T (d, "%.1s", d + i);       /* { dg-warning "may overlap" } */
     699  
     700    T (d + 1, "%.0s", d);
     701    T (d + 2, "%.0s", d);
     702  
     703    T (d + 1, "%.1s", d);       /* { dg-warning "may overlap" } */
     704    T (d + 2, "%.1s", d);
     705  
     706    T (d + 2, "%.1s", d + 1);   /* { dg-warning "may overlap" } */
     707    T (d + 2, "%.1s", d + i);   /* { dg-warning "may overlap" } */
     708  
     709    /* The following should be "overlaps" but tracking that the offset
     710       is the same variable doesn't seem worth the effort.  */
     711    T (d + i, "%.1s", d + i);   /* { dg-warning "overlap" } */
     712  
     713    T (d + i, "%.1s", d + j);   /* { dg-warning "may overlap" } */
     714  
     715    /* Exercise overlap with precison in the range [0, 1].  */
     716    if (i < 0 || 1 < i)
     717      i = 0;
     718  
     719    T (d, "%.*s", i, d + 0);    /* { dg-warning "may overlap" } */
     720    T (d, "%.*s", i, d + 1);    /* { dg-warning "may overlap" } */
     721    T (d, "%.*s", i, d + 2);
     722    T (d, "%.*s", i, d + i);    /* { dg-warning "may overlap" "" { xfail *-*-* } } */
     723  }