blob: 0a18c3c8249e9f2cadcbe3daebea28310d244ce1 [file] [log] [blame]
/* 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'" }
}