(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Warray-bounds-48.c
       1  /* PR middle-end/91647 - missing -Warray-bounds accessing a zero-length array
       2     of a declared object
       3     { dg-do "compile" }
       4     { dg-options "-O2 -Wall" }
       5     { dg-require-effective-target alloca } */
       6  
       7  /* pr102706: disabled warnings because the now-disabled conditions for the
       8     bogus warnings to come up do not take cost analysis into account, and often
       9     come up wrong.  */
      10  /* { dg-additional-options "-Wno-stringop-overflow" } */
      11  
      12  typedef __INT16_TYPE__ int16_t;
      13  typedef __INT32_TYPE__ int32_t;
      14  
      15  void sink (void*);
      16  
      17  /* Exercise a true flexible member.  */
      18  
      19  struct AX
      20  {
      21    int32_t n;
      22    int16_t ax[];     // { dg-message "while referencing 'ax'" "member" }
      23  };
      24  
      25  static void warn_ax_local (struct AX *p)
      26  {
      27    p->ax[0] = 0;     // { dg-warning "\\\[-Warray-bounds" }
      28    p->ax[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
      29  }
      30  
      31  static void nowarn_ax_extern (struct AX *p)
      32  {
      33    p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
      34  }
      35  
      36  static void warn_ax_local_buf (struct AX *p)
      37  {
      38    p->ax[0] = 4; p->ax[1] = 5;  // { dg-bogus "\\\[-Wstringop-overflow" "pr102706" }
      39                                 //   { xfail { vect_slp_v2hi_store_align &&  { ! vect_slp_v4hi_store_unalign } } }
      40  
      41    p->ax[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
      42    p->ax[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
      43    p->ax[4] = 8;     // { dg-warning "\\\[-Warray-bounds" }
      44  }
      45  
      46  static void warn_ax_extern_buf (struct AX *p)
      47  {
      48    p->ax[0] = 9; p->ax[1] = 10; p->ax[2] = 11;
      49  
      50    p->ax[3] = 12;    // { dg-warning "\\\[-Warray-bounds" }
      51    p->ax[4] = 13;    // { dg-warning "\\\[-Warray-bounds" }
      52    p->ax[5] = 14;    // { dg-warning "\\\[-Warray-bounds" }
      53  }
      54  
      55  static void nowarn_ax_extern_bufx (struct AX *p)
      56  {
      57    p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
      58  }
      59  
      60  static void nowarn_ax_ref (struct AX *p)
      61  {
      62    p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999;
      63  }
      64  
      65  void test_ax (struct AX *p, unsigned n)
      66  {
      67    {
      68      struct AX sax;  // { dg-message "defined here" "struct definition" }
      69      warn_ax_local (&sax);
      70      sink (&sax);
      71    }
      72  
      73    {
      74      extern
      75        struct AX xsax;
      76      nowarn_ax_extern (&xsax);
      77      sink (&xsax);
      78    }
      79  
      80    {
      81      /* Verify out-of-bounds access to the local BUF is diagnosed.  */
      82      char ax_buf_p2[sizeof (struct AX) + 2 * sizeof (int16_t)];
      83      warn_ax_local_buf ((struct AX*) ax_buf_p2);
      84      sink (ax_buf_p2);
      85    }
      86  
      87    {
      88      /* Verify out-of-bounds access to the extern BUF with a known
      89         bound is diagnosed.  */
      90      extern char ax_buf_p3[sizeof (struct AX) + 3 * sizeof (int16_t)];
      91      warn_ax_extern_buf ((struct AX*) ax_buf_p3);
      92      sink (ax_buf_p3);
      93    }
      94  
      95    {
      96      /* Verify that accesses to BUFX with an unknown bound are not
      97         diagnosed.  */
      98      extern char bufx[];
      99      nowarn_ax_extern_bufx ((struct AX*) bufx);
     100      sink (bufx);
     101    }
     102  
     103    {
     104      /* Verify that accesses to BUFN with a runtime bound are not
     105         diagnosed.  */
     106      char bufn[n];
     107      nowarn_ax_extern_bufx ((struct AX*) bufn);
     108      sink (bufn);
     109    }
     110  
     111    nowarn_ax_ref (p);
     112  }
     113  
     114  
     115  /* Exercise a zero-length trailing member array.  It's the same as above
     116     except that extern declarations with no definitions are considered to
     117     have zero elements (they can't be initialized to have any).  */
     118  
     119  struct A0
     120  {
     121    int32_t n;
     122    int16_t a0[0];    // { dg-message "while referencing 'a0'" "member" }
     123  };
     124  
     125  static void warn_a0_local (struct A0 *p)
     126  {
     127    p->a0[0] = 0;     // { dg-warning "\\\[-Warray-bounds" }
     128    p->a0[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
     129  }
     130  
     131  static void warn_a0_extern (struct A0 *p)
     132  {
     133    p->a0[0] = 2;     // { dg-warning "\\\[-Warray-bounds" }
     134    p->a0[1] = 3;     // { dg-warning "\\\[-Warray-bounds" }
     135  }
     136  
     137  static void warn_a0_local_buf (struct A0 *p)
     138  {
     139    p->a0[0] = 4; p->a0[1] = 5;  // { dg-bogus "\\\[-Wstringop-overflow" "pr102706" }
     140                                 //   { xfail { vect_slp_v2hi_store_align && { ! vect_slp_v4hi_store_unalign } } }
     141  
     142    p->a0[2] = 6;     // { dg-warning "\\\[-Warray-bounds" }
     143    p->a0[3] = 7;     // { dg-warning "\\\[-Warray-bounds" }
     144    p->a0[4] = 8;     // { dg-warning "\\\[-Warray-bounds" }
     145  }
     146  
     147  static void warn_a0_extern_buf (struct A0 *p)
     148  {
     149    p->a0[0] = 9; p->a0[1] = 10; p->a0[2] = 11;
     150  
     151    p->a0[3] = 12;    // { dg-warning "\\\[-Warray-bounds" }
     152    p->a0[4] = 13;    // { dg-warning "\\\[-Warray-bounds" }
     153    p->a0[5] = 14;    // { dg-warning "\\\[-Warray-bounds" }
     154  }
     155  
     156  static void nowarn_a0_extern_bufx (struct A0 *p)
     157  {
     158    p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
     159  }
     160  
     161  static void nowarn_a0_ref (struct A0 *p)
     162  {
     163    p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999;
     164  }
     165  
     166  void test_a0 (struct A0 *p, unsigned n)
     167  {
     168    {
     169      struct A0 sa0;  // { dg-message "defined here" "struct definition" }
     170      warn_a0_local (&sa0);
     171      sink (&sa0);
     172    }
     173  
     174    {
     175      extern
     176        struct A0 xsa0;  // { dg-message "defined here" "struct definition" }
     177      warn_a0_extern (&xsa0);
     178      sink (&xsa0);
     179    }
     180  
     181    {
     182      /* Verify out-of-bounds access to the local BUF is diagnosed.  */
     183      char a0_buf_p2[sizeof (struct A0) + 2 * sizeof (int16_t)];
     184      warn_a0_local_buf ((struct A0*) a0_buf_p2);
     185      sink (a0_buf_p2);
     186    }
     187  
     188    {
     189      /* Verify out-of-bounds access to the extern BUF with a known
     190         bound is diagnosed.  */
     191      extern char a0_buf_p3[sizeof (struct A0) + 3 * sizeof (int16_t)];
     192      warn_a0_extern_buf ((struct A0*) a0_buf_p3);
     193      sink (a0_buf_p3);
     194    }
     195  
     196    {
     197      /* Verify that accesses to BUFX with an unknown bound are not
     198         diagnosed.  */
     199      extern char bufx[];
     200      nowarn_a0_extern_bufx ((struct A0*) bufx);
     201      sink (bufx);
     202    }
     203  
     204    {
     205      /* Verify that accesses to BUFN with a runtime bound are not
     206         diagnosed.  */
     207      char bufn[n];
     208      nowarn_a0_extern_bufx ((struct A0*) bufn);
     209      sink (bufn);
     210    }
     211  
     212    nowarn_a0_ref (p);
     213  }
     214  
     215  
     216  /* Exercise a one-element trailing member array.  It's the same as above
     217     except that it has exactly one element.  */
     218  
     219  struct A1
     220  {
     221    int32_t n;
     222    __attribute__ ((aligned (4)))
     223    int16_t a1[1];    // { dg-message "while referencing 'a1'" }
     224  };
     225  
     226  static void warn_a1_local_noinit (struct A1 *p)
     227  {
     228    p->a1[0] = 0;
     229    p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
     230    p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
     231  }
     232  
     233  static void warn_a1_extern (struct A1 *p)
     234  {
     235    p->a1[0] = 0;
     236    p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
     237    p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
     238  }
     239  
     240  static void warn_a1_init (struct A1 *p)
     241  {
     242    p->a1[0] = 0;
     243    p->a1[1] = 1;     // { dg-warning "\\\[-Warray-bounds" }
     244    p->a1[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
     245  }
     246  
     247  static void warn_a1_local_buf (struct A1 *p)
     248  {
     249    p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3;
     250  
     251    p->a1[4] = 4;     // { dg-warning "\\\[-Warray-bounds" }
     252  }
     253  
     254  static void warn_a1_extern_buf (struct A1 *p)
     255  {
     256    p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3; p->a1[4] = 4;
     257  
     258    p->a1[5] = 5;     // { dg-warning "\\\[-Warray-bounds" }
     259  }
     260  
     261  static void nowarn_a1_extern_bufx (struct A1 *p)
     262  {
     263    p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
     264  }
     265  
     266  static void nowarn_a1_ref (struct A1 *p)
     267  {
     268    p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999;
     269  }
     270  
     271  void test_a1 (struct A1 *p, unsigned n)
     272  {
     273    {
     274      struct A1 a1;
     275      warn_a1_local_noinit (&a1);
     276      sink (&a1);
     277    }
     278  
     279    {
     280      extern struct A1 a1x;
     281      warn_a1_extern (&a1x);
     282      sink (&a1x);
     283  }
     284    {
     285      struct A1 a1 = { 0, { 1 } };
     286      warn_a1_init (&a1);
     287      sink (&a1);
     288    }
     289  
     290    {
     291      /* Verify out-of-bounds access to the local BUF is diagnosed.  */
     292      char buf_p2[sizeof (struct A1) + 2 * sizeof (int16_t)];
     293      warn_a1_local_buf ((struct A1*) buf_p2);
     294      sink (buf_p2);
     295    }
     296  
     297    {
     298      /* Verify out-of-bounds access to the extern BUF with a known
     299         bound is diagnosed.  */
     300      extern char a1_buf_p3[sizeof (struct A1) + 3 * sizeof (int16_t)];
     301      warn_a1_extern_buf ((struct A1*) a1_buf_p3);
     302      sink (a1_buf_p3);
     303    }
     304  
     305    {
     306      /* Verify that accesses to BUFX with an unknown bound are not
     307         diagnosed.  */
     308      extern char bufx[];
     309      nowarn_a1_extern_bufx ((struct A1*) bufx);
     310      sink (bufx);
     311    }
     312  
     313    {
     314      /* Verify that accesses to BUFN with a runtime bound are not
     315         diagnosed.  */
     316      char bufn[n];
     317      nowarn_a1_extern_bufx ((struct A1*) bufn);
     318      sink (bufn);
     319    }
     320  
     321    nowarn_a1_ref (p);
     322  }
     323  
     324  
     325  /* Exercise a two-element trailing member array.  It's treated
     326     the same as an interior array member.  */
     327  
     328  struct A2
     329  {
     330    int32_t n;
     331    int16_t a2[2];    // { dg-message "while referencing 'a2'" }
     332  };
     333  
     334  static void warn_a2_noinit (struct A2 *p)
     335  {
     336    p->a2[0] = 0; p->a2[1] = 1;
     337  
     338    p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
     339  }
     340  
     341  static void warn_a2_init (struct A2 *p)
     342  {
     343    p->a2[0] = 0; p->a2[1] = 1;
     344  
     345    p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
     346    p->a2[9] = 9;     // { dg-warning "\\\[-Warray-bounds" }
     347  }
     348  
     349  static void warn_a2_ref (struct A2 *p)
     350  {
     351    p->a2[0] = 0; p->a2[1] = 1;
     352  
     353    p->a2[2] = 2;     // { dg-warning "\\\[-Warray-bounds" }
     354    p->a2[9] = 9;     // { dg-warning "\\\[-Warray-bounds" }
     355  }
     356  
     357  void test_a2 (struct A2 *p)
     358  {
     359    {
     360      struct A2 a2;
     361      warn_a2_noinit (&a2);
     362      sink (&a2);
     363    }
     364  
     365    {
     366      struct A2 a2 = { 0, { 1, 2 } };
     367      warn_a2_init (&a2);
     368      sink (&a2);
     369    }
     370  
     371    warn_a2_ref (p);
     372  }