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