(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-34.c
       1  /* PR middle-end/95353 - spurious -Wstringop-overflow writing to a trailing
       2     array plus offset
       3     { dg-do compile }
       4     { dg-options "-O2 -Wall" } */
       5  
       6  typedef __SIZE_TYPE__ size_t;
       7  
       8  struct S0 { char n, a[0]; };
       9  
      10  
      11  void s0_nowarn_cstidx (struct S0 *p)
      12  {
      13    char *q = p->a;
      14    q[1] = __LINE__;
      15    q[9] = __LINE__;
      16  }
      17  
      18  void s0_nowarn_cstoff_cstidx (struct S0 *p)
      19  {
      20    char *q = p->a + 1;
      21    q[1] = __LINE__;
      22    q[9] = __LINE__;
      23  }
      24  
      25  void s0_nowarn_varoff_cstdix (struct S0 *p, int i)
      26  {
      27    char *q = p->a + i;
      28    q[1] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
      29    q[9] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
      30  }
      31  
      32  void s0_nowarn_cstoff_varidx (struct S0 *p, int i)
      33  {
      34    char *q = p->a + 1;
      35    q[i] = __LINE__;
      36  }
      37  
      38  void s0_nowarn_varoff_varidx (struct S0 *p, int i, int j)
      39  {
      40    char *q = p->a + i;
      41    q[j] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
      42  }
      43  
      44  
      45  /* Accesses past the end of a trailing array with one element is
      46     discouraged but still reluctantly not diagnosed.  This should
      47     change.  */
      48  
      49  struct S1 { char n, a[1]; };
      50  
      51  
      52  void s1_nowarn_cstidx (struct S1 *p)
      53  {
      54    char *q = p->a;
      55    q[1] = __LINE__;
      56    q[9] = __LINE__;
      57  }
      58  
      59  void s1_nowarn_cstoff_cstidx (struct S1 *p)
      60  {
      61    char *q = p->a + 1;
      62    q[1] = __LINE__;
      63    q[9] = __LINE__;
      64  }
      65  
      66  void s1_nowarn_varoff_cstdix (struct S1 *p, int i)
      67  {
      68    char *q = p->a + i;
      69    q[1] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
      70    q[9] = __LINE__;            // { dg-bogus "\\\[-Wstringop-overflow" }
      71  }
      72  
      73  void s1_nowarn_cstoff_varidx (struct S1 *p, int i)
      74  {
      75    char *q = p->a + 1;
      76    q[i] = __LINE__;
      77  }
      78  
      79  void s1_nowarn_varoff_varidx (struct S1 *p, int i, int j)
      80  {
      81    char *q = p->a + i;
      82    q[j] = __LINE__;
      83  }
      84  
      85  
      86  /* Accesses past the end of a trailing array with more than one
      87     element should be diagnosed but aren't yet because the MEM_REF
      88     makes the out-of-bounds accesses indistinguishable from valid
      89     ones to subsequent elements of the array pointed by P.  */
      90  
      91  struct S2 { char n, a[2]; };
      92  
      93  
      94  void s2_warn_cstidx (struct S2 *p)
      95  {
      96    char *q = p->a;
      97  
      98    /* The following invalid store is represented as
      99         MEM[(char *)p_1(D) + 3B] = __LINE__;
     100       which is indistinguishable from the valid
     101         q = &p[1].n; q[0] = __LINE__;
     102    */
     103    q[2] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
     104  }
     105  
     106  void s2_warn_cstoff_cstidx (struct S2 *p)
     107  {
     108    char *q = p->a + 1;
     109    q[1] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* }  }
     110  }
     111  
     112  void s2_warn_varoff_cstdix (struct S2 *p, int i)
     113  {
     114    char *q = p->a + i;
     115    q[2] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
     116  }
     117  
     118  void s2_warn_cstoff_varidx (struct S2 *p, int i)
     119  {
     120    char *q = p->a + 1;
     121    q[i] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* }  }
     122  }
     123  
     124  void s2_warn_varoff_varidx (struct S2 *p, int i, int j)
     125  {
     126    char *q = p->a + i;
     127    q[j] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* }  }
     128  }
     129  
     130  
     131  /* Verify that none of these triggers a bogus warning (not tested
     132     elsewhere but triggered during bootstrap).  */
     133  
     134  void s2_nowarn_varidx_int (struct S2 *p, int i)
     135  {
     136    extern struct S2 s2;
     137    extern struct S2 s2a[];
     138  
     139    s2.a[i - 1] = __LINE__;
     140    s2.a[i] = __LINE__;
     141    s2.a[i + 1] = __LINE__;
     142  
     143    s2a[i].a[i - 1] = __LINE__;
     144    s2a[i].a[i] = __LINE__;
     145    s2a[i].a[i + 1] = __LINE__;
     146  
     147    p[i].a[i - 1] = __LINE__;
     148    p[i].a[i] = __LINE__;
     149    p[i].a[i + 1] = __LINE__;
     150  
     151    char *q = p->a;
     152    q[i - 1] = __LINE__;
     153    q[i] = __LINE__;
     154    q[i + 1] = __LINE__;
     155  }
     156  
     157  /* Same as above but with a size_t index in range [1, SIZE_MAX].  */
     158  
     159  void* s2_nowarn_varidx_size (struct S2 *p, size_t i, size_t j)
     160  {
     161    extern struct S2 s2;
     162    extern struct S2 s2a[];
     163    struct S2 *ps2 = __builtin_malloc (3 * sizeof *ps2);
     164  
     165    s2.a[i - 1] = __LINE__;
     166    s2.a[i] = __LINE__;
     167    s2.a[i + 1] = __LINE__;
     168  
     169    s2a[i].a[i - 1] = __LINE__;
     170    s2a[i].a[i] = __LINE__;
     171    s2a[i].a[i + 1] = __LINE__;
     172  
     173    p[i].a[i - 1] = __LINE__;
     174    p[i].a[i] = __LINE__;
     175    p[i].a[i + 1] = __LINE__;
     176  
     177    ps2->a[i - 1] = __LINE__;
     178    ps2->a[i] = __LINE__;
     179    ps2->a[i + 1] = __LINE__;
     180  
     181    char *q = p->a;
     182    q[i - 1] = __LINE__;
     183    q[i] = __LINE__;
     184    q[i + 1] = __LINE__;
     185  
     186    if (j == 0)
     187      return ps2;
     188  
     189    s2.a[j - 1] = __LINE__;
     190    s2.a[j] = __LINE__;
     191    s2.a[j + 1] = __LINE__;
     192  
     193    s2a[j].a[j - 1] = __LINE__;
     194    s2a[j].a[j] = __LINE__;
     195    s2a[j].a[j + 1] = __LINE__;
     196  
     197    p[j].a[j - 1] = __LINE__;
     198    p[j].a[j] = __LINE__;
     199    p[j].a[j + 1] = __LINE__;
     200  
     201    ps2->a[j - 1] = __LINE__;
     202    ps2->a[j] = __LINE__;
     203    ps2->a[j + 1] = __LINE__;
     204  
     205    q = p->a;
     206    q[j - 1] = __LINE__;
     207    q[j] = __LINE__;
     208    q[j + 1] = __LINE__;
     209  
     210    return ps2;
     211  }
     212  
     213  /* Verify that accesses to an interior zero-length array are diagnosed.  */
     214  
     215  struct Si0 { char c, a[0], d; };
     216  
     217  void si0_warn_cstidx (struct Si0 *p)
     218  {
     219    // These are indistinguishable from valid accesses to p->d:
     220    //   MEM[(char *)p_1(D) + 1B] = 0;
     221    char *q = p->a;
     222    q[1] = __LINE__;            // { dg-warning "writing 1 byte into a region of size 0"  "pr?????" { xfail *-*-* } }
     223    q[9] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
     224  }
     225  
     226  void si0_warn_cstoff_cstidx (struct Si0 *p)
     227  {
     228    // Like those above, these too are indistinguishable from valid accesses
     229    // to p->d.
     230    char *q = p->a + 1;
     231    q[1] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
     232    q[9] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
     233  }
     234  
     235  void si0_warn_varoff_cstdix (struct Si0 *p, int i)
     236  {
     237    char *q = p->a + i;
     238    q[1] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
     239    q[9] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
     240  }
     241  
     242  void si0_warn_cstoff_varidx (struct Si0 *p, int i)
     243  {
     244    char *q = p->a + 1;
     245    q[i] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" "pr?????" { xfail *-*-* } }
     246  }
     247  
     248  void si0_warn_varoff_varidx (struct Si0 *p, int i, int j)
     249  {
     250    char *q = p->a + i;
     251    q[j] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
     252  }