(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
Wuse-after-free-6.c
       1  /* Verify -Wuse-after-free=2 triggers for conditional as well as
       2     unconditional uses but not for equality expressions.  Same as
       3     -Wuse-after-free-5.c but with optimization.
       4     { dg-do compile }
       5     { dg-options "-O2 -Wall -Wuse-after-free=2" } */
       6  
       7  
       8  #if __cplusplus
       9  #  define EXTERN_C extern "C"
      10  #else
      11  #  define EXTERN_C extern
      12  #endif
      13  
      14  EXTERN_C void free (void*);
      15  
      16  void sink (void*);
      17  
      18  
      19  void warn_double_free (void *p)
      20  {
      21    free (p);
      22    free (p);         // { dg-warning "pointer 'p' used" }
      23  }
      24  
      25  void warn_cond_double_free (void *p, int c)
      26  {
      27    free (p);
      28    if (c)
      29      free (p);       // { dg-warning "pointer 'p' may be used" }
      30  }
      31  
      32  void warn_call_after_free (void *p)
      33  {
      34    free (p);
      35    sink (p);         // { dg-warning "pointer 'p' used" }
      36  }
      37  
      38  void warn_cond_call_after_free (void *p, int c)
      39  {
      40    free (p);
      41    if (c)
      42      sink (p);       // { dg-warning "pointer 'p' may be used" }
      43  }
      44  
      45  void* warn_return_after_free (void *p)
      46  {
      47    free (p);
      48    return p;         // { dg-warning "pointer 'p' used" }
      49  }
      50  
      51  void* warn_cond_return_after_free (void *p, int c)
      52  {
      53    free (p);
      54    // PHI handling not fully implemented.
      55    if (c)
      56      return p;       // { dg-warning "pointer 'p' may be used" }
      57    return 0;
      58  }
      59  
      60  void warn_relational_after_free (char *p, char *q[])
      61  {
      62    free (p);
      63  
      64    int a[] =
      65      {
      66       p < q[0],      // { dg-warning "pointer 'p' used" }
      67       p <= q[1],     // { dg-warning "pointer 'p' used" }
      68       p > q[2],      // { dg-warning "pointer 'p' used" }
      69       p >= q[3],     // { dg-warning "pointer 'p' used" }
      70       p == q[4],
      71       p != q[5]
      72      };
      73  
      74    sink (a);
      75  }
      76  
      77  void warn_cond_relational_after_free (char *p, char *q[], int c)
      78  {
      79    free (p);
      80  
      81    int a[] =
      82      {
      83       c ? p < q[0] : q[0][0],  // { dg-warning "pointer 'p' may be used" }
      84       c ? p <= q[1] : q[1][1], // { dg-warning "pointer 'p' may be used" }
      85       c ? p > q[2] : q[2][2],  // { dg-warning "pointer 'p' may be used" }
      86       c ? p >= q[3] : q[3][3], // { dg-warning "pointer 'p' may be used" }
      87       c ? p == q[4] : q[4][4],
      88       c ? p != q[5] : q[5][5],
      89      };
      90  
      91    sink (a);
      92  }
      93  
      94  
      95  // Verify warning for the example in the manual.
      96  
      97  struct A { int refcount; void *data; };
      98  
      99  void release (struct A *p)
     100  {
     101    int refcount = --p->refcount;
     102    free (p);
     103    if (refcount == 0)
     104      free (p->data); // { dg-warning "pointer 'p' may be used" }
     105  }