| /* PR middle-end/63272 - GCC should warn when using pointer to dead scoped | |
| variable within the same function | |
| Exercise basic cases of -Wdangling-pointer without optimization. | |
| { dg-do compile } | |
| { dg-options "-O0 -Wall -Wno-uninitialized -ftrack-macro-expansion=0" } | |
| { dg-require-effective-target alloca } */ | |
| typedef __INTPTR_TYPE__ intptr_t; | |
| typedef __SIZE_TYPE__ size_t; | |
| #if __cplusplus | |
| # define EXTERN_C extern "C" | |
| #else | |
| # define EXTERN_C extern | |
| #endif | |
| EXTERN_C void* alloca (size_t); | |
| EXTERN_C void* malloc (size_t); | |
| EXTERN_C void* memchr (const void*, int, size_t); | |
| EXTERN_C char* strchr (const char*, int); | |
| int sink (const void*, ...); | |
| #define sink(...) sink (0, __VA_ARGS__) | |
| /* Verify that integer assignments don't cause bogus warnings. | |
| Reduced from GFlibc's s_nextafter.c. */ | |
| int nowarn_integer (float x) | |
| { | |
| int i; | |
| { | |
| union | |
| { | |
| float x; | |
| int i; | |
| } u; | |
| u.x = x; | |
| i = u.i; | |
| } | |
| return i; | |
| } | |
| void nowarn_addr (void) | |
| { | |
| int *p; | |
| { | |
| int a[] = { 1, 2, 3 }; | |
| p = a; | |
| } | |
| // This is suspect but not a clear error. | |
| sink (&p); | |
| } | |
| char* nowarn_ptr (void) | |
| { | |
| char *p; | |
| sink (&p); | |
| return p; | |
| } | |
| char* nowarn_cond_ptr (void) | |
| { | |
| // Distilled from a false positive in Glibc dlerror.c. | |
| char *q; | |
| if (sink (&q)) | |
| return q; | |
| return 0; | |
| } | |
| void nowarn_loop_ptr (int n, int *p) | |
| { | |
| // Distilled from a false positive in Glibc td_thr_get_info.c. | |
| for (int i = 0; i != 2; ++i) | |
| { | |
| int x; | |
| sink (&x); | |
| *p++ = x; | |
| } | |
| } | |
| void nowarn_intptr_t (void) | |
| { | |
| intptr_t ip; | |
| { | |
| int a[] = { 1, 2, 3 }; | |
| ip = (intptr_t)a; | |
| } | |
| // Using an intptr_t is not diagnosed. | |
| sink (0, ip); | |
| } | |
| void nowarn_string_literal (void) | |
| { | |
| const char *s; | |
| { | |
| s = "123"; | |
| } | |
| sink (s); | |
| } | |
| void nowarn_extern_array (int x) | |
| { | |
| { | |
| /* This is a silly sanity check. */ | |
| extern int eia[]; | |
| int *p; | |
| { | |
| p = eia; | |
| } | |
| sink (p); | |
| } | |
| } | |
| void nowarn_static_array (int x) | |
| { | |
| { | |
| const char *s; | |
| { | |
| static const char sca[] = "123"; | |
| s = sca; | |
| } | |
| sink (s); | |
| } | |
| { | |
| const int *p; | |
| { | |
| static const int sia[] = { 1, 2, 3 }; | |
| p = sia; | |
| } | |
| sink (p); | |
| } | |
| { | |
| const int *p; | |
| { | |
| static const int sia[] = { 1, 2, 3 }; | |
| p = (const int*)memchr (sia, x, sizeof sia); | |
| } | |
| sink (p); | |
| } | |
| } | |
| void nowarn_alloca (unsigned n) | |
| { | |
| { | |
| char *p; | |
| { | |
| p = (char*)alloca (n); | |
| } | |
| sink (p); | |
| } | |
| { | |
| int *p; | |
| { | |
| p = (int*)alloca (n * sizeof *p); | |
| sink (p); | |
| } | |
| sink (p); | |
| } | |
| { | |
| long *p; | |
| { | |
| p = (long*)alloca (n * sizeof *p); | |
| sink (p); | |
| p = p + 1; | |
| } | |
| sink (p); | |
| } | |
| } | |
| #pragma GCC diagnostic push | |
| /* Verify that -Wdangling-pointer works with #pragma diagnostic. */ | |
| #pragma GCC diagnostic ignored "-Wdangling-pointer" | |
| void nowarn_scalar_call_ignored (void *vp) | |
| { | |
| int *p; | |
| { | |
| int i; | |
| p = &i; | |
| } | |
| sink (p); | |
| } | |
| #pragma GCC diagnostic pop | |
| void* nowarn_return_local_addr (void) | |
| { | |
| int a[] = { 1, 2, 3 }; | |
| int *p = a; | |
| /* This is a likely bug but it's not really one of using a dangling | |
| pointer but rather of returning the address of a local variable | |
| which is diagnosed by -Wreturn-local-addr. */ | |
| return p; | |
| } | |
| void* warn_return_local_addr (void) | |
| { | |
| int *p = 0; | |
| { | |
| int a[] = { 1, 2, 3 }; | |
| p = a; | |
| } | |
| /* Unlike the above case, here the pointer is dangling when it's | |
| used. */ | |
| return p; // { dg-warning "using dangling pointer 'p' to 'a'" "array" } | |
| } | |
| void* nowarn_return_alloca (int n) | |
| { | |
| int *p = (int*)alloca (n); | |
| sink (p); | |
| /* This is a likely bug but it's not really one of using a dangling | |
| pointer but rather of returning the address of a local variable | |
| which is diagnosed by -Wreturn-local-addr. */ | |
| return p; | |
| } | |
| void warn_scalar_call (void) | |
| { | |
| int *p; | |
| { | |
| int i; // { dg-message "'i' declared" "note" } | |
| p = &i; | |
| } | |
| sink (p); // { dg-warning "using dangling pointer 'p' to 'i'" "array" } | |
| } | |
| void warn_array_call (void) | |
| { | |
| int *p; | |
| { | |
| int a[] = { 1, 2, 3 }; // { dg-message "'a' declared" "note" } | |
| p = a; | |
| } | |
| sink (p); // { dg-warning "using dangling pointer 'p' to 'a'" "array" } | |
| } | |
| void* warn_array_return (void) | |
| { | |
| int *p; | |
| { | |
| int a[] = { 1, 2, 3 }; // { dg-message "'a' declared" "note" } | |
| p = a; | |
| } | |
| return p; // { dg-warning "using dangling pointer 'p' to 'a'" "array" } | |
| } | |
| void warn_pr63272_c1 (int i) | |
| { | |
| int *p = 0; | |
| if (i) | |
| { | |
| int k = i; // { dg-message "'k' declared" "note" } | |
| p = &k; | |
| } | |
| sink (p ? *p : 0); // { dg-warning "dangling pointer 'p' to 'k' may be used" } | |
| } | |
| void warn_pr63272_c4 (void) | |
| { | |
| int *p = 0; | |
| { | |
| int b; // { dg-message "'b' declared" "note" } | |
| p = &b; | |
| } | |
| sink (p); // { dg-warning "using dangling pointer 'p' to 'b'" "scalar" } | |
| } | |
| void nowarn_cond_if (int i, int n) | |
| { | |
| int *p; | |
| if (i) | |
| { | |
| int a[] = { 1, 2 }; | |
| p = a; | |
| sink (p); | |
| } | |
| else | |
| { | |
| int *b = (int*)malloc (n); | |
| p = b; | |
| sink (p); | |
| } | |
| p = 0; | |
| } | |
| void warn_cond_if (int i, int n) | |
| { | |
| int *p; | |
| if (i) | |
| { | |
| int a[] = { 1, 2 }; // { dg-message "'a' declared" "note" } | |
| sink (a); | |
| p = a; | |
| } | |
| else | |
| { | |
| int *b = (int*)malloc (n); | |
| sink (b); | |
| p = b; | |
| } | |
| sink (p); // { dg-warning "dangling pointer 'p' to 'a' may be used" } | |
| } | |
| void warn_cond_else (int i, int n) | |
| { | |
| int *p; | |
| if (i) | |
| { | |
| int *a = (int*)malloc (n); | |
| sink (a); | |
| p = a; | |
| } | |
| else | |
| { | |
| int b[] = { 2, 3 }; | |
| sink (b); | |
| p = b; | |
| } | |
| sink (p); // { dg-warning "dangling pointer 'p' to 'b' may be used" } | |
| } | |
| void warn_cond_if_else (int i) | |
| { | |
| int *p; | |
| if (i) | |
| { | |
| int a[] = { 1, 2 }; // { dg-message "'a' declared" "note" } | |
| sink (a); | |
| p = a; | |
| } | |
| else | |
| { | |
| int b[] = { 3, 4 }; // { dg-message "'b' declared" "note" { xfail *-*-* } } | |
| sink (b); | |
| p = b; | |
| } | |
| /* With a PHI with more than invalid argument, only one use is diagnosed | |
| because after the first diagnostic the code suppresses subsequent | |
| ones for the same use. This needs to be fixed. */ | |
| sink (p); // { dg-warning "dangling pointer 'p' to 'a' may be used" } | |
| // { dg-warning "dangling pointer 'p' to 'b' may be used" "pr??????" { xfail *-*-* } .-1 } | |
| } | |
| void nowarn_gcc_i386 (int i) | |
| { | |
| // Regression test reduced from gcc's i386.c. | |
| char a[32], *p; | |
| if (i != 1) | |
| p = a; | |
| else | |
| p = 0; | |
| if (i == 2) | |
| sink (p); | |
| else | |
| { | |
| if (p) | |
| { | |
| sink (p); | |
| return; | |
| } | |
| sink (p); | |
| } | |
| } | |
| void warn_memchr (char c1, char c2, char c3, char c4) | |
| { | |
| char *p = 0; | |
| { | |
| char a[] = { c1, c2, c3 };// { dg-message "'a' declared" "note" } | |
| p = (char*)memchr (a, c4, 3); | |
| if (!p) | |
| return; | |
| } | |
| sink (p); // { dg-warning "using dangling pointer 'p' to 'a'" } | |
| } | |
| void warn_strchr (char c1, char c2, char c3, char c4) | |
| { | |
| char *p = 0; | |
| { | |
| char a[] = { c1, c2, c3 }; // { dg-message "'a' declared" "note" } | |
| p = (char*)strchr (a, c4); | |
| if (!p) | |
| return; | |
| } | |
| sink (p); // { dg-warning "using dangling pointer 'p' to 'a'" } | |
| } |