1  /* { dg-additional-options "-fanalyzer-transitivity" } */
       2  /* { dg-require-effective-target alloca } */
       3  
       4  #include <stddef.h>
       5  #include <stdlib.h>
       6  
       7  extern void do_stuff (const void *);
       8  
       9  #define LIMIT 1024
      10  
      11  void test_1 (size_t sz)
      12  {
      13    void *ptr;
      14    if (sz >= LIMIT)
      15      ptr = malloc (sz);
      16    else
      17      ptr = __builtin_alloca (sz);
      18  
      19    do_stuff (ptr);
      20  
      21    if (sz >= LIMIT)
      22      free (ptr);
      23  }
      24  
      25  void test_2 (size_t sz)
      26  {
      27    void *ptr;
      28    if (sz < LIMIT)
      29      ptr = __builtin_alloca (sz);
      30    else
      31      ptr = malloc (sz);
      32  
      33    do_stuff (ptr);
      34  
      35    if (sz >= LIMIT)
      36      free (ptr);
      37  }
      38  
      39  void test_3 (size_t sz)
      40  {
      41    void *ptr;
      42    if (sz <= LIMIT)
      43      ptr = __builtin_alloca (sz); /* { dg-message "region created on stack here" } */
      44    else
      45      ptr = malloc (sz);
      46  
      47    do_stuff (ptr);
      48  
      49    /* Bug: the "sz <= LIMIT" above should have been "sz < LIMIT",
      50       so there's a free-of-alloca when sz == LIMIT.  */
      51    if (sz >= LIMIT)
      52      free (ptr); /* { dg-warning "'free' of 'ptr' which points to memory on the stack" } */
      53  }
      54  /* { dg-bogus "leak of 'ptr'" } */
      55  /* This can't happen, as "sz > 1024" && "sz <= 1023" is impossible.  */