/* Adapted from gcc.dg/Wmismatched-dealloc.c. */ #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); int fclose (FILE*); FILE* freopen (const char*, const char*, FILE*); int pclose (FILE*); A (fclose) A (freopen, 3) FILE* fdopen (int); A (fclose) A (freopen, 3) FILE* fopen (const char*, const char*); A (fclose) A (freopen, 3) FILE* fmemopen(void *, size_t, const char *); A (fclose) A (freopen, 3) FILE* freopen (const char*, const char*, FILE*); A (pclose) A (freopen, 3) FILE* popen (const char*, const char*); A (fclose) A (freopen, 3) FILE* tmpfile (void); void sink (FILE*); void release (void*); A (release) FILE* acquire (void); 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 "allocated here" } release (q); // { dg-warning "'release' called on 'q' returned from a mismatched allocation function" } } { FILE *q = fdopen (0); // { dg-message "allocated here" } free (q); // { dg-warning "'free' called on 'q' returned from a mismatched allocation function" } } { FILE *q = fdopen (0); // { dg-message "allocated here" } q = realloc (q, 7); // { dg-warning "'realloc' called on 'q' 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"); release (q); // { dg-warning "'release' called on 'q' returned from a mismatched allocation function" } fclose (q); } { FILE *q = fdopen (0); free (q); // { dg-warning "'free' called on 'q' returned from a mismatched allocation function" } } { FILE *q = fdopen (0); q = realloc (q, 7); // { dg-warning "'realloc' called on 'q' returned from a mismatched allocation function" } sink (q); } } void test_popen (void) { { FILE *p = popen ("1", "r"); sink (p); pclose (p); } { FILE *p; p = popen ("2", "r"); // { dg-message "allocated here" } fclose (p); // { dg-warning "'fclose' called on 'p' returned from a mismatched allocation function" } } { /* freopen() can close a stream open by popen() but pclose() can't close the stream returned from freopen(). */ FILE *p = popen ("2", "r"); p = freopen ("3", "r", p); // { dg-message "allocated here" } pclose (p); // { dg-warning "'pclose' called on 'p' returned from a mismatched allocation function" } } } void test_tmpfile (void) { { FILE *p = tmpfile (); fclose (p); } { FILE *p = tmpfile (); p = freopen ("1", "r", p); fclose (p); } { FILE *p = tmpfile (); // { dg-message "allocated here" } pclose (p); // { dg-warning "'pclose' called on 'p' returned from a mismatched allocation function" } } } void warn_malloc (void) { { FILE *p = malloc (100); // { dg-message "allocated here" } fclose (p); // { dg-warning "'p' should have been deallocated with 'free' but was deallocated with 'fclose'" } } { FILE *p = malloc (100); // { dg-message "allocated here" } p = freopen ("1", "r", p);// { dg-warning "'p' should have been deallocated with 'free' but was deallocated with 'freopen'" } fclose (p); } { FILE *p = malloc (100); // { dg-message "allocated here" } pclose (p); // { dg-warning "'p' should have been deallocated with 'free' but was deallocated with 'pclose'" } } } void test_acquire (void) { { FILE *p = acquire (); release (p); } { FILE *p = acquire (); release (p); } { FILE *p = acquire (); // { dg-message "allocated here \\(expects deallocation with 'release'\\)" } fclose (p); // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'fclose'" } } { FILE *p = acquire (); // { dg-message "allocated here \\(expects deallocation with 'release'\\)" } pclose (p); // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'pclose'" } } { FILE *p = acquire (); // { dg-message "allocated here \\(expects deallocation with 'release'\\)" } p = freopen ("1", "r", p); // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'freopen'" } sink (p); } { FILE *p = acquire (); // { dg-message "allocated here \\(expects deallocation with 'release'\\)" } free (p); // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'free'" } } { FILE *p = acquire (); // { dg-message "allocated here \\(expects deallocation with 'release'\\)" } p = realloc (p, 123); // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'realloc'" } sink (p); } }