blob: 6336efa559492403c20fb9d261a71588d4be3998 [file] [log] [blame]
/* PR middle-end/94527 - Add an attribute that marks a function as freeing
an object
Verify that attribute malloc with one or two arguments has the expected
effect on diagnostics.
{ dg-options "-Wall -ftrack-macro-expansion=0" } */
#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
typedef struct FILE FILE;
typedef __SIZE_TYPE__ size_t;
void free (void*);
void* malloc (size_t);
void* realloc (void*, size_t);
/* Declare functions with the minimum attributes malloc how they're
likely going to be declared in <stdio.h>. */
int fclose (FILE*);
A (fclose) FILE* fdopen (int);
A (fclose) FILE* fopen (const char*, const char*);
A (fclose) FILE* fmemopen(void *, size_t, const char *);
A (fclose) FILE* freopen (const char*, const char*, FILE*);
A (freopen, 3) FILE* freopen (const char*, const char*, FILE*);
A (fclose) FILE* tmpfile (void);
A (fclose) FILE* open_memstream (char**, size_t*);
A (fclose) FILE* open_wmemstream (char**, size_t*);
int pclose (FILE*);
A (pclose) FILE* popen (const char*, const char*);
void release (void*);
A (release) FILE* acquire (void);
void sink (FILE*);
void nowarn_fdopen (void)
{
{
FILE *q = fdopen (0);
if (!q)
return;
fclose (q);
}
{
FILE *q = fdopen (0);
if (!q)
return;
q = freopen ("1", "r", q);
fclose (q);
}
{
FILE *q = fdopen (0);
if (!q)
return;
sink (q);
}
}
void warn_fdopen (void)
{
{
FILE *q = fdopen (0); // { dg-message "returned from 'fdopen'" "note" }
sink (q);
release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
}
{
FILE *q = fdopen (0); // { dg-message "returned from 'fdopen'" "note" }
sink (q);
free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
}
{
FILE *q = fdopen (0); // { dg-message "returned from 'fdopen'" "note" }
sink (q);
q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
sink (q);
}
}
void nowarn_fopen (void)
{
{
FILE *q = fopen ("1", "r");
sink (q);
fclose (q);
}
{
FILE *q = fopen ("2", "r");
sink (q);
q = freopen ("3", "r", q);
sink (q);
fclose (q);
}
{
FILE *q = fopen ("4", "r");
sink (q);
}
}
void warn_fopen (void)
{
{
FILE *q = fopen ("1", "r");
sink (q);
release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
}
{
FILE *q = fdopen (0);
sink (q);
free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
}
{
FILE *q = fdopen (0);
sink (q);
q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
sink (q);
}
}
void test_freopen (FILE *p[])
{
{
FILE *q = freopen ("1", "r", p[0]);
sink (q);
fclose (q);
}
{
FILE *q = freopen ("2", "r", p[1]);
sink (q);
q = freopen ("3", "r", q);
sink (q);
fclose (q);
}
{
FILE *q;
q = freopen ("3", "r", p[2]); // { dg-message "returned from 'freopen'" }
sink (q);
q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
sink (q);
}
}
void test_tmpfile (void)
{
{
FILE *p = tmpfile ();
sink (p);
fclose (p);
}
{
FILE *p = tmpfile ();
sink (p);
p = freopen ("1", "r", p);
sink (p);
fclose (p);
}
{
FILE *p = tmpfile (); // { dg-message "returned from 'tmpfile'" "note" }
sink (p);
pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
}
}
void test_open_memstream (char **bufp, size_t *sizep)
{
{
FILE *p = open_memstream (bufp, sizep);
sink (p);
fclose (p);
}
{
FILE *p = open_memstream (bufp, sizep);
sink (p);
p = freopen ("1", "r", p);
sink (p);
fclose (p);
}
{
FILE *p;
p = open_memstream (bufp, sizep); // { dg-message "returned from 'open_memstream'" "note" }
sink (p);
pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
}
{
FILE *p;
p = open_memstream (bufp, sizep); // { dg-message "returned from 'open_memstream'" "note" }
sink (p);
free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
}
{
FILE *p;
p = open_memstream (bufp, sizep); // { dg-message "returned from 'open_memstream'" "note" }
sink (p);
release (p); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
}
}
void test_open_wmemstream (char **bufp, size_t *sizep)
{
{
FILE *p = open_wmemstream (bufp, sizep);
sink (p);
fclose (p);
}
{
FILE *p = open_wmemstream (bufp, sizep);
sink (p);
p = freopen ("1", "r", p);
sink (p);
fclose (p);
}
{
FILE *p;
p = open_wmemstream (bufp, sizep); // { dg-message "returned from 'open_wmemstream'" "note" }
sink (p);
pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
}
{
FILE *p;
p = open_wmemstream (bufp, sizep); // { dg-message "returned from 'open_wmemstream'" "note" }
sink (p);
free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
}
{
FILE *p;
p = open_wmemstream (bufp, sizep); // { dg-message "returned from 'open_wmemstream'" "note" }
sink (p);
release (p); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
}
}
void warn_malloc (void)
{
{
FILE *p = malloc (100); // { dg-message "returned from 'malloc'" "note" }
sink (p);
fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
}
{
FILE *p = malloc (100); // { dg-message "returned from 'malloc'" "note" }
sink (p);
p = freopen ("1", "r", p);// { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
}
{
FILE *p = malloc (100); // { dg-message "returned from 'malloc'" "note" }
sink (p);
pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
}
}
void test_acquire (void)
{
{
FILE *p = acquire ();
release (p);
}
{
FILE *p = acquire ();
sink (p);
release (p);
}
{
FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
sink (p);
fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
}
{
FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
sink (p);
pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
}
{
FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
sink (p);
p = freopen ("1", "r", p); // { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
sink (p);
}
{
FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
sink (p);
free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
}
{
FILE *p = acquire (); // { dg-message "returned from 'acquire'" "note" }
sink (p);
p = realloc (p, 123); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
sink (p);
}
}