1 /* { dg-additional-options "-fno-analyzer-call-summaries -fanalyzer-transitivity" } */
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 "3 processed enodes" } */
52 // FIXME: why 3 here?
53 __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */
54 // FIXME: why 3 here?
55
56 if (n > 10)
57 free (ptr); /* { dg-bogus "not on the heap" } */
58
59 return result; /* { dg-bogus "leak" } */
60 }
61
62 /* A simpler version of the above. */
63
test_repeated_predicate_2(int n)64 int test_repeated_predicate_2 (int n)
65 {
66 int buf[10];
67 int *ptr;
68 int result;
69
70 if (n > 10)
71 ptr = (int *)malloc (sizeof (int) * n);
72 else
73 ptr = buf;
74
75 __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
76
77 result = do_stuff_2 (ptr, n);
78
79 __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
80
81 if (n > 10)
82 free (ptr); /* { dg-bogus "not on the heap" } */
83
84 return result; /* { dg-bogus "leak" } */
85 }
86
87 /* A predicate that sets a flag for the 2nd test. */
88
test_explicit_flag(int n)89 int test_explicit_flag (int n)
90 {
91 int buf[10];
92 int *ptr;
93 int result;
94 int need_to_free = 0;
95
96 if (n > 10)
97 {
98 ptr = (int *)malloc (sizeof (int) * n);
99 need_to_free = 1;
100 }
101 else
102 ptr = buf;
103
104 __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
105
106 result = do_stuff (ptr, n);
107
108 __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */
109 // FIXME: why 3 here?
110
111 if (need_to_free)
112 free (ptr); /* { dg-bogus "not on the heap" } */
113
114 return result; /* { dg-bogus "leak" } */
115 }
116
117 /* Pointer comparison. */
118
test_pointer_comparison(int n)119 int test_pointer_comparison (int n)
120 {
121 int buf[10];
122 int *ptr;
123 int result;
124
125 if (n > 10)
126 ptr = (int *)malloc (sizeof (int) * n);
127 else
128 ptr = buf;
129
130 __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
131
132 result = do_stuff (ptr, n);
133
134 __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 processed enodes" } */
135 // FIXME: why 3 here?
136
137 if (ptr != buf)
138 free (ptr); /* { dg-bogus "not on the heap" } */
139
140 return result; /* { dg-bogus "leak" } */
141 }
142
143 /* Set a flag based on a conditional, then use it, then reuse the
144 conditional. */
145
test_initial_flag(int n)146 int test_initial_flag (int n)
147 {
148 int buf[10];
149 int *ptr;
150 int result;
151 int on_heap = 0;
152
153 if (n > 10)
154 on_heap = 1;
155 else
156 on_heap = 0;
157
158 /* Due to state-merging, we lose the relationship between 'n > 10'
159 and 'on_heap' here; we have to rely on feasibility-checking
160 in the diagnostic_manager to reject the false warnings. */
161 __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
162
163 if (on_heap)
164 ptr = (int *)malloc (sizeof (int) * n);
165 else
166 ptr = buf;
167
168 __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
169
170 result = do_stuff (ptr, n);
171
172 __analyzer_dump_exploded_nodes (0); /* { dg-warning "5 processed enodes" } */
173 // FIXME: why 5 here?
174
175 if (n > 10)
176 free (ptr); /* { dg-bogus "not on the heap" } */
177
178 return result; /* { dg-bogus "leak" } */
179 }
180