| /* Verify -Wuse-after-free=3 triggers for conditional and unconditional |
| uses in all expressions including equality. |
| { dg-do compile } |
| { dg-options "-O0 -Wall -Wuse-after-free=3" } */ |
| |
| |
| #if __cplusplus |
| # define EXTERN_C extern "C" |
| #else |
| # define EXTERN_C extern |
| #endif |
| |
| EXTERN_C void free (void*); |
| |
| void sink (void*); |
| |
| |
| void warn_double_free (void *p) |
| { |
| free (p); |
| free (p); // { dg-warning "pointer 'p' used" } |
| } |
| |
| void warn_cond_double_free (void *p, int c) |
| { |
| free (p); |
| if (c) |
| free (p); // { dg-warning "pointer 'p' may be used" } |
| } |
| |
| void warn_call_after_free (void *p) |
| { |
| free (p); |
| sink (p); // { dg-warning "pointer 'p' used" } |
| } |
| |
| void warn_cond_call_after_free (void *p, int c) |
| { |
| free (p); |
| if (c) |
| sink (p); // { dg-warning "pointer 'p' may be used" } |
| } |
| |
| void* warn_return_after_free (void *p) |
| { |
| free (p); |
| return p; // { dg-warning "pointer 'p' used" } |
| } |
| |
| void* warn_cond_return_after_free (void *p, int c) |
| { |
| free (p); |
| if (c) |
| return p; // { dg-warning "pointer 'p' may be used" } |
| return 0; |
| } |
| |
| void warn_relational_after_free (char *p, char *q[]) |
| { |
| free (p); |
| |
| int a[] = |
| { |
| p < q[0], // { dg-warning "pointer 'p' used" } |
| p <= q[1], // { dg-warning "pointer 'p' used" } |
| p > q[2], // { dg-warning "pointer 'p' used" } |
| p >= q[3], // { dg-warning "pointer 'p' used" } |
| p == q[4], // { dg-warning "pointer 'p' used" } |
| p != q[5] // { dg-warning "pointer 'p' used" } |
| }; |
| |
| sink (a); |
| } |
| |
| void warn_cond_relational_after_free (char *p, char *q[], int c) |
| { |
| free (p); |
| |
| int a[] = |
| { |
| c ? p < q[0] : q[0][0], // { dg-warning "pointer 'p' may be used" } |
| c ? p <= q[1] : q[1][1], // { dg-warning "pointer 'p' may be used" } |
| c ? p > q[2] : q[2][2], // { dg-warning "pointer 'p' may be used" } |
| c ? p >= q[3] : q[3][3], // { dg-warning "pointer 'p' may be used" } |
| c ? p == q[4] : q[4][4], // { dg-warning "pointer 'p' may be used" } |
| c ? p != q[5] : q[5][5], // { dg-warning "pointer 'p' may be used" } |
| }; |
| |
| sink (a); |
| } |
| |
| |
| // Verify warning for the example in the manual. |
| |
| struct A { int refcount; void *data; }; |
| |
| void release (struct A *p) |
| { |
| int refcount = --p->refcount; |
| free (p); |
| if (refcount == 0) |
| free (p->data); // { dg-warning "pointer 'p' may be used" } |
| } |