blob: 634d3142f435493fb320639098d0cccb26430d9f [file] [log] [blame]
/* Exercise basic cases of -Wuse-after-free without optimization.
{ dg-do compile }
{ dg-options "-O0 -Wall" } */
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* calloc (size_t, size_t);
EXTERN_C void* malloc (size_t);
EXTERN_C void free (void*);
void sink (void *);
extern void* evp;
extern void* evpa[];
extern int ei;
struct List { struct List *next; };
void nowarn_free (void *vp, struct List *lp)
{
{
free (vp);
vp = 0;
sink (vp);
}
{
free (evp);
evp = 0;
sink (evp);
}
{
free (evpa[0]);
evpa[0] = 0;
sink (evpa[0]);
}
{
void *vp = evpa[0];
free (evpa[1]);
sink (vp);
}
{
void *p = evpa[1];
if (ei & 1)
free (p);
if (ei & 2)
sink (p);
}
{
struct List *next = lp->next;
free (lp);
free (next);
}
}
void nowarn_free_arg (void *p, void *q)
{
free (p);
if (q)
free (q);
}
void nowarn_free_extern (void)
{
extern void *ep, *eq;
free (ep);
ep = eq;
free (ep);
}
void nowarn_free_assign (void)
{
extern void *ep;
free (ep);
ep = 0;
free (ep);
}
#pragma GCC diagnostic push
/* Verify that -Wuse-after-free works with #pragma diagnostic. Note
that the option name should not need to include a trailing =, even
though it's a multi-level option. (specifying the level after
the option, as in "-Wuse-after-free=2", doesn't work. */
#pragma GCC diagnostic ignored "-Wuse-after-free"
void nowarn_double_free_suppressed (void *p)
{
free (p);
free (p);
}
#pragma GCC diagnostic pop
void warn_double_free_arg (void *p)
{
free (p); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
// Verify exactly one warning is issued.
free (p); // { dg-warning "\\\-Wuse-after-free" }
// { dg-bogus "\\\-Wuse-after-free" "duplicate warning" { target *-*-* } .-1 }
}
void warn_double_free_extern (void)
{
/* GCC assumes free() clobbers global memory and the warning is
too simplistic to see through that assumption. */
extern void *ep, *eq;
{
eq = ep;
free (ep); // { dg-message "call to 'free'" "pr??????" { xfail *-*-* } }
free (eq); // { dg-warning "\\\-Wuse-after-free" "pr??????" { xfail *-*-* } }
}
}
void warn_deref_after_free (int *p, int i)
{
int *q0 = p, *q1 = p + 1, *qi = p + i;
free (p); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
*p = 0; // { dg-warning "\\\-Wuse-after-free" }
*q0 = 0; // { dg-warning "\\\-Wuse-after-free" }
*q1 = 0; // { dg-warning "\\\-Wuse-after-free" }
*qi = 0; // { dg-warning "\\\-Wuse-after-free" }
}
void warn_array_ref_after_free (int *p, int i)
{
free (p); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
p[i] = 0; // { dg-warning "\\\-Wuse-after-free" }
}
void nowarn_free_list (struct List *head)
{
for (struct List *p = head, *q; p; p = q)
{
q = p->next;
free (p);
}
}
void warn_free_list (struct List *head)
{
struct List *p = head;
for (; p; p = p->next) // { dg-warning "\\\[-Wuse-after-free" }
free (p); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
}
void warn_free (void *vp)
{
{
free (vp); // { dg-message "call to '\(void \)?free\(\\(void\\*\\)\)?'" "note" }
evp = vp; // { dg-warning "-Wuse-after-free" }
evpa[0] = vp; // { dg-warning "-Wuse-after-free" }
evpa[1] = evp;
}
}