1 /* PR middle-end/63272 - GCC should warn when using pointer to dead scoped
2 variable within the same function
3 Exercise basic cases of -Wdangling-pointer without optimization.
4 { dg-do compile }
5 { dg-options "-O0 -Wall -Wno-uninitialized -ftrack-macro-expansion=0" }
6 { dg-require-effective-target alloca } */
7
8 typedef __INTPTR_TYPE__ intptr_t;
9 typedef __SIZE_TYPE__ size_t;
10
11 #if __cplusplus
12 # define EXTERN_C extern "C"
13 #else
14 # define EXTERN_C extern
15 #endif
16
17 EXTERN_C void* alloca (size_t);
18 EXTERN_C void* malloc (size_t);
19 EXTERN_C void* memchr (const void*, int, size_t);
20 EXTERN_C char* strchr (const char*, int);
21
22 int sink (const void*, ...);
23 #define sink(...) sink (0, __VA_ARGS__)
24
25 /* Verify that integer assignments don't cause bogus warnings.
26 Reduced from GFlibc's s_nextafter.c. */
27
28 int nowarn_integer (float x)
29 {
30 int i;
31
32 {
33 union
34 {
35 float x;
36 int i;
37 } u;
38
39 u.x = x;
40 i = u.i;
41 }
42
43 return i;
44 }
45
46 void nowarn_addr (void)
47 {
48 int *p;
49 {
50 int a[] = { 1, 2, 3 };
51 p = a;
52 }
53
54 // This is suspect but not a clear error.
55 sink (&p);
56 }
57
58
59 char* nowarn_ptr (void)
60 {
61 char *p;
62 sink (&p);
63 return p;
64 }
65
66
67 char* nowarn_cond_ptr (void)
68 {
69 // Distilled from a false positive in Glibc dlerror.c.
70 char *q;
71 if (sink (&q))
72 return q;
73
74 return 0;
75 }
76
77
78 void nowarn_loop_ptr (int n, int *p)
79 {
80 // Distilled from a false positive in Glibc td_thr_get_info.c.
81 for (int i = 0; i != 2; ++i)
82 {
83 int x;
84 sink (&x);
85 *p++ = x;
86 }
87 }
88
89
90 void nowarn_intptr_t (void)
91 {
92 intptr_t ip;
93 {
94 int a[] = { 1, 2, 3 };
95 ip = (intptr_t)a;
96 }
97
98 // Using an intptr_t is not diagnosed.
99 sink (0, ip);
100 }
101
102
103 void nowarn_string_literal (void)
104 {
105 const char *s;
106 {
107 s = "123";
108 }
109
110 sink (s);
111 }
112
113
114 void nowarn_extern_array (int x)
115 {
116 {
117 /* This is a silly sanity check. */
118 extern int eia[];
119 int *p;
120 {
121 p = eia;
122 }
123 sink (p);
124 }
125 }
126
127
128 void nowarn_static_array (int x)
129 {
130 {
131 const char *s;
132 {
133 static const char sca[] = "123";
134 s = sca;
135 }
136
137 sink (s);
138 }
139 {
140 const int *p;
141 {
142 static const int sia[] = { 1, 2, 3 };
143 p = sia;
144 }
145
146 sink (p);
147 }
148 {
149 const int *p;
150 {
151 static const int sia[] = { 1, 2, 3 };
152 p = (const int*)memchr (sia, x, sizeof sia);
153 }
154
155 sink (p);
156 }
157 }
158
159
160 void nowarn_alloca (unsigned n)
161 {
162 {
163 char *p;
164 {
165 p = (char*)alloca (n);
166 }
167 sink (p);
168 }
169 {
170 int *p;
171 {
172 p = (int*)alloca (n * sizeof *p);
173 sink (p);
174 }
175 sink (p);
176 }
177 {
178 long *p;
179 {
180 p = (long*)alloca (n * sizeof *p);
181 sink (p);
182 p = p + 1;
183 }
184 sink (p);
185 }
186 }
187
188
189 #pragma GCC diagnostic push
190 /* Verify that -Wdangling-pointer works with #pragma diagnostic. */
191 #pragma GCC diagnostic ignored "-Wdangling-pointer"
192
193 void nowarn_scalar_call_ignored (void *vp)
194 {
195 int *p;
196 {
197 int i;
198 p = &i;
199 }
200 sink (p);
201 }
202
203 #pragma GCC diagnostic pop
204
205
206 void* nowarn_return_local_addr (void)
207 {
208 int a[] = { 1, 2, 3 };
209 int *p = a;
210
211 /* This is a likely bug but it's not really one of using a dangling
212 pointer but rather of returning the address of a local variable
213 which is diagnosed by -Wreturn-local-addr. */
214 return p;
215 }
216
217 void* warn_return_local_addr (void)
218 {
219 int *p = 0;
220 {
221 int a[] = { 1, 2, 3 };
222 p = a;
223 }
224
225 /* Unlike the above case, here the pointer is dangling when it's
226 used. */
227 return p; // { dg-warning "using dangling pointer 'p' to 'a'" "array" }
228 }
229
230
231 void* nowarn_return_alloca (int n)
232 {
233 int *p = (int*)alloca (n);
234 sink (p);
235
236 /* This is a likely bug but it's not really one of using a dangling
237 pointer but rather of returning the address of a local variable
238 which is diagnosed by -Wreturn-local-addr. */
239 return p;
240 }
241
242
243 void warn_scalar_call (void)
244 {
245 int *p;
246 {
247 int i; // { dg-message "'i' declared" "note" }
248 p = &i;
249 }
250 sink (p); // { dg-warning "using dangling pointer 'p' to 'i'" "array" }
251 }
252
253
254 void warn_array_call (void)
255 {
256 int *p;
257 {
258 int a[] = { 1, 2, 3 }; // { dg-message "'a' declared" "note" }
259 p = a;
260 }
261 sink (p); // { dg-warning "using dangling pointer 'p' to 'a'" "array" }
262 }
263
264
265 void* warn_array_return (void)
266 {
267 int *p;
268 {
269 int a[] = { 1, 2, 3 }; // { dg-message "'a' declared" "note" }
270 p = a;
271 }
272 return p; // { dg-warning "using dangling pointer 'p' to 'a'" "array" }
273 }
274
275
276 void warn_pr63272_c1 (int i)
277 {
278 int *p = 0;
279
280 if (i)
281 {
282 int k = i; // { dg-message "'k' declared" "note" }
283 p = &k;
284 }
285
286 sink (p ? *p : 0); // { dg-warning "dangling pointer 'p' to 'k' may be used" }
287 }
288
289
290 void warn_pr63272_c4 (void)
291 {
292 int *p = 0;
293
294 {
295 int b; // { dg-message "'b' declared" "note" }
296 p = &b;
297 }
298
299 sink (p); // { dg-warning "using dangling pointer 'p' to 'b'" "scalar" }
300 }
301
302 void nowarn_cond_if (int i, int n)
303 {
304 int *p;
305 if (i)
306 {
307 int a[] = { 1, 2 };
308 p = a;
309 sink (p);
310 }
311 else
312 {
313 int *b = (int*)malloc (n);
314 p = b;
315 sink (p);
316 }
317
318 p = 0;
319 }
320
321
322 void warn_cond_if (int i, int n)
323 {
324 int *p;
325 if (i)
326 {
327 int a[] = { 1, 2 }; // { dg-message "'a' declared" "note" }
328 sink (a);
329 p = a;
330 }
331 else
332 {
333 int *b = (int*)malloc (n);
334 sink (b);
335 p = b;
336 }
337
338 sink (p); // { dg-warning "dangling pointer 'p' to 'a' may be used" }
339 }
340
341
342 void warn_cond_else (int i, int n)
343 {
344 int *p;
345 if (i)
346 {
347 int *a = (int*)malloc (n);
348 sink (a);
349 p = a;
350 }
351 else
352 {
353 int b[] = { 2, 3 };
354 sink (b);
355 p = b;
356 }
357
358 sink (p); // { dg-warning "dangling pointer 'p' to 'b' may be used" }
359 }
360
361
362 void warn_cond_if_else (int i)
363 {
364 int *p;
365 if (i)
366 {
367 int a[] = { 1, 2 }; // { dg-message "'a' declared" "note" }
368 sink (a);
369 p = a;
370 }
371 else
372 {
373 int b[] = { 3, 4 }; // { dg-message "'b' declared" "note" { xfail *-*-* } }
374 sink (b);
375 p = b;
376 }
377
378 /* With a PHI with more than invalid argument, only one use is diagnosed
379 because after the first diagnostic the code suppresses subsequent
380 ones for the same use. This needs to be fixed. */
381 sink (p); // { dg-warning "dangling pointer 'p' to 'a' may be used" }
382 // { dg-warning "dangling pointer 'p' to 'b' may be used" "pr??????" { xfail *-*-* } .-1 }
383 }
384
385
386 void nowarn_gcc_i386 (int i)
387 {
388 // Regression test reduced from gcc's i386.c.
389 char a[32], *p;
390
391 if (i != 1)
392 p = a;
393 else
394 p = 0;
395
396 if (i == 2)
397 sink (p);
398 else
399 {
400 if (p)
401 {
402 sink (p);
403 return;
404 }
405 sink (p);
406 }
407 }
408
409
410 void warn_memchr (char c1, char c2, char c3, char c4)
411 {
412 char *p = 0;
413 {
414 char a[] = { c1, c2, c3 };// { dg-message "'a' declared" "note" }
415 p = (char*)memchr (a, c4, 3);
416 if (!p)
417 return;
418 }
419
420 sink (p); // { dg-warning "using dangling pointer 'p' to 'a'" }
421 }
422
423
424 void warn_strchr (char c1, char c2, char c3, char c4)
425 {
426 char *p = 0;
427 {
428 char a[] = { c1, c2, c3 }; // { dg-message "'a' declared" "note" }
429 p = (char*)strchr (a, c4);
430 if (!p)
431 return;
432 }
433
434 sink (p); // { dg-warning "using dangling pointer 'p' to 'a'" }
435 }