1  /* Adapted from gcc.dg/Wmismatched-dealloc.c.  */
       2  
       3  #define A(...) __attribute__ ((malloc (__VA_ARGS__)))
       4  
       5  typedef struct FILE   FILE;
       6  typedef __SIZE_TYPE__ size_t;
       7  
       8  void  free (void*);
       9  void* malloc (size_t);
      10  void* realloc (void*, size_t);
      11  
      12  int   fclose (FILE*);
      13  FILE* freopen (const char*, const char*, FILE*);
      14  int   pclose (FILE*);
      15  
      16  A (fclose) A (freopen, 3)
      17    FILE* fdopen (int);
      18  A (fclose) A (freopen, 3)
      19    FILE* fopen (const char*, const char*);
      20  A (fclose) A (freopen, 3)
      21    FILE* fmemopen(void *, size_t, const char *);
      22  A (fclose) A (freopen, 3)
      23    FILE* freopen (const char*, const char*, FILE*);
      24  A (pclose) A (freopen, 3)
      25    FILE* popen (const char*, const char*);
      26  A (fclose) A (freopen, 3)
      27    FILE* tmpfile (void);
      28  
      29  void sink (FILE*);
      30  
      31  
      32              void  release (void*);
      33  A (release) FILE* acquire (void);
      34  
      35  void nowarn_fdopen (void)
      36  {
      37    {
      38      FILE *q = fdopen (0);
      39      if (!q)
      40        return;
      41  
      42      fclose (q);
      43    }
      44  
      45    {
      46      FILE *q = fdopen (0);
      47      if (!q)
      48        return;
      49  
      50      q = freopen ("1", "r", q);
      51      fclose (q);
      52    }
      53  
      54    {
      55      FILE *q = fdopen (0);
      56      if (!q)
      57        return;
      58  
      59      sink (q);
      60    }
      61  }
      62  
      63  
      64  void warn_fdopen (void)
      65  {
      66    {
      67      FILE *q = fdopen (0);     // { dg-message "allocated here" }
      68      release (q);              // { dg-warning "'release' called on 'q' returned from a mismatched allocation function" }
      69    }
      70    {
      71      FILE *q = fdopen (0);     // { dg-message "allocated here" }
      72      free (q);                 // { dg-warning "'free' called on 'q' returned from a mismatched allocation function" }
      73    }
      74  
      75    {
      76      FILE *q = fdopen (0);     // { dg-message "allocated here" }
      77      q = realloc (q, 7);       // { dg-warning "'realloc' called on 'q' returned from a mismatched allocation function" }
      78      sink (q);
      79    }
      80  }
      81  
      82  
      83  void nowarn_fopen (void)
      84  {
      85    {
      86      FILE *q = fopen ("1", "r");
      87      sink (q);
      88      fclose (q);
      89    }
      90  
      91    {
      92      FILE *q = fopen ("2", "r");
      93      sink (q);
      94      q = freopen ("3", "r", q);
      95      sink (q);
      96      fclose (q);
      97    }
      98  
      99    {
     100      FILE *q = fopen ("4", "r");
     101      sink (q);
     102    }
     103  }
     104  
     105  
     106  void warn_fopen (void)
     107  {
     108    {
     109      FILE *q = fopen ("1", "r");
     110      release (q);              // { dg-warning "'release' called on 'q' returned from a mismatched allocation function" }
     111      fclose (q);
     112    }
     113    {
     114      FILE *q = fdopen (0);
     115      free (q);                 // { dg-warning "'free' called on 'q' returned from a mismatched allocation function" }
     116    }
     117  
     118    {
     119      FILE *q = fdopen (0);
     120      q = realloc (q, 7);       // { dg-warning "'realloc' called on 'q' returned from a mismatched allocation function" }
     121      sink (q);
     122    }
     123  }
     124  
     125  
     126  void test_popen (void)
     127  {
     128    {
     129      FILE *p = popen ("1", "r");
     130      sink (p);
     131      pclose (p);
     132    }
     133  
     134    {
     135      FILE *p;
     136      p = popen ("2", "r");     // { dg-message "allocated here" }
     137      fclose (p);               // { dg-warning "'fclose' called on 'p' returned from a mismatched allocation function" }
     138    }
     139  
     140    {
     141      /* freopen() can close a stream open by popen() but pclose() can't
     142         close the stream returned from freopen().  */
     143      FILE *p = popen ("2", "r");
     144      p = freopen ("3", "r", p);  // { dg-message "allocated here" }
     145      pclose (p);               // { dg-warning "'pclose' called on 'p' returned from a mismatched allocation function" }
     146    }
     147  }
     148  
     149  
     150  void test_tmpfile (void)
     151  {
     152    {
     153      FILE *p = tmpfile ();
     154      fclose (p);
     155    }
     156  
     157    {
     158      FILE *p = tmpfile ();
     159      p = freopen ("1", "r", p);
     160      fclose (p);
     161    }
     162  
     163    {
     164      FILE *p = tmpfile ();     // { dg-message "allocated here" }
     165      pclose (p);               // { dg-warning "'pclose' called on 'p' returned from a mismatched allocation function" }
     166    }
     167  }
     168  
     169  
     170  void warn_malloc (void)
     171  {
     172    {
     173      FILE *p = malloc (100);   // { dg-message "allocated here" }
     174      fclose (p);               // { dg-warning "'p' should have been deallocated with 'free' but was deallocated with 'fclose'" }
     175    }
     176  
     177    {
     178      FILE *p = malloc (100);   // { dg-message "allocated here" }
     179      p = freopen ("1", "r", p);// { dg-warning "'p' should have been deallocated with 'free' but was deallocated with 'freopen'" }
     180      fclose (p);
     181    }
     182  
     183    {
     184      FILE *p = malloc (100);   // { dg-message "allocated here" }
     185      pclose (p);               // { dg-warning "'p' should have been deallocated with 'free' but was deallocated with 'pclose'" }
     186    }
     187  }
     188  
     189  
     190  void test_acquire (void)
     191  {
     192    {
     193      FILE *p = acquire ();
     194      release (p);
     195    }
     196  
     197    {
     198      FILE *p = acquire ();
     199      release (p);
     200    }
     201  
     202    {
     203      FILE *p = acquire ();     // { dg-message "allocated here \\(expects deallocation with 'release'\\)" }
     204      fclose (p);               // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'fclose'" }
     205    }
     206  
     207    {
     208      FILE *p = acquire ();     // { dg-message "allocated here \\(expects deallocation with 'release'\\)" }
     209      pclose (p);               // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'pclose'" }
     210    }
     211  
     212    {
     213      FILE *p = acquire ();      // { dg-message "allocated here \\(expects deallocation with 'release'\\)" }
     214      p = freopen ("1", "r", p); // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'freopen'" }
     215      sink (p);
     216    }
     217  
     218    {
     219      FILE *p = acquire ();   // { dg-message "allocated here \\(expects deallocation with 'release'\\)" }
     220      free (p);               // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'free'" }
     221    }
     222  
     223    {
     224      FILE *p = acquire ();     // { dg-message "allocated here \\(expects deallocation with 'release'\\)" }
     225      p = realloc (p, 123);     // { dg-warning "'p' should have been deallocated with 'release' but was deallocated with 'realloc'" }
     226      sink (p);
     227    }
     228  }