diff options
Diffstat (limited to 'gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1b.c')
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1b.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1b.c b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1b.c new file mode 100644 index 0000000..1997bb7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1b.c @@ -0,0 +1,176 @@ +/* { dg-additional-options "-fanalyzer-call-summaries" } */ + +#include <stdlib.h> +#include "analyzer-decls.h" + +extern int foo (int); + +static int __attribute__((noinline)) +do_stuff (int *p, int n) +{ + int sum = 0; + int i; + for (i = 0; i < n; i++) + p[i] = i; + for (i = 0; i < n; i++) + sum += foo (p[i]); /* { dg-bogus "uninitialized" } */ + return sum; +} + +static int __attribute__((noinline)) +do_stuff_2 (int *p, int n) +{ + return 0; +} + +/* Various examples of functions that use either a malloc buffer + or a local buffer, do something, then conditionally free the + buffer, tracking whether "free" is necessary in various + ways. + + In each case, there ought to be only two paths through the function, + not four. */ + +/* Repeated (n > 10) predicate. */ + +int test_repeated_predicate_1 (int n) +{ + int buf[10]; + int *ptr; + int result; + + if (n > 10) + ptr = (int *)malloc (sizeof (int) * n); + else + ptr = buf; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + result = do_stuff (ptr, n); + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + if (n > 10) + free (ptr); /* { dg-bogus "not on the heap" } */ + + return result; /* { dg-bogus "leak" } */ +} + +/* A simpler version of the above. */ + +int test_repeated_predicate_2 (int n) +{ + int buf[10]; + int *ptr; + int result; + + if (n > 10) + ptr = (int *)malloc (sizeof (int) * n); + else + ptr = buf; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + result = do_stuff_2 (ptr, n); + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + if (n > 10) + free (ptr); /* { dg-bogus "not on the heap" } */ + + return result; /* { dg-bogus "leak" } */ +} + +/* A predicate that sets a flag for the 2nd test. */ + +int test_explicit_flag (int n) +{ + int buf[10]; + int *ptr; + int result; + int need_to_free = 0; + + if (n > 10) + { + ptr = (int *)malloc (sizeof (int) * n); + need_to_free = 1; + } + else + ptr = buf; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + result = do_stuff (ptr, n); + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + if (need_to_free) + free (ptr); /* { dg-bogus "not on the heap" } */ + + return result; /* { dg-bogus "leak" } */ +} + +/* Pointer comparison. */ + +int test_pointer_comparison (int n) +{ + int buf[10]; + int *ptr; + int result; + + if (n > 10) + ptr = (int *)malloc (sizeof (int) * n); + else + ptr = buf; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + result = do_stuff (ptr, n); + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + if (ptr != buf) + free (ptr); /* { dg-bogus "not on the heap" } */ + + return result; /* { dg-bogus "leak" } */ +} + +/* Set a flag based on a conditional, then use it, then reuse the + conditional. */ + +int test_initial_flag (int n) +{ + int buf[10]; + int *ptr; + int result; + int on_heap = 0; + + if (n > 10) + on_heap = 1; + else + on_heap = 0; + + /* Due to state-merging, we lose the relationship between 'n > 10' + and 'on_heap' here; we have to rely on feasibility-checking + in the diagnostic_manager to reject the false warnings. */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */ + + if (on_heap) + ptr = (int *)malloc (sizeof (int) * n); + else + ptr = buf; + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + result = do_stuff (ptr, n); + + __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */ + + if (n > 10) + free (ptr); /* { dg-bogus "not on the heap" } */ + + return result; /* { dg-bogus "leak" } */ +} |