(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wstringop-overflow-58.c
       1  /* PR middle-end/92936 - missing warning on a past-the-end store to a PHI
       2     Exercise warnings for writing into one of two or more declared objects.
       3     { dg-do compile }
       4     { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
       5  
       6  #include "range.h"
       7  
       8  #define INT_MAX __INT_MAX__
       9  
      10  extern void* memset (void*, int, size_t);
      11  #define memset(d, c, n) sink (memset (d, c, n))
      12  
      13  void sink (int, ...);
      14  #define sink(...) sink (0, __VA_ARGS__)
      15  
      16  volatile int cond1, cond2;
      17  
      18  extern char ca0[0], ca1[1], ca2[2], ca3[3], ca4[4],
      19              ca5[5], ca6[6], ca7[7], ca8[8], ca9[9], cax[];
      20  
      21  #define CHOOSE_DECL_2(n1, n2)			\
      22    (cond1 ? ca ## n1 : ca ## n2)
      23  #define CHOOSE_DECL_3(n1, n2, n3)			\
      24    (cond1 < 0 ? ca ## n1 : 0 < cond1 ? ca ## n2 : ca ## n3)
      25  
      26  
      27  void memset_decl_2 (void)
      28  {
      29    {
      30      char *p0_1 = CHOOSE_DECL_2 (0, 1);
      31  
      32      memset (p0_1, 0, 0);
      33      /* Writing more than the smallest destination should trigger a "may
      34         write" warning if the access is unconditionally reachable from
      35         the block where the pointer to either object is assigned.  */
      36      memset (p0_1, 0, 1);
      37      memset (p0_1, 0, 2);      // { dg-warning "memset' writing 2 bytes into a region of size 1 " }
      38      memset (p0_1, 0, 9);      // { dg-warning "memset' writing 9 bytes into a region of size 1 " }
      39    }
      40  
      41    {
      42      char *p0_x = CHOOSE_DECL_2 (0, x);
      43  
      44      memset (p0_x, 0, 0);
      45      memset (p0_x, 0, 1);
      46      memset (p0_x, 0, 2);
      47      memset (p0_x, 0, 9);
      48    }
      49  
      50    {
      51      char *p3_5 = CHOOSE_DECL_2 (3, 5);
      52  
      53      memset (p3_5, 0, 1);
      54      memset (p3_5, 0, 3);
      55      memset (p3_5, 0, 4);
      56      memset (p3_5, 0, 5);
      57      memset (p3_5, 0, 6);      // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
      58    }
      59  
      60    {
      61      char *p5_3 = CHOOSE_DECL_2 (5, 3);
      62  
      63      memset (p5_3, 0, 3);
      64      memset (p5_3, 0, 4);
      65      memset (p5_3, 0, 5);
      66      memset (p5_3, 0, 6);      // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
      67    }
      68  
      69    {
      70      char *px_3 = CHOOSE_DECL_2 (x, 3);
      71  
      72      memset (px_3, 0, 1);
      73      memset (px_3, 0, 3);
      74      memset (px_3, 0, 4);
      75      memset (px_3, 0, 1234);
      76    }
      77  
      78    {
      79      char *p5_x = CHOOSE_DECL_2 (5, x);
      80  
      81      memset (p5_x, 0, 1);
      82      memset (p5_x, 0, 5);
      83      memset (p5_x, 0, 6);
      84      memset (p5_x, 0, 1234);
      85    }
      86  
      87  }
      88  
      89  
      90  void memset_decl_3 (void)
      91  {
      92    {
      93      char *p0_1_2 = CHOOSE_DECL_3 (0, 1, 2);
      94      memset (p0_1_2, 0, 0);
      95      memset (p0_1_2, 0, 1);
      96      memset (p0_1_2, 0, 2);
      97      memset (p0_1_2, 0, 3);    // { dg-warning "memset' writing 3 bytes into a region of size 2 " }
      98      memset (p0_1_2, 0, 9);    // { dg-warning "memset' writing 9 bytes into a region of size 2 " }
      99    }
     100  
     101    {
     102      char *p0_2_x = CHOOSE_DECL_3 (0, 2, x);
     103  
     104      memset (p0_2_x, 0, 0);
     105      memset (p0_2_x, 0, 1);
     106      memset (p0_2_x, 0, 3);
     107      memset (p0_2_x, 0, 9);
     108    }
     109  
     110    {
     111      char *p3_4_5 = CHOOSE_DECL_3 (3, 4, 5);
     112  
     113      memset (p3_4_5, 0, 3);
     114      memset (p3_4_5, 0, 4);
     115      memset (p3_4_5, 0, 5);
     116      memset (p3_4_5, 0, 6);    // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
     117    }
     118  
     119    {
     120      char *p5_3_4 = CHOOSE_DECL_3 (5, 3, 4);
     121  
     122      memset (p5_3_4, 0, 3);
     123      memset (p5_3_4, 0, 4);
     124      memset (p5_3_4, 0, 5);
     125      memset (p5_3_4, 0, 6);    // { dg-warning "memset' writing 6 bytes into a region of size 5 " }
     126    }
     127  
     128    {
     129      char *p9_8_7 = CHOOSE_DECL_3 (9, 8, 7);
     130  
     131      memset (p9_8_7, 0, 7);
     132      memset (p9_8_7, 0, 8);
     133      memset (p9_8_7, 0, 9);
     134      memset (p9_8_7, 0, 10);   // { dg-warning "memset' writing 10 bytes into a region of size 9 " }
     135    }
     136  }
     137  
     138  
     139  /* Verify conditionally writing into one of two objects with the same
     140     size.  */
     141  
     142  void memset_decl_2_same_size (int i)
     143  {
     144    {
     145      char a4_1[4], a4_2[4];
     146      char *p4 = cond1 ? a4_1 : a4_2;
     147  
     148      memset (p4, 0, 1);
     149      memset (p4, 0, 2);
     150      memset (p4, 0, 3);
     151      memset (p4, 0, 4);
     152      memset (p4, 0, 5);        // { dg-warning "memset' writing 5 bytes into a region of size 4" }
     153    }
     154  
     155    {
     156      char a4_1[4];             // { dg-message "destination object 'a4_1" "note" }
     157      char a4_2[4];             // { dg-message "destination object 'a4_2" "note" }
     158      char *p4 = cond1 ? a4_1 : a4_2;
     159      char *p4_i = p4 + i;
     160  
     161      memset (p4_i, 0, 5);      // { dg-warning "memset' writing 5 bytes into a region of size 4" }
     162    }
     163  
     164    {
     165      if (i < 1)
     166        i = 1;
     167  
     168      char a4_1[4];             // { dg-message "at offset \\\[1, 4] into destination object 'a4_1" "note" }
     169      char a4_2[4];             // { dg-message "at offset \\\[1, 4] into destination object 'a4_2" "note" }
     170      char *p4 = cond1 ? a4_1 : a4_2;
     171      char *p4_i = p4 + i;
     172  
     173      memset (p4_i, 0, 3);
     174      memset (p4_i, 0, 4);      // { dg-warning "memset' writing 4 bytes into a region of size 3 " }
     175    }
     176  }
     177  
     178  
     179  void memset_decl_2_off (void)
     180  {
     181    int i1 = SR (1, INT_MAX);
     182    int i2 = SR (2, INT_MAX);
     183  
     184    {
     185      char a5[5];               // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" }
     186      char a7[7];               // { dg-message "at offset \\\[2, 7] into destination object 'a7'" "note" }
     187      char *p5_p1 = a5 + i1;
     188      char *p7_p2 = a7 + i2;
     189      char *p5_7 = cond1 ? p5_p1 : p7_p2;
     190  
     191      memset (p5_7, 0, 1);
     192      memset (p5_7, 0, 2);
     193      memset (p5_7, 0, 3);
     194      memset (p5_7, 0, 4);
     195      memset (p5_7, 0, 5);
     196      /* The warning code conservatively "merges" both the sizes and the offsets
     197         into A5 and A7 and so only the second store below is diagnosed but not
     198         the first.  See PR 103215.  The logic needs to be tightened up.  */
     199      memset (p5_7, 0, 6);      // { dg-warning "memset' writing 6 bytes into a region of size 5 " "pr??????" { xfail *-*-* } }
     200      memset (p5_7, 0, 7);      // { dg-warning "memset' writing 7 bytes into a region of size 6 " }
     201    }
     202  
     203    int i3 = SR (3, INT_MAX);
     204  
     205    {
     206      char a5[5];
     207      // { dg-message "at offset \\\[3, 5] into destination object 'a5'" "note" { target *-*-* } .-1 }
     208      // { dg-message "at offset \\\[2, 5] into destination object 'a5'" "note" { target *-*-* } .-2 }
     209      // { dg-message "at offset \\\[1, 5] into destination object 'a5'" "note" { target *-*-* } .-3 }
     210      // { dg-message ": destination object 'a5'" "note" { target *-*-* } .-4 }
     211      char a9[9];
     212      // { dg-message "at offset \\\[4, 9] into destination object 'a9'" "note" { target *-*-* } .-1 }
     213      // { dg-message "at offset \\\[3, 9] into destination object 'a9'" "note" { target *-*-* } .-2 }
     214      // { dg-message "at offset \\\[2, 9] into destination object 'a9'" "note" { target *-*-* } .-3 }
     215      // { dg-message "at offset \\\[1, 9] into destination object 'a9'" "note" { target *-*-* } .-4 }
     216      // { dg-message ": destination object 'a9'" "pr??????" { xfail *-*-* } .-5 }
     217      char *p5_p2 = a5 + i2;    // 3 bytes left
     218      char *p9_p3 = a9 + i3;    // 6 bytes left
     219      char *p =
     220        cond1 ? p5_p2 : p9_p3;  // [3 - 6] bytes left
     221      char *q = p + i1;         // [2 - 5] bytes left
     222  
     223      memset (q, 0, 1);
     224      memset (q, 0, 2);
     225      memset (q, 0, 3);
     226      memset (q, 0, 4);
     227      memset (q, 0, 5);
     228      memset (q, 0, 6);         // { dg-warning "memset' writing 6 bytes into a region of size 5" "pr??????" { xfail *-*-* } }
     229      memset (q, 0, 7);         // { dg-warning "memset' writing 7 bytes into a region of size 6" }
     230  
     231      --q;                      // [3 - 6] bytes left
     232      memset (q, 0, 1);
     233      memset (q, 0, 2);
     234      memset (q, 0, 3);
     235      memset (q, 0, 4);
     236      memset (q, 0, 5);
     237      memset (q, 0, 6);
     238      memset (q, 0, 7);         // { dg-warning "memset' writing 7 bytes into a region of size 6" "pr??????" { xfail *-*-* } }
     239      memset (q, 0, 8);         // { dg-warning "memset' writing 8 bytes into a region of size 7" }
     240  
     241      --q;                      // [4 - 7] bytes left
     242      memset (q, 0, 1);
     243      memset (q, 0, 2);
     244      memset (q, 0, 3);
     245      memset (q, 0, 4);
     246      memset (q, 0, 5);
     247      memset (q, 0, 6);
     248      memset (q, 0, 7);
     249      memset (q, 0, 8);         // { dg-warning "memset' writing 8 bytes into a region of size 7" "pr??????" { xfail *-*-* } }
     250      memset (q, 0, 9);         // { dg-warning "memset' writing 9 bytes into a region of size 8" }
     251  
     252      int m1_x = SR (-1, INT_MAX);
     253      int m2_x = SR (-2, INT_MAX);
     254  
     255      q += cond2 ? m1_x : m2_x;   // [5 - 9] bytes left
     256  
     257      memset (q, 0, 1);
     258      memset (q, 0, 2);
     259      memset (q, 0, 3);
     260      memset (q, 0, 4);
     261      memset (q, 0, 5);
     262      memset (q, 0, 6);
     263      memset (q, 0, 7);
     264      memset (q, 0, 8);
     265      memset (q, 0, 9);
     266      memset (q, 0, 10);        // { dg-warning "memset' writing 10 bytes into a region of size 9" }
     267    }
     268  }