(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wuse-after-free-2.c
       1  /* PR middle-end/104232 - spurious -Wuse-after-free after conditional free
       2     { dg-do compile }
       3     { dg-options "-O2 -Wall -fno-tree-loop-distribute-patterns -fno-ivopts" }  */
       4  
       5  void free (void*);
       6  
       7  void sink (void*);
       8  
       9  void nowarn_cond_2 (char *p0, char *q0, int i)
      10  {
      11    char *r = i ? p0 : q0;
      12  
      13    free (p0);
      14  
      15    /* The use of a PHI operand could be diagnosed using the "maybe" form
      16       of the warning at level 2 but it's not done.  If it ever changes
      17       this test and those below will need to be updated.  */
      18    sink (r);
      19  }
      20  
      21  void nowarn_cond_2_null (char *p0, int i)
      22  {
      23    char *r = i ? p0 : 0;
      24  
      25    free (p0);
      26    sink (r);
      27  }
      28  
      29  void nowarn_cond_3 (char *p0, char *q0, int i)
      30  {
      31    char *r = i < 0 ? p0 - 1 : 0 < i ? p0 + 1 : q0;
      32  
      33    free (p0);
      34    sink (r);
      35  }
      36  
      37  void nowarn_cond_3_null (char *p0, int i)
      38  {
      39    char *r = i < 0 ? p0 - 1 : 0 < i ? p0 + 1 : 0;
      40  
      41    free (p0);
      42    sink (r);
      43  }
      44  
      45  void nowarn_cond_4 (char *p0, char *q0, int i)
      46  {
      47    char *r = i < -1 ? p0 - 2 : i < 0 ? p0 - 1 : 1 < i ? p0 + 1 : q0;
      48  
      49    free (p0);
      50    sink (r);
      51  }
      52  
      53  int nowarn_cond_loop (char *p)
      54  {
      55    char *q = p;
      56    while (*q)
      57      {
      58        if (*q == 'x')
      59          {
      60            q = "";
      61            break;
      62          }
      63        ++q;
      64      }
      65  
      66    free (p);
      67    return *q;
      68  }
      69  
      70  
      71  void warn_cond_2_cst (char *p, int i)
      72  {
      73    /* Same as nowarn_cond_2() above but with R being derived only from
      74       P, which means that any R's use after P has been freed should be
      75       diagnosed.  */
      76    char *r = i ? p + 1 : p + 2;
      77  
      78    free (p);         // { dg-message "call to 'free'" }
      79    sink (r);         // { dg-warning "pointer 'r' used after 'free'" }
      80  }
      81  
      82  void warn_cond_2_var (char *p, int i, int j)
      83  {
      84    char *r = i ? p + i : p + j;
      85  
      86    free (p);         // { dg-message "call to 'free'" }
      87    sink (r);         // { dg-warning "pointer 'r' used after 'free'" }
      88  }
      89  
      90  void warn_cond_3_var (char *p0, int i, int j)
      91  {
      92    char *r = i < 0 ? p0 - i : 0 < i ? p0 + j : p0 + i + j;
      93  
      94    free (p0);        // { dg-message "call to 'free'" }
      95    sink (r + 1);     // { dg-warning "pointer 'r' used after 'free'" }
      96  }
      97  
      98  int warn_cond_4 (char *p0, char *q0, int i)
      99  {
     100    char *r = i < -1 ? p0 - 2 : i < 0 ? p0 - 1 : 1 < i ? p0 + 2 : p0 + 1;
     101  
     102    free (p0);        // { dg-message "call to 'free'" }
     103    return *r;        // { dg-warning "pointer 'r' used after 'free'" }
     104  }
     105  
     106  int warn_cond_loop (char *p)
     107  {
     108    char *q = p;
     109  
     110    /*  -fno-tree-loop-distribute-patterns ensures this does not get converted
     111        into rawmemchr (making q and p unrelated).  Also, -fno-ivopts is required
     112        for some targets, to not lose track of the pointer.  */
     113    while (*q)
     114      ++q;
     115  
     116    free (p);         // { dg-message "call to 'free'" }
     117    return *q;        // { dg-warning "pointer 'q' used after 'free'" }
     118  }