(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wmismatched-dealloc.c
       1  /* PR middle-end/94527 - Add an attribute that marks a function as freeing
       2     an object
       3     Verify that attribute malloc with one or two arguments has the expected
       4     effect on diagnostics.
       5     { dg-options "-Wall -ftrack-macro-expansion=0" } */
       6  
       7  #define A(...) __attribute__ ((malloc (__VA_ARGS__)))
       8  
       9  typedef struct FILE   FILE;
      10  typedef __SIZE_TYPE__ size_t;
      11  
      12  void  free (void*);
      13  void* malloc (size_t);
      14  void* realloc (void*, size_t);
      15  
      16  /* Declare functions with the minimum attributes malloc how they're
      17     likely going to be declared in <stdio.h>.  */
      18                 int   fclose (FILE*);
      19  A (fclose)     FILE* fdopen (int);
      20  A (fclose)     FILE* fopen (const char*, const char*);
      21  A (fclose)     FILE* fmemopen(void *, size_t, const char *);
      22  A (fclose)     FILE* freopen (const char*, const char*, FILE*);
      23  A (freopen, 3) FILE* freopen (const char*, const char*, FILE*);
      24  A (fclose)     FILE* tmpfile (void);
      25  
      26  A (fclose)     FILE* open_memstream (char**, size_t*);
      27  A (fclose)     FILE* open_wmemstream (char**, size_t*);
      28  
      29                 int   pclose (FILE*);
      30  A (pclose)     FILE* popen (const char*, const char*);
      31  
      32                 void  release (void*);
      33  A (release)    FILE* acquire (void);
      34  
      35  void sink (FILE*);
      36  
      37  
      38  void nowarn_fdopen (void)
      39  {
      40    {
      41      FILE *q = fdopen (0);
      42      if (!q)
      43        return;
      44  
      45      fclose (q);
      46    }
      47  
      48    {
      49      FILE *q = fdopen (0);
      50      if (!q)
      51        return;
      52  
      53      q = freopen ("1", "r", q);
      54      fclose (q);
      55    }
      56  
      57    {
      58      FILE *q = fdopen (0);
      59      if (!q)
      60        return;
      61  
      62      sink (q);
      63    }
      64  }
      65  
      66  
      67  void warn_fdopen (void)
      68  {
      69    {
      70      FILE *q = fdopen (0);     // { dg-message "returned from 'fdopen'" "note" }
      71      sink (q);
      72      release (q);              // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
      73    }
      74    {
      75      FILE *q = fdopen (0);     // { dg-message "returned from 'fdopen'" "note" }
      76      sink (q);
      77      free (q);                 // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
      78    }
      79  
      80    {
      81      FILE *q = fdopen (0);     // { dg-message "returned from 'fdopen'" "note" }
      82      sink (q);
      83      q = realloc (q, 7);       // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
      84      sink (q);
      85    }
      86  }
      87  
      88  
      89  void nowarn_fopen (void)
      90  {
      91    {
      92      FILE *q = fopen ("1", "r");
      93      sink (q);
      94      fclose (q);
      95    }
      96  
      97    {
      98      FILE *q = fopen ("2", "r");
      99      sink (q);
     100      q = freopen ("3", "r", q);
     101      sink (q);
     102      fclose (q);
     103    }
     104  
     105    {
     106      FILE *q = fopen ("4", "r");
     107      sink (q);
     108    }
     109  }
     110  
     111  
     112  void warn_fopen (void)
     113  {
     114    {
     115      FILE *q = fopen ("1", "r");
     116      sink (q);
     117      release (q);              // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
     118    }
     119    {
     120      FILE *q = fdopen (0);
     121      sink (q);
     122      free (q);                 // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
     123    }
     124  
     125    {
     126      FILE *q = fdopen (0);
     127      sink (q);
     128      q = realloc (q, 7);       // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
     129      sink (q);
     130    }
     131  }
     132  
     133  
     134  void test_freopen (FILE *p[])
     135  {
     136    {
     137      FILE *q = freopen ("1", "r", p[0]);
     138      sink (q);
     139      fclose (q);
     140    }
     141    {
     142      FILE *q = freopen ("2", "r", p[1]);
     143      sink (q);
     144      q = freopen ("3", "r", q);
     145      sink (q);
     146      fclose (q);
     147    }
     148  
     149    {
     150      FILE *q;
     151      q = freopen ("3", "r", p[2]); // { dg-message "returned from 'freopen'" }
     152      sink (q);
     153      q = realloc (q, 7);       // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
     154      sink (q);
     155    }
     156  }
     157  
     158  
     159  void test_tmpfile (void)
     160  {
     161    {
     162      FILE *p = tmpfile ();
     163      sink (p);
     164      fclose (p);
     165    }
     166  
     167    {
     168      FILE *p = tmpfile ();
     169      sink (p);
     170      p = freopen ("1", "r", p);
     171      sink (p);
     172      fclose (p);
     173    }
     174  
     175    {
     176      FILE *p = tmpfile ();     // { dg-message "returned from 'tmpfile'" "note" }
     177      sink (p);
     178      pclose (p);               // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
     179    }
     180  }
     181  
     182  
     183  void test_open_memstream (char **bufp, size_t *sizep)
     184  {
     185    {
     186      FILE *p = open_memstream (bufp, sizep);
     187      sink (p);
     188      fclose (p);
     189    }
     190  
     191    {
     192      FILE *p = open_memstream (bufp, sizep);
     193      sink (p);
     194      p = freopen ("1", "r", p);
     195      sink (p);
     196      fclose (p);
     197    }
     198  
     199    {
     200      FILE *p;
     201      p = open_memstream (bufp, sizep);   // { dg-message "returned from 'open_memstream'" "note" }
     202      sink (p);
     203      pclose (p);               // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
     204    }
     205  
     206    {
     207      FILE *p;
     208      p = open_memstream (bufp, sizep);   // { dg-message "returned from 'open_memstream'" "note" }
     209      sink (p);
     210      free (p);                 // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
     211    }
     212  
     213    {
     214      FILE *p;
     215      p = open_memstream (bufp, sizep);   // { dg-message "returned from 'open_memstream'" "note" }
     216      sink (p);
     217      release (p);              // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
     218    }
     219  }
     220  
     221  
     222  void test_open_wmemstream (char **bufp, size_t *sizep)
     223  {
     224    {
     225      FILE *p = open_wmemstream (bufp, sizep);
     226      sink (p);
     227      fclose (p);
     228    }
     229  
     230    {
     231      FILE *p = open_wmemstream (bufp, sizep);
     232      sink (p);
     233      p = freopen ("1", "r", p);
     234      sink (p);
     235      fclose (p);
     236    }
     237  
     238    {
     239      FILE *p;
     240      p = open_wmemstream (bufp, sizep);  // { dg-message "returned from 'open_wmemstream'" "note" }
     241      sink (p);
     242      pclose (p);               // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
     243    }
     244  
     245    {
     246      FILE *p;
     247      p = open_wmemstream (bufp, sizep);  // { dg-message "returned from 'open_wmemstream'" "note" }
     248      sink (p);
     249      free (p);                 // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
     250    }
     251  
     252    {
     253      FILE *p;
     254      p = open_wmemstream (bufp, sizep);  // { dg-message "returned from 'open_wmemstream'" "note" }
     255      sink (p);
     256      release (p);              // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
     257    }
     258  }
     259  
     260  
     261  void warn_malloc (void)
     262  {
     263    {
     264      FILE *p = malloc (100);   // { dg-message "returned from 'malloc'" "note" }
     265      sink (p);
     266      fclose (p);               // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
     267    }
     268  
     269    {
     270      FILE *p = malloc (100);   // { dg-message "returned from 'malloc'" "note" }
     271      sink (p);
     272      p = freopen ("1", "r", p);// { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
     273    }
     274  
     275    {
     276      FILE *p = malloc (100);   // { dg-message "returned from 'malloc'" "note" }
     277      sink (p);
     278      pclose (p);               // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
     279    }
     280  }
     281  
     282  
     283  void test_acquire (void)
     284  {
     285    {
     286      FILE *p = acquire ();
     287      release (p);
     288    }
     289  
     290    {
     291      FILE *p = acquire ();
     292      sink (p);
     293      release (p);
     294    }
     295  
     296    {
     297      FILE *p = acquire ();     // { dg-message "returned from 'acquire'" "note" }
     298      sink (p);
     299      fclose (p);               // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
     300    }
     301  
     302    {
     303      FILE *p = acquire ();     // { dg-message "returned from 'acquire'" "note" }
     304      sink (p);
     305      pclose (p);               // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
     306    }
     307  
     308    {
     309      FILE *p = acquire ();     // { dg-message "returned from 'acquire'" "note" }
     310      sink (p);
     311      p = freopen ("1", "r", p);  // { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
     312      sink (p);
     313    }
     314  
     315    {
     316      FILE *p = acquire ();     // { dg-message "returned from 'acquire'" "note" }
     317      sink (p);
     318      free (p);               // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
     319    }
     320  
     321    {
     322      FILE *p = acquire ();     // { dg-message "returned from 'acquire'" "note" }
     323      sink (p);
     324      p = realloc (p, 123);     // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
     325      sink (p);
     326    }
     327  }