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))
do_stuff(int * p,int n)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))
do_stuff_2(int * p,int n)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
test_repeated_predicate_1(int n)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
test_repeated_predicate_2(int n)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
test_explicit_flag(int n)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
test_pointer_comparison(int n)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
test_initial_flag(int n)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 }
174