(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-85.c
       1  /* PR middle-end/103215 - bogus -Wstringop-overflow with two pointers with
       2     different offsets each
       3     Test for accesses into distinct arrays through pointers with different
       4     offsets each.
       5  
       6     If/when -Wstringop-overflow is enhanced to issue "maybe" kinds of
       7     warnings some of the accesses here will trigger those and will need
       8     updating.
       9  
      10     { dg-do compile }
      11     { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
      12  
      13  #define NOIPA __attribute__ ((noipa))
      14  
      15  void sink (int[1]);
      16  #define A(p, off) sink (p + off)
      17  
      18  extern int a4[4], a8[8];
      19  
      20  
      21  
      22  
      23  NOIPA void a4_p1_a8_p3 (int i)
      24  {
      25    int *a4_p1 = a4 + 1;
      26    int *a8_p3 = a8 + 3;
      27    int *q = i ? a4_p1 : a8_p3;
      28    A (q, -4);      // { dg-warning "-Wstringop-overflow" }
      29    /* Because -3 is a valid offset into a8 but not a4, q must point
      30       to the former and so subscripts between -3 and +4 refer to its
      31       elements.  */
      32    A (q, -3); A (q, -2); A (q, -1); A (q, 0);
      33    A (q,  1); A (q,  2); A (q,  3); A (q, 4);
      34    A (q, 5);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      35    /* Both of the following are definitely out of bounds but the first isn't
      36       diagnosed because the code conservatively merges the offsets into A4
      37       and A8.  */
      38    A (q, 7);       // { dg-warning "-Wstringop-overflow" }
      39  }
      40  
      41  
      42  NOIPA void a4_p1_a8_p5 (int i)
      43  {
      44    int *a4_p1 = a4 + 1;
      45    int *a8_p5 = a8 + 5;
      46    int *q = i ? a4_p1 : a8_p5;
      47    A (q, -6);     // { dg-warning "-Wstringop-overflow" }
      48    /* Similarly to the above, because -5 is a valid offset into a8 but
      49       not a4, q must point to the former and so subscripts between -5
      50       and +2 refer to its elements.  */
      51    A (q, -5); A (q, -4); A (q, -3); A (q, -2);
      52    A (q, -1); A (q,  0); A (q,  1); A (q,  2);
      53    A (q, 3);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      54    A (q, 7);       // { dg-warning "-Wstringop-overflow" }
      55  }
      56  
      57  
      58  NOIPA void a4_p1_a8_p7 (int i)
      59  {
      60    int *a4_p1 = a4 + 1;
      61    int *a8_p7 = a8 + 7;
      62    int *q = i ? a4_p1 : a8_p7;
      63    A (q, -8);     // { dg-warning "-Wstringop-overflow" }
      64    A (q, -7); A (q, -6); A (q, -5); A (q, -4);
      65    A (q, -3); A (q, -2); A (q, -1); A (q,  0);
      66    /* Since -7 is valid, q must point to a8 and the last valid subscript
      67       must be 0.  */
      68    A (q, 1);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      69    A (q, 2);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      70    A (q, 3);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      71    A (q, 7);       // { dg-warning "-Wstringop-overflow" }
      72  }
      73  
      74  
      75  NOIPA void mp_1_a4_p1_a8_p7 (int i, int j)
      76  {
      77    int *a4_p1 = a4 + 1;
      78    int *a8_p7 = a8 + 7;
      79    int *p = i ? a4_p1 : a8_p7;
      80    int *q = j ? p + 1 : p - 1;
      81  
      82    A (q, -9);      // { dg-warning "-Wstringop-overflow" }
      83  
      84    /* q points either to a8 + [6, 8] or a4 + [0, 2].  */
      85    A (q, -8); A (q, -7); A (q, -6); A (q, -5);
      86    A (q, -4); A (q, -3); A (q, -2); A (q, -1);
      87  
      88    /* Since all the above are valid, q must point to a8 + 8. But as
      89       mentioned above, the warning for each subscript is independent
      90       of prior subscripts into the same object so the access below
      91       aren't diagnosed.  */
      92    A (q, 0);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      93    A (q, 1);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      94    A (q, 2);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      95    A (q, 3);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      96    A (q, 4);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
      97    A (q, 8);       // { dg-warning "-Wstringop-overflow" }
      98  }
      99  
     100  
     101  NOIPA void mp1_a4_p1_a8_p5 (int i, int j)
     102  {
     103    int *a4_p1 = a4 + 1;
     104    int *a8_p5 = a8 + 5;
     105    int *p = i ? a4_p1 : a8_p5;
     106  
     107    int *q = j ? p + 1 : p - 1;
     108  
     109    // q is assumed to point to a8 + 6
     110    A (q, -7);      // { dg-warning "-Wstringop-overflow" }
     111    A (q, -6); A (q, -5); A (q, -4); A (q, -3);
     112    A (q, -2); A (q, -1); A (q,  0); A (q,  1);
     113    /* Even though the above accesses rule it out, q is now assumed
     114       to point to either a4 + [0, 2] or a8 + [4, 5].  */
     115    A (q, 2);
     116    /* q is now assumed to point tp a4.  Given that, only the first store
     117       is valid.  */
     118    A (q, 3);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     119    A (q, 4);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     120    A (q, 5);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     121    A (q, 6);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     122    A (q, 7);       // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     123    A (q, 8);       // { dg-warning "-Wstringop-overflow" }
     124  }
     125  
     126  
     127  NOIPA void mp1_a4_p1_a8_p4 (int i, int j)
     128  {
     129    int *a4_p1 = a4 + 1;
     130    int *a8_p4 = a8 + 4;
     131    int *p = i ? a4_p1 : a8_p4;
     132  
     133    int *q = j ? p + 1 : p - 1;
     134  
     135    // q is assumed to point to a8 + 5
     136    A (q, -6);      // { dg-warning "-Wstringop-overflow" }
     137    A (q, -5);
     138    A (q, -4);
     139    A (q, -3);
     140    A (q, -2);
     141    A (q, -1);
     142    A (q,  0);
     143    A (q,  1);
     144    A (q,  2);
     145    /* Even though the above accesses rule it out, q is now assumed
     146       to point tp a4.  Given that, only the first store is valid.  */
     147    A (q,  3);      // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     148    A (q,  4);      // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     149    A (q,  5);      // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     150    A (q,  6);      // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     151    A (q,  7);      // { dg-warning "-Wstringop-overflow" "pr??????" { xfail *-*-* } }
     152    A (q,  8);      // { dg-warning "-Wstringop-overflow" }
     153  }