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