(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
malloc-vs-local-1b.c
       1  /* { dg-additional-options "-fanalyzer-call-summaries" } */
       2  
       3  #include <stdlib.h>
       4  #include "analyzer-decls.h"
       5  
       6  extern int foo (int);
       7  
       8  static int __attribute__((noinline))
       9  do_stuff (int *p, int n)
      10  {
      11    int sum = 0;
      12    int i;
      13    for (i = 0; i < n; i++)
      14      p[i] = i;
      15    for (i = 0; i < n; i++)
      16      sum += foo (p[i]); /* { dg-bogus "uninitialized" } */
      17    return sum;
      18  }
      19  
      20  static int __attribute__((noinline))
      21  do_stuff_2 (int *p, int n)
      22  {
      23    return 0;
      24  }
      25  
      26  /* Various examples of functions that use either a malloc buffer
      27     or a local buffer, do something, then conditionally free the
      28     buffer, tracking whether "free" is necessary in various
      29     ways.
      30  
      31     In each case, there ought to be only two paths through the function,
      32     not four.  */
      33  
      34  /* Repeated (n > 10) predicate.  */
      35  
      36  int test_repeated_predicate_1 (int n)
      37  {
      38    int buf[10];
      39    int *ptr;
      40    int result;
      41  
      42    if (n > 10)
      43      ptr = (int *)malloc (sizeof (int) * n);
      44    else
      45      ptr = buf;
      46  
      47    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
      48  
      49    result = do_stuff (ptr, n);
      50  
      51    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
      52  
      53    if (n > 10)
      54      free (ptr); /* { dg-bogus "not on the heap" } */
      55  
      56    return result; /* { dg-bogus "leak" } */
      57  }
      58  
      59  /* A simpler version of the above.  */
      60  
      61  int test_repeated_predicate_2 (int n)
      62  {
      63    int buf[10];
      64    int *ptr;
      65    int result;
      66  
      67    if (n > 10)
      68      ptr = (int *)malloc (sizeof (int) * n);
      69    else
      70      ptr = buf;
      71  
      72    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
      73  
      74    result = do_stuff_2 (ptr, n);
      75  
      76    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
      77  
      78    if (n > 10)
      79      free (ptr); /* { dg-bogus "not on the heap" } */
      80  
      81    return result; /* { dg-bogus "leak" } */
      82  }
      83  
      84  /* A predicate that sets a flag for the 2nd test.  */
      85  
      86  int test_explicit_flag (int n)
      87  {
      88    int buf[10];
      89    int *ptr;
      90    int result;
      91    int need_to_free = 0;
      92  
      93    if (n > 10)
      94      {
      95        ptr = (int *)malloc (sizeof (int) * n);
      96        need_to_free = 1;
      97      }
      98    else
      99      ptr = buf;
     100  
     101    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
     102  
     103    result = do_stuff (ptr, n);
     104  
     105    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
     106  
     107    if (need_to_free)
     108      free (ptr); /* { dg-bogus "not on the heap" } */
     109  
     110    return result; /* { dg-bogus "leak" } */
     111  }
     112  
     113  /* Pointer comparison.  */
     114  
     115  int test_pointer_comparison (int n)
     116  {
     117    int buf[10];
     118    int *ptr;
     119    int result;
     120  
     121    if (n > 10)
     122      ptr = (int *)malloc (sizeof (int) * n);
     123    else
     124      ptr = buf;
     125  
     126    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
     127  
     128    result = do_stuff (ptr, n);
     129  
     130    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
     131  
     132    if (ptr != buf)
     133      free (ptr); /* { dg-bogus "not on the heap" } */
     134  
     135    return result; /* { dg-bogus "leak" } */
     136  }
     137  
     138  /* Set a flag based on a conditional, then use it, then reuse the
     139     conditional.  */
     140  
     141  int test_initial_flag (int n)
     142  {
     143    int buf[10];
     144    int *ptr;
     145    int result;
     146    int on_heap = 0;
     147  
     148    if (n > 10)
     149      on_heap = 1;
     150    else
     151      on_heap = 0;
     152  
     153    /* Due to state-merging, we lose the relationship between 'n > 10'
     154       and 'on_heap' here; we have to rely on feasibility-checking
     155       in the diagnostic_manager to reject the false warnings.  */
     156    __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
     157  
     158    if (on_heap)
     159      ptr = (int *)malloc (sizeof (int) * n);
     160    else
     161      ptr = buf;
     162  
     163    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
     164  
     165    result = do_stuff (ptr, n);
     166  
     167    __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
     168  
     169    if (n > 10)
     170      free (ptr); /* { dg-bogus "not on the heap" } */
     171  
     172    return result; /* { dg-bogus "leak" } */
     173  }