]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/testsuite/c-c++-common/Wuse-after-free.c
Add -Wuse-after-free [PR80532].
[thirdparty/gcc.git] / gcc / testsuite / c-c++-common / Wuse-after-free.c
1 /* Exercise basic cases of -Wuse-after-free without optimization.
2 { dg-do compile }
3 { dg-options "-O0 -Wall" } */
4
5 typedef __SIZE_TYPE__ size_t;
6
7 #if __cplusplus
8 # define EXTERN_C extern "C"
9 #else
10 # define EXTERN_C extern
11 #endif
12
13 EXTERN_C void* alloca (size_t);
14
15 EXTERN_C void* calloc (size_t, size_t);
16 EXTERN_C void* malloc (size_t);
17
18 EXTERN_C void free (void*);
19
20
21 void sink (void *);
22
23 extern void* evp;
24 extern void* evpa[];
25
26 extern int ei;
27
28 struct List { struct List *next; };
29
30 void nowarn_free (void *vp, struct List *lp)
31 {
32 {
33 free (vp);
34 vp = 0;
35 sink (vp);
36 }
37 {
38 free (evp);
39 evp = 0;
40 sink (evp);
41 }
42 {
43 free (evpa[0]);
44 evpa[0] = 0;
45 sink (evpa[0]);
46 }
47 {
48 void *vp = evpa[0];
49 free (evpa[1]);
50 sink (vp);
51 }
52 {
53 void *p = evpa[1];
54 if (ei & 1)
55 free (p);
56 if (ei & 2)
57 sink (p);
58 }
59 {
60 struct List *next = lp->next;
61 free (lp);
62 free (next);
63 }
64 }
65
66 void nowarn_free_arg (void *p, void *q)
67 {
68 free (p);
69 if (q)
70 free (q);
71 }
72
73 void nowarn_free_extern (void)
74 {
75 extern void *ep, *eq;
76 free (ep);
77 ep = eq;
78 free (ep);
79 }
80
81 void nowarn_free_assign (void)
82 {
83 extern void *ep;
84 free (ep);
85 ep = 0;
86 free (ep);
87 }
88
89 #pragma GCC diagnostic push
90 /* Verify that -Wuse-after-free works with #pragma diagnostic. Note
91 that the option name should not need to include a trailing =, even
92 though it's a multi-level option. (specifying the level after
93 the option, as in "-Wuse-after-free=2", doesn't work. */
94 #pragma GCC diagnostic ignored "-Wuse-after-free"
95
96 void nowarn_double_free_suppressed (void *p)
97 {
98 free (p);
99 free (p);
100 }
101
102 #pragma GCC diagnostic pop
103
104 void warn_double_free_arg (void *p)
105 {
106 free (p); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
107 // Verify exactly one warning is issued.
108 free (p); // { dg-warning "\\\-Wuse-after-free" }
109 // { dg-bogus "\\\-Wuse-after-free" "duplicate warning" { target *-*-* } .-1 }
110
111 }
112
113 void warn_double_free_extern (void)
114 {
115 /* GCC assumes free() clobbers global memory and the warning is
116 too simplistic to see through that assumption. */
117 extern void *ep, *eq;
118 {
119 eq = ep;
120 free (ep); // { dg-message "call to 'free'" "pr??????" { xfail *-*-* } }
121 free (eq); // { dg-warning "\\\-Wuse-after-free" "pr??????" { xfail *-*-* } }
122 }
123 }
124
125 void warn_deref_after_free (int *p, int i)
126 {
127 int *q0 = p, *q1 = p + 1, *qi = p + i;
128 free (p); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
129 *p = 0; // { dg-warning "\\\-Wuse-after-free" }
130
131 *q0 = 0; // { dg-warning "\\\-Wuse-after-free" }
132 *q1 = 0; // { dg-warning "\\\-Wuse-after-free" }
133 *qi = 0; // { dg-warning "\\\-Wuse-after-free" }
134 }
135
136 void warn_array_ref_after_free (int *p, int i)
137 {
138 free (p); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
139 p[i] = 0; // { dg-warning "\\\-Wuse-after-free" }
140 }
141
142 void nowarn_free_list (struct List *head)
143 {
144 for (struct List *p = head, *q; p; p = q)
145 {
146 q = p->next;
147 free (p);
148 }
149 }
150
151 void warn_free_list (struct List *head)
152 {
153 struct List *p = head;
154 for (; p; p = p->next) // { dg-warning "\\\[-Wuse-after-free" }
155 free (p); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
156 }
157
158
159 void warn_free (void *vp)
160 {
161 {
162 free (vp); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
163 evp = vp; // { dg-warning "-Wuse-after-free" }
164 evpa[0] = vp; // { dg-warning "-Wuse-after-free" }
165 evpa[1] = evp;
166 }
167 }