(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
Wmismatched-dealloc-2.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__), noipa))
       8  
       9  typedef __SIZE_TYPE__ size_t;
      10  typedef struct A A;
      11  typedef struct B B;
      12  
      13  /* A pointer returned by any of the four functions must be deallocated
      14     either by dealloc() or by realloc_{A,B}().  */
      15  A (__builtin_free) A* alloc_A (int);
      16  A (__builtin_free) B* alloc_B (int);
      17  A (__builtin_free) A* realloc_A (A *p, int n) { return p; }
      18  A (__builtin_free) B* realloc_B (B *p, int n) { return p; }
      19  
      20  A (realloc_A) A* alloc_A (int);
      21  A (realloc_B) B* alloc_B (int);
      22  A (realloc_A) A* realloc_A (A*, int);
      23  A (realloc_B) B* realloc_B (B*, int);
      24  
      25  void dealloc (void*);
      26  A (dealloc) void* alloc (int);
      27  
      28  void sink (void*);
      29  void* source (void);
      30  
      31  void test_alloc_A (void)
      32  {
      33    {
      34      void *p = alloc_A (1);
      35      p = realloc_A (p, 2);
      36      __builtin_free (p);
      37    }
      38  
      39    {
      40      void *p = alloc_A (1);
      41      /* Verify that calling realloc doesn't trigger a warning even though
      42         alloc_A is not directly associated with it.  */
      43      p = __builtin_realloc (p, 2);
      44      sink (p);
      45    }
      46  
      47    {
      48      void *p = alloc_A (1);              // { dg-message "returned from 'alloc_A'" }
      49      dealloc (p);                        // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
      50    }
      51  
      52    {
      53      /* Because alloc_A() and realloc_B() share free() as a deallocator
      54         they must also be valid as each other's deallocators.  */
      55      void *p = alloc_A (1);
      56      p = realloc_B ((B*)p, 2);
      57      __builtin_free (p);
      58    }
      59  
      60    {
      61      void *p = alloc_A (1);
      62      p = realloc_A (p, 2);
      63      p = __builtin_realloc (p, 3);
      64      __builtin_free (p);
      65    }
      66  }
      67  
      68  
      69  void test_realloc_A (void *ptr)
      70  {
      71    {
      72      void *p = realloc_A (0, 1);
      73      p = realloc_A (p, 2);
      74      __builtin_free (p);
      75    }
      76  
      77    {
      78      void *p = realloc_A (ptr, 2);
      79      p = realloc_A (p, 2);
      80      __builtin_free (p);
      81    }
      82  
      83    {
      84      void *p = realloc_A (0, 3);
      85      p = __builtin_realloc (p, 2);
      86      sink (p);
      87    }
      88  
      89    {
      90      void *p = realloc_A (0, 4);         // { dg-message "returned from 'realloc_A'" }
      91      dealloc (p);                        // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
      92    }
      93  
      94    {
      95      /* Because realloc_A() and realloc_B() share free() as a deallocator
      96         they must also be valid as each other's deallocators.  */
      97      void *p = realloc_A (0, 5);
      98      p = realloc_B ((B*)p, 2);
      99      __builtin_free (p);
     100    }
     101  
     102    {
     103      void *p = realloc_A (0, 6);
     104      p = realloc_A ((A*)p, 2);
     105      p = __builtin_realloc (p, 3);
     106      __builtin_free (p);
     107    }
     108  }
     109  
     110  
     111  void test_realloc (void)
     112  {
     113    extern void free (void*);
     114    extern void* realloc (void*, size_t);
     115  
     116    {
     117      void *p = realloc (source (), 1);
     118      p = realloc_A (p, 2);
     119      __builtin_free (p);
     120    }
     121  
     122    {
     123      void *p = realloc (source (), 2);
     124      p = realloc_A (p, 2);
     125      free (p);
     126    }
     127  
     128    {
     129      void *p = realloc (source (), 3);
     130      free (p);
     131    }
     132  
     133    {
     134      void *p = realloc (source (), 4);
     135      __builtin_free (p);
     136    }
     137  
     138    {
     139      void *p = realloc (source (), 5);   // { dg-message "returned from 'realloc'" }
     140      dealloc (p);                        // { dg-warning "'dealloc' called on pointer returned from a mismatched allocation function" }
     141    }
     142  }