1 /* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret -fanalyzer-verbosity=3" } */
2 /* { dg-enable-nn-line-numbers "" } */
3
4 #include <stdlib.h>
5
calls_free_1(void * ptr)6 void calls_free_1 (void *ptr)
7 {
8 free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
9 }
10
test_1(void * ptr,int a,int b)11 void test_1 (void *ptr, int a, int b)
12 {
13 if (a)
14 calls_free_1 (ptr);
15
16 if (b)
17 {
18 }
19 else
20 calls_free_1 (ptr);
21 }
22
23 /* { dg-begin-multiline-output "" }
24 NN | free (ptr);
25 | ^~~~~~~~~~
26 'test_1': events 1-4
27 |
28 | NN | void test_1 (void *ptr, int a, int b)
29 | | ^~~~~~
30 | | |
31 | | (1) entry to 'test_1'
32 | NN | {
33 | NN | if (a)
34 | | ~
35 | | |
36 | | (2) following 'true' branch (when 'a != 0')...
37 | NN | calls_free_1 (ptr);
38 | | ~~~~~~~~~~~~~~~~~~
39 | | |
40 | | (3) ...to here
41 | | (4) calling 'calls_free_1' from 'test_1'
42 |
43 +--> 'calls_free_1': events 5-6
44 |
45 | NN | void calls_free_1 (void *ptr)
46 | | ^~~~~~~~~~~~
47 | | |
48 | | (5) entry to 'calls_free_1'
49 | NN | {
50 | NN | free (ptr);
51 | | ~~~~~~~~~~
52 | | |
53 | | (6) first 'free' here
54 |
55 <------+
56 |
57 'test_1': events 7-10
58 |
59 | NN | calls_free_1 (ptr);
60 | | ^~~~~~~~~~~~~~~~~~
61 | | |
62 | | (7) returning to 'test_1' from 'calls_free_1'
63 | NN |
64 | NN | if (b)
65 | | ~
66 | | |
67 | | (8) following 'false' branch (when 'b == 0')...
68 |......
69 | NN | calls_free_1 (ptr);
70 | | ~~~~~~~~~~~~~~~~~~
71 | | |
72 | | (9) ...to here
73 | | (10) passing freed pointer 'ptr' in call to 'calls_free_1' from 'test_1'
74 |
75 +--> 'calls_free_1': events 11-12
76 |
77 | NN | void calls_free_1 (void *ptr)
78 | | ^~~~~~~~~~~~
79 | | |
80 | | (11) entry to 'calls_free_1'
81 | NN | {
82 | NN | free (ptr);
83 | | ~~~~~~~~~~
84 | | |
85 | | (12) second 'free' here; first 'free' was at (6)
86 |
87 { dg-end-multiline-output "" } */
88
calls_free_2(void * ptr)89 void calls_free_2 (void *ptr)
90 {
91 free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
92 }
93
test_2(void * ptr,int a,int b)94 void test_2 (void *ptr, int a, int b)
95 {
96 switch (a)
97 {
98 default:
99 break;
100 case 1:
101 break;
102 case 3:
103 calls_free_2 (ptr);
104 break;
105 }
106
107 switch (b)
108 {
109 default:
110 calls_free_2 (ptr);
111 break;
112 case 1:
113 break;
114 case 42:
115 break;
116 }
117 }
118
119 /* { dg-begin-multiline-output "" }
120 NN | free (ptr);
121 | ^~~~~~~~~~
122 'test_2': events 1-4
123 |
124 | NN | void test_2 (void *ptr, int a, int b)
125 | | ^~~~~~
126 | | |
127 | | (1) entry to 'test_2'
128 | NN | {
129 | NN | switch (a)
130 | | ~~~~~~
131 | | |
132 | | (2) following 'case 3:' branch...
133 |......
134 | NN | case 3:
135 | | ~~~~
136 | | |
137 | | (3) ...to here
138 | NN | calls_free_2 (ptr);
139 | | ~~~~~~~~~~~~~~~~~~
140 | | |
141 | | (4) calling 'calls_free_2' from 'test_2'
142 |
143 +--> 'calls_free_2': events 5-6
144 |
145 | NN | void calls_free_2 (void *ptr)
146 | | ^~~~~~~~~~~~
147 | | |
148 | | (5) entry to 'calls_free_2'
149 | NN | {
150 | NN | free (ptr);
151 | | ~~~~~~~~~~
152 | | |
153 | | (6) first 'free' here
154 |
155 <------+
156 |
157 'test_2': events 7-10
158 |
159 | NN | calls_free_2 (ptr);
160 | | ^~~~~~~~~~~~~~~~~~
161 | | |
162 | | (7) returning to 'test_2' from 'calls_free_2'
163 |......
164 | NN | switch (b)
165 | | ~~~~~~
166 | | |
167 | | (8) following 'default:' branch...
168 | NN | {
169 | NN | default:
170 | | ~~~~~~~
171 | | |
172 | | (9) ...to here
173 | NN | calls_free_2 (ptr);
174 | | ~~~~~~~~~~~~~~~~~~
175 | | |
176 | | (10) passing freed pointer 'ptr' in call to 'calls_free_2' from 'test_2'
177 |
178 +--> 'calls_free_2': events 11-12
179 |
180 | NN | void calls_free_2 (void *ptr)
181 | | ^~~~~~~~~~~~
182 | | |
183 | | (11) entry to 'calls_free_2'
184 | NN | {
185 | NN | free (ptr);
186 | | ~~~~~~~~~~
187 | | |
188 | | (12) second 'free' here; first 'free' was at (6)
189 |
190 { dg-end-multiline-output "" } */
191
192 // TODO: range cases
193
194 /* The call/return to this function shouldn't appear in the path. */
195
called_by_test_3(void)196 void called_by_test_3 (void)
197 {
198 }
199
test_3(void * ptr)200 void test_3 (void *ptr)
201 {
202 free (ptr);
203 called_by_test_3 ();
204 free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
205 }
206
207 /* { dg-begin-multiline-output "" }
208 NN | free (ptr);
209 | ^~~~~~~~~~
210 'test_3': events 1-2
211 |
212 | NN | free (ptr);
213 | | ^~~~~~~~~~
214 | | |
215 | | (1) first 'free' here
216 | NN | called_by_test_3 ();
217 | NN | free (ptr);
218 | | ~~~~~~~~~~
219 | | |
220 | | (2) second 'free' here; first 'free' was at (1)
221 |
222 { dg-end-multiline-output "" } */
223