blob: 0a2db1a16c87517c0112eec59f5b0429c633ca1f [file] [log] [blame]
/* Exercise -Wuse-after-free with user-defined deallocators.
{ 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
#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
EXTERN_C void free (void *);
EXTERN_C void* realloc (void *, size_t);
typedef struct List { struct List *next; } List;
// User-defined allocator/deallocator just like like realloc and free.
extern void list_free (List *);
extern List* list_realloc (size_t, List *);
extern A (list_realloc, 2) List* list_realloc (size_t, List *);
extern A (list_free, 1) List* list_realloc (size_t, List *);
void sink (void *);
extern int ei;
extern List *elp, *elpa[];
void nowarn_list_free (struct List *lp)
{
{
list_free (lp);
lp = 0;
sink (lp);
}
{
list_free (elp);
elp = 0;
sink (elp);
}
{
list_free (elpa[0]);
elpa[0] = 0;
sink (elpa[0]);
}
{
void *vp = elpa[0];
list_free (elpa[0]);
sink (vp);
}
{
List *p = elpa[1];
if (ei & 1)
list_free (p);
if (ei & 2)
sink (p);
}
{
struct List *next = lp->next;
list_free (lp);
list_free (next);
}
}
void nowarn_list_free_list (List *head)
{
for (List *p = head, *q; p; p = q)
{
q = p->next;
list_free (p);
}
}
void warn_list_free_list (List *head)
{
List *p = head;
for (; p; p = p->next) // { dg-warning "\\\[-Wuse-after-free" }
list_free (p); // { dg-message "call to '\(void \)?list_free\(\\(List\\*\\)\)?'" "note" }
}