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