1 /* PR middle-end/94527 - Add an attribute that marks a function as freeing
2 an object
3 Verify that attribute malloc with one or two arguments has the expected
4 effect on diagnostics.
5 { dg-options "-Wall -ftrack-macro-expansion=0" } */
6
7 #define A(...) __attribute__ ((malloc (__VA_ARGS__)))
8
9 typedef struct FILE FILE;
10 typedef __SIZE_TYPE__ size_t;
11
12 void free (void*);
13 void* malloc (size_t);
14 void* realloc (void*, size_t);
15
16 /* Declare functions with the minimum attributes malloc how they're
17 likely going to be declared in <stdio.h>. */
18 int fclose (FILE*);
19 A (fclose) FILE* fdopen (int);
20 A (fclose) FILE* fopen (const char*, const char*);
21 A (fclose) FILE* fmemopen(void *, size_t, const char *);
22 A (fclose) FILE* freopen (const char*, const char*, FILE*);
23 A (freopen, 3) FILE* freopen (const char*, const char*, FILE*);
24 A (fclose) FILE* tmpfile (void);
25
26 A (fclose) FILE* open_memstream (char**, size_t*);
27 A (fclose) FILE* open_wmemstream (char**, size_t*);
28
29 int pclose (FILE*);
30 A (pclose) FILE* popen (const char*, const char*);
31
32 void release (void*);
33 A (release) FILE* acquire (void);
34
35 void sink (FILE*);
36
37
nowarn_fdopen(void)38 void nowarn_fdopen (void)
39 {
40 {
41 FILE *q = fdopen (0);
42 if (!q)
43 return;
44
45 fclose (q);
46 }
47
48 {
49 FILE *q = fdopen (0);
50 if (!q)
51 return;
52
53 q = freopen ("1", "r", q);
54 fclose (q);
55 }
56
57 {
58 FILE *q = fdopen (0);
59 if (!q)
60 return;
61
62 sink (q);
63 }
64 }
65
66
warn_fdopen(void)67 void warn_fdopen (void)
68 {
69 {
70 FILE *q = fdopen (0); // { dg-message "returned from 'fdopen'" "note" }
71 sink (q);
72 release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
73 }
74 {
75 FILE *q = fdopen (0); // { dg-message "returned from 'fdopen'" "note" }
76 sink (q);
77 free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
78 }
79
80 {
81 FILE *q = fdopen (0); // { dg-message "returned from 'fdopen'" "note" }
82 sink (q);
83 q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
84 sink (q);
85 }
86 }
87
88
nowarn_fopen(void)89 void nowarn_fopen (void)
90 {
91 {
92 FILE *q = fopen ("1", "r");
93 sink (q);
94 fclose (q);
95 }
96
97 {
98 FILE *q = fopen ("2", "r");
99 sink (q);
100 q = freopen ("3", "r", q);
101 sink (q);
102 fclose (q);
103 }
104
105 {
106 FILE *q = fopen ("4", "r");
107 sink (q);
108 }
109 }
110
111
warn_fopen(void)112 void warn_fopen (void)
113 {
114 {
115 FILE *q = fopen ("1", "r");
116 sink (q);
117 release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
118 }
119 {
120 FILE *q = fdopen (0);
121 sink (q);
122 free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
123 }
124
125 {
126 FILE *q = fdopen (0);
127 sink (q);
128 q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
129 sink (q);
130 }
131 }
132
133
test_freopen(FILE * p[])134 void test_freopen (FILE *p[])
135 {
136 {
137 FILE *q = freopen ("1", "r", p[0]);
138 sink (q);
139 fclose (q);
140 }
141 {
142 FILE *q = freopen ("2", "r", p[1]);
143 sink (q);
144 q = freopen ("3", "r", q);
145 sink (q);
146 fclose (q);
147 }
148
149 {
150 FILE *q;
151 q = freopen ("3", "r", p[2]); // { dg-message "returned from 'freopen'" }
152 sink (q);
153 q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
154 sink (q);
155 }
156 }
157
158
test_tmpfile(void)159 void test_tmpfile (void)
160 {
161 {
162 FILE *p = tmpfile ();
163 sink (p);
164 fclose (p);
165 }
166
167 {
168 FILE *p = tmpfile ();
169 sink (p);
170 p = freopen ("1", "r", p);
171 sink (p);
172 fclose (p);
173 }
174
175 {
176 FILE *p = tmpfile (); // { dg-message "returned from 'tmpfile'" "note" }
177 sink (p);
178 pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
179 }
180 }
181
182
test_open_memstream(char ** bufp,size_t * sizep)183 void test_open_memstream (char **bufp, size_t *sizep)
184 {
185 {
186 FILE *p = open_memstream (bufp, sizep);
187 sink (p);
188 fclose (p);
189 }
190
191 {
192 FILE *p = open_memstream (bufp, sizep);
193 sink (p);
194 p = freopen ("1", "r", p);
195 sink (p);
196 fclose (p);
197 }
198
199 {
200 FILE *p;
201 p = open_memstream (bufp, sizep); // { dg-message "returned from 'open_memstream'" "note" }
202 sink (p);
203 pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
204 }
205
206 {
207 FILE *p;
208 p = open_memstream (bufp, sizep); // { dg-message "returned from 'open_memstream'" "note" }
209 sink (p);
210 free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
211 }
212
213 {
214 FILE *p;
215 p = open_memstream (bufp, sizep); // { dg-message "returned from 'open_memstream'" "note" }
216 sink (p);
217 release (p); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
218 }
219 }
220
221
test_open_wmemstream(char ** bufp,size_t * sizep)222 void test_open_wmemstream (char **bufp, size_t *sizep)
223 {
224 {
225 FILE *p = open_wmemstream (bufp, sizep);
226 sink (p);
227 fclose (p);
228 }
229
230 {
231 FILE *p = open_wmemstream (bufp, sizep);
232 sink (p);
233 p = freopen ("1", "r", p);
234 sink (p);
235 fclose (p);
236 }
237
238 {
239 FILE *p;
240 p = open_wmemstream (bufp, sizep); // { dg-message "returned from 'open_wmemstream'" "note" }
241 sink (p);
242 pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
243 }
244
245 {
246 FILE *p;
247 p = open_wmemstream (bufp, sizep); // { dg-message "returned from 'open_wmemstream'" "note" }
248 sink (p);
249 free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
250 }
251
252 {
253 FILE *p;
254 p = open_wmemstream (bufp, sizep); // { dg-message "returned from 'open_wmemstream'" "note" }
255 sink (p);
256 release (p); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
257 }
258 }
259
260
warn_malloc(void)261 void warn_malloc (void)
262 {
263 {
264 FILE *p = malloc (100); // { dg-message "returned from 'malloc'" "note" }
265 sink (p);
266 fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
267 }
268
269 {
270 FILE *p = malloc (100); // { dg-message "returned from 'malloc'" "note" }
271 sink (p);
272 p = freopen ("1", "r", p);// { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
273 }
274
275 {
276 FILE *p = malloc (100); // { dg-message "returned from 'malloc'" "note" }
277 sink (p);
278 pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
279 }
280 }
281
282
test_acquire(void)283 void test_acquire (void)
284 {
285 {
286 FILE *p = acquire ();
287 release (p);
288 }
289
290 {
291 FILE *p = acquire ();
292 sink (p);
293 release (p);
294 }
295
296 {
297 FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
298 sink (p);
299 fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
300 }
301
302 {
303 FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
304 sink (p);
305 pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
306 }
307
308 {
309 FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
310 sink (p);
311 p = freopen ("1", "r", p); // { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
312 sink (p);
313 }
314
315 {
316 FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
317 sink (p);
318 free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
319 }
320
321 {
322 FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
323 sink (p);
324 p = realloc (p, 123); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
325 sink (p);
326 }
327 }
328