]>
Commit | Line | Data |
---|---|---|
671a2836 MS |
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 | } |