1 // RUN: %clang_analyze_cc1 %s -std=c++14 \
2 // RUN: -verify=expected,tracking \
3 // RUN: -analyzer-config track-conditions=true \
4 // RUN: -analyzer-output=text \
5 // RUN: -analyzer-checker=core
6
7 // RUN: not %clang_analyze_cc1 -std=c++14 -verify %s \
8 // RUN: -analyzer-checker=core \
9 // RUN: -analyzer-config track-conditions=false \
10 // RUN: -analyzer-config track-conditions-debug=true \
11 // RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-DEBUG
12
13 // CHECK-INVALID-DEBUG: (frontend): invalid input for analyzer-config option
14 // CHECK-INVALID-DEBUG-SAME: 'track-conditions-debug', that expects
15 // CHECK-INVALID-DEBUG-SAME: 'track-conditions' to also be enabled
16 //
17 // RUN: %clang_analyze_cc1 %s -std=c++14 \
18 // RUN: -verify=expected,tracking,debug \
19 // RUN: -analyzer-config track-conditions=true \
20 // RUN: -analyzer-config track-conditions-debug=true \
21 // RUN: -analyzer-output=text \
22 // RUN: -analyzer-checker=core
23
24 // RUN: %clang_analyze_cc1 %s -std=c++14 -verify \
25 // RUN: -analyzer-output=text \
26 // RUN: -analyzer-config track-conditions=false \
27 // RUN: -analyzer-checker=core
28
29 namespace example_1 {
30 int flag;
31 bool coin();
32
foo()33 void foo() {
34 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
35 }
36
test()37 void test() {
38 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
39 flag = 1;
40
41 foo(); // TODO: Add nodes here about flag's value being invalidated.
42 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}}
43 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
44 x = new int;
45
46 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
47 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
48
49 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
50 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
51 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
52
53 *x = 5; // expected-warning{{Dereference of null pointer}}
54 // expected-note@-1{{Dereference of null pointer}}
55 }
56 } // end of namespace example_1
57
58 namespace example_2 {
59 int flag;
60 bool coin();
61
foo()62 void foo() {
63 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
64 }
65
test()66 void test() {
67 int *x = 0;
68 flag = 1;
69
70 foo();
71 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}}
72 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
73 x = new int;
74
75 x = 0; // expected-note-re{{{{^}}Null pointer value stored to 'x'{{$}}}}
76
77 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
78 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
79
80 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
81 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
82 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
83
84 *x = 5; // expected-warning{{Dereference of null pointer}}
85 // expected-note@-1{{Dereference of null pointer}}
86 }
87 } // end of namespace example_2
88
89 namespace global_variable_invalidation {
90 int flag;
91 bool coin();
92
foo()93 void foo() {
94 // coin() could write bar, do it's invalidated.
95 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
96 // tracking-note-re@-1{{{{^}}Value assigned to 'bar', which participates in a condition later{{$}}}}
97 }
98
99 int bar;
100
test()101 void test() {
102 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
103 flag = 1;
104
105 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
106 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
107
108 if (bar) // expected-note-re {{{{^}}Assuming 'bar' is not equal to 0{{$}}}}
109 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
110 // debug-note-re@-2{{{{^}}Tracking condition 'bar'{{$}}}}
111 if (flag) // expected-note-re {{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
112 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
113 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
114
115 *x = 5; // expected-warning{{Dereference of null pointer}}
116 // expected-note@-1{{Dereference of null pointer}}
117 }
118 } // end of namespace global_variable_invalidation
119
120 namespace variable_declaration_in_condition {
121 bool coin();
122
foo()123 bool foo() {
124 return coin();
125 }
126
127 int bar;
128
test()129 void test() {
130 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
131
132 if (int flag = foo()) // debug-note-re{{{{^}}Tracking condition 'flag'{{$}}}}
133 // expected-note-re@-1{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
134 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}}
135
136 *x = 5; // expected-warning{{Dereference of null pointer}}
137 // expected-note@-1{{Dereference of null pointer}}
138 }
139 } // end of namespace variable_declaration_in_condition
140
141 namespace conversion_to_bool {
142 bool coin();
143
144 struct ConvertsToBool {
operator boolconversion_to_bool::ConvertsToBool145 operator bool() const { return coin(); }
146 };
147
test()148 void test() {
149 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
150
151 if (ConvertsToBool())
152 // debug-note-re@-1{{{{^}}Tracking condition 'ConvertsToBool()'{{$}}}}
153 // expected-note-re@-2{{{{^}}Assuming the condition is true{{$}}}}
154 // expected-note-re@-3{{{{^}}Taking true branch{{$}}}}
155 *x = 5; // expected-warning{{Dereference of null pointer}}
156 // expected-note@-1{{Dereference of null pointer}}
157 }
158
159 } // end of namespace variable_declaration_in_condition
160
161 namespace note_from_different_but_not_nested_stackframe {
162
nullptrDeref(int * ptr,bool True)163 void nullptrDeref(int *ptr, bool True) {
164 if (True) // expected-note-re{{{{^}}'True' is true{{$}}}}
165 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
166 // debug-note-re@-2{{{{^}}Tracking condition 'True'{{$}}}}
167 *ptr = 5;
168 // expected-note@-1{{Dereference of null pointer (loaded from variable 'ptr')}}
169 // expected-warning@-2{{Dereference of null pointer (loaded from variable 'ptr')}}
170 }
171
f()172 void f() {
173 int *ptr = nullptr;
174 // expected-note-re@-1{{{{^}}'ptr' initialized to a null pointer value{{$}}}}
175 bool True = true;
176 nullptrDeref(ptr, True);
177 // expected-note-re@-1{{{{^}}Passing null pointer value via 1st parameter 'ptr'{{$}}}}
178 // expected-note-re@-2{{{{^}}Calling 'nullptrDeref'{{$}}}}
179 }
180
181 } // end of namespace note_from_different_but_not_nested_stackframe
182
183 namespace important_returning_pointer_loaded_from {
184 bool coin();
185
186 int *getIntPtr();
187
storeValue(int ** i)188 void storeValue(int **i) {
189 *i = getIntPtr(); // tracking-note-re{{{{^}}Value assigned to 'i', which participates in a condition later{{$}}}}
190 }
191
conjurePointer()192 int *conjurePointer() {
193 int *i;
194 storeValue(&i); // tracking-note-re{{{{^}}Calling 'storeValue'{{$}}}}
195 // tracking-note-re@-1{{{{^}}Returning from 'storeValue'{{$}}}}
196 return i; // tracking-note-re{{{{^}}Returning pointer (loaded from 'i'), which participates in a condition later{{$}}}}
197 }
198
f(int * ptr)199 void f(int *ptr) {
200 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
201 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
202 ;
203 if (!conjurePointer())
204 // tracking-note-re@-1{{{{^}}Calling 'conjurePointer'{{$}}}}
205 // tracking-note-re@-2{{{{^}}Returning from 'conjurePointer'{{$}}}}
206 // debug-note-re@-3{{{{^}}Tracking condition '!conjurePointer()'{{$}}}}
207 // expected-note-re@-4{{{{^}}Assuming the condition is true{{$}}}}
208 // expected-note-re@-5{{{{^}}Taking true branch{{$}}}}
209 *ptr = 5; // expected-warning{{Dereference of null pointer}}
210 // expected-note@-1{{Dereference of null pointer}}
211 }
212 } // end of namespace important_returning_pointer_loaded_from
213
214 namespace unimportant_returning_pointer_loaded_from {
215 bool coin();
216
217 int *getIntPtr();
218
conjurePointer()219 int *conjurePointer() {
220 int *i = getIntPtr();
221 return i;
222 }
223
f(int * ptr)224 void f(int *ptr) {
225 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
226 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
227 ;
228 if (!conjurePointer())
229 // debug-note-re@-1{{{{^}}Tracking condition '!conjurePointer()'{{$}}}}
230 // expected-note-re@-2{{{{^}}Assuming the condition is true{{$}}}}
231 // expected-note-re@-3{{{{^}}Taking true branch{{$}}}}
232 *ptr = 5; // expected-warning{{Dereference of null pointer}}
233 // expected-note@-1{{Dereference of null pointer}}
234 }
235 } // end of namespace unimportant_returning_pointer_loaded_from
236
237 namespace unimportant_returning_pointer_loaded_from_through_cast {
238
239 void *conjure();
240
cast(void * P)241 int *cast(void *P) {
242 return static_cast<int *>(P);
243 }
244
f()245 void f() {
246 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
247
248 if (cast(conjure()))
249 // debug-note-re@-1{{{{^}}Tracking condition 'cast(conjure())'{{$}}}}
250 // expected-note-re@-2{{{{^}}Assuming the condition is false{{$}}}}
251 // expected-note-re@-3{{{{^}}Taking false branch{{$}}}}
252 return;
253 *x = 5; // expected-warning{{Dereference of null pointer}}
254 // expected-note@-1{{Dereference of null pointer}}
255 }
256
257 } // end of namespace unimportant_returning_pointer_loaded_from_through_cast
258
259 namespace unimportant_returning_value_note {
260 bool coin();
261
flipCoin()262 bool flipCoin() { return coin(); }
263
i(int * ptr)264 void i(int *ptr) {
265 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
266 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
267 ;
268 if (!flipCoin())
269 // debug-note-re@-1{{{{^}}Tracking condition '!flipCoin()'{{$}}}}
270 // expected-note-re@-2{{{{^}}Assuming the condition is true{{$}}}}
271 // expected-note-re@-3{{{{^}}Taking true branch{{$}}}}
272 *ptr = 5; // expected-warning{{Dereference of null pointer}}
273 // expected-note@-1{{Dereference of null pointer}}
274 }
275 } // end of namespace unimportant_returning_value_note
276
277 namespace important_returning_value_note {
278 bool coin();
279
flipCoin()280 bool flipCoin() {
281 if (coin()) // tracking-note-re{{{{^}}Assuming the condition is false{{$}}}}
282 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
283 // debug-note-re@-2{{{{^}}Tracking condition 'coin()'{{$}}}}
284 return true;
285 return coin(); // tracking-note-re{{{{^}}Returning value, which participates in a condition later{{$}}}}
286 }
287
i(int * ptr)288 void i(int *ptr) {
289 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
290 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
291 ;
292 if (!flipCoin())
293 // tracking-note-re@-1{{{{^}}Calling 'flipCoin'{{$}}}}
294 // tracking-note-re@-2{{{{^}}Returning from 'flipCoin'{{$}}}}
295 // debug-note-re@-3{{{{^}}Tracking condition '!flipCoin()'{{$}}}}
296 // expected-note-re@-4{{{{^}}Assuming the condition is true{{$}}}}
297 // expected-note-re@-5{{{{^}}Taking true branch{{$}}}}
298 *ptr = 5; // expected-warning{{Dereference of null pointer}}
299 // expected-note@-1{{Dereference of null pointer}}
300 }
301 } // end of namespace important_returning_value_note
302
303 namespace important_returning_value_note_in_linear_function {
304 bool coin();
305
306 struct super_complicated_template_hackery {
307 static constexpr bool value = false;
308 };
309
flipCoin()310 bool flipCoin() {
311 if (super_complicated_template_hackery::value)
312 // tracking-note-re@-1{{{{^}}'value' is false{{$}}}}
313 // tracking-note-re@-2{{{{^}}Taking false branch{{$}}}}
314 return true;
315 return coin(); // tracking-note-re{{{{^}}Returning value, which participates in a condition later{{$}}}}
316 }
317
i(int * ptr)318 void i(int *ptr) {
319 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
320 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
321 ;
322 if (!flipCoin())
323 // tracking-note-re@-1{{{{^}}Calling 'flipCoin'{{$}}}}
324 // tracking-note-re@-2{{{{^}}Returning from 'flipCoin'{{$}}}}
325 // debug-note-re@-3{{{{^}}Tracking condition '!flipCoin()'{{$}}}}
326 // expected-note-re@-4{{{{^}}Assuming the condition is true{{$}}}}
327 // expected-note-re@-5{{{{^}}Taking true branch{{$}}}}
328 *ptr = 5; // expected-warning{{Dereference of null pointer}}
329 // expected-note@-1{{Dereference of null pointer}}
330 }
331 } // end of namespace important_returning_value_note_in_linear_function
332
333 namespace tracked_condition_is_only_initialized {
334 int getInt();
335
f()336 void f() {
337 int flag = getInt();
338 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
339 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
340 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
341 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
342 *x = 5; // expected-warning{{Dereference of null pointer}}
343 // expected-note@-1{{Dereference of null pointer}}
344 }
345 } // end of namespace tracked_condition_is_only_initialized
346
347 namespace tracked_condition_written_in_same_stackframe {
348 int flag;
349 int getInt();
350
f(int y)351 void f(int y) {
352 y = 1;
353 flag = y;
354
355 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
356 if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}}
357 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
358 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
359 *x = 5; // expected-warning{{Dereference of null pointer}}
360 // expected-note@-1{{Dereference of null pointer}}
361 }
362 } // end of namespace tracked_condition_written_in_same_stackframe
363
364 namespace tracked_condition_written_in_nested_stackframe {
365 int flag;
366 int getInt();
367
foo()368 void foo() {
369 int y;
370 y = 1;
371 flag = y; // tracking-note-re{{{{^}}The value 1 is assigned to 'flag', which participates in a condition later{{$}}}}
372 }
373
f(int y)374 void f(int y) {
375 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
376
377 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
378 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
379
380 if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}}
381 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
382 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
383 *x = 5; // expected-warning{{Dereference of null pointer}}
384 // expected-note@-1{{Dereference of null pointer}}
385 }
386 } // end of namespace tracked_condition_written_in_nested_stackframe
387
388 namespace condition_written_in_nested_stackframe_before_assignment {
389 int flag = 0;
390 int getInt();
391
foo()392 void foo() {
393 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
394 }
395
f()396 void f() {
397 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
398 int y = 0;
399
400 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
401 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
402 y = flag;
403
404 if (y) // expected-note-re{{{{^}}Assuming 'y' is not equal to 0{{$}}}}
405 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
406 // debug-note-re@-2{{{{^}}Tracking condition 'y'{{$}}}}
407 *x = 5; // expected-warning{{Dereference of null pointer}}
408 // expected-note@-1{{Dereference of null pointer}}
409 }
410 } // end of namespace condition_written_in_nested_stackframe_before_assignment
411
412 namespace dont_explain_foreach_loops {
413
414 struct Iterator {
415 int *pos;
operator !=dont_explain_foreach_loops::Iterator416 bool operator!=(Iterator other) const {
417 return pos && other.pos && pos != other.pos;
418 }
419 int operator*();
420 Iterator operator++();
421 };
422
423 struct Container {
424 Iterator begin();
425 Iterator end();
426 };
427
f(Container Cont)428 void f(Container Cont) {
429 int flag = 0;
430 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
431 for (int i : Cont)
432 if (i) // expected-note-re {{{{^}}Assuming 'i' is not equal to 0{{$}}}}
433 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
434 // debug-note-re@-2{{{{^}}Tracking condition 'i'{{$}}}}
435 flag = i;
436
437 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
438 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
439 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
440 *x = 5; // expected-warning{{Dereference of null pointer}}
441 // expected-note@-1{{Dereference of null pointer}}
442 }
443 } // end of namespace dont_explain_foreach_loops
444
445 namespace condition_lambda_capture_by_reference_last_write {
446 int getInt();
447
448 [[noreturn]] void halt();
449
f(int flag)450 void f(int flag) {
451 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
452
453 auto lambda = [&flag]() {
454 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
455 };
456
457 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}}
458 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}}
459
460 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
461 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
462 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
463 *x = 5; // expected-warning{{Dereference of null pointer}}
464 // expected-note@-1{{Dereference of null pointer}}
465 }
466 } // end of namespace condition_lambda_capture_by_reference_last_write
467
468 namespace condition_lambda_capture_by_value_assumption {
469 int getInt();
470
471 [[noreturn]] void halt();
472
bar(int & flag)473 void bar(int &flag) {
474 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
475 }
476
f(int flag)477 void f(int flag) {
478 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
479
480 auto lambda = [flag]() {
481 if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}}
482 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
483 halt();
484 };
485
486 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}}
487 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}}
488 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}}
489 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}}
490
491 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
492 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
493 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
494 *x = 5; // expected-warning{{Dereference of null pointer}}
495 // expected-note@-1{{Dereference of null pointer}}
496 }
497 } // end of namespace condition_lambda_capture_by_value_assumption
498
499 namespace condition_lambda_capture_by_reference_assumption {
500 int getInt();
501
502 [[noreturn]] void halt();
503
bar(int & flag)504 void bar(int &flag) {
505 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
506 }
507
f(int flag)508 void f(int flag) {
509 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
510
511 auto lambda = [&flag]() {
512 if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}}
513 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
514 halt();
515 };
516
517 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}}
518 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}}
519 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}}
520 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}}
521
522 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
523 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
524 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
525 *x = 5; // expected-warning{{Dereference of null pointer}}
526 // expected-note@-1{{Dereference of null pointer}}
527 }
528 } // end of namespace condition_lambda_capture_by_reference_assumption
529
530 namespace collapse_point_not_in_condition_bool {
531
532 [[noreturn]] void halt();
533
check(bool b)534 void check(bool b) {
535 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is true, which participates in a condition later{{$}}}}
536 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
537 halt();
538 }
539
f(bool flag)540 void f(bool flag) {
541 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
542
543 check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}}
544 // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}}
545
546 if (flag) // expected-note-re{{{{^}}'flag' is true{{$}}}}
547 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
548 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
549 *x = 5; // expected-warning{{Dereference of null pointer}}
550 // expected-note@-1{{Dereference of null pointer}}
551 }
552 } // end of namespace collapse_point_not_in_condition_bool
553
554 namespace collapse_point_not_in_condition {
555
556 [[noreturn]] void halt();
557
assert(int b)558 void assert(int b) {
559 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}}
560 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
561 halt();
562 }
563
f(int flag)564 void f(int flag) {
565 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
566
567 assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}}
568 // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}}
569
570 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
571 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
572 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
573 *x = 5; // expected-warning{{Dereference of null pointer}}
574 // expected-note@-1{{Dereference of null pointer}}
575 }
576
577 } // end of namespace collapse_point_not_in_condition
578
579 namespace unimportant_write_before_collapse_point {
580
581 [[noreturn]] void halt();
582
assert(int b)583 void assert(int b) {
584 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}}
585 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
586 halt();
587 }
588 int getInt();
589
f(int flag)590 void f(int flag) {
591 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
592
593 flag = getInt();
594 assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}}
595 // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}}
596
597 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
598 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
599 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
600 *x = 5; // expected-warning{{Dereference of null pointer}}
601 // expected-note@-1{{Dereference of null pointer}}
602 }
603
604 } // end of namespace unimportant_write_before_collapse_point
605
606 namespace dont_crash_on_nonlogical_binary_operator {
607
f6(int x)608 void f6(int x) {
609 int a[20];
610 if (x == 25) {} // expected-note{{Assuming 'x' is equal to 25}}
611 // expected-note@-1{{Taking true branch}}
612 if (a[x] == 123) {} // expected-warning{{The left operand of '==' is a garbage value due to array index out of bounds}}
613 // expected-note@-1{{The left operand of '==' is a garbage value due to array index out of bounds}}
614 }
615
616 } // end of namespace dont_crash_on_nonlogical_binary_operator
617
618 namespace collapse_point_not_in_condition_binary_op {
619
620 [[noreturn]] void halt();
621
check(int b)622 void check(int b) {
623 if (b == 1) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 1, which participates in a condition later{{$}}}}
624 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
625 halt();
626 }
627
f(int flag)628 void f(int flag) {
629 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
630
631 check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}}
632 // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}}
633
634 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
635 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
636 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
637 *x = 5; // expected-warning{{Dereference of null pointer}}
638 // expected-note@-1{{Dereference of null pointer}}
639 }
640
641 } // end of namespace collapse_point_not_in_condition_binary_op
642
643 namespace collapse_point_not_in_condition_as_field {
644
645 [[noreturn]] void halt();
646 struct IntWrapper {
647 int b;
648 IntWrapper();
649
checkcollapse_point_not_in_condition_as_field::IntWrapper650 void check() {
651 if (!b) // tracking-note-re{{{{^}}Assuming field 'b' is not equal to 0, which participates in a condition later{{$}}}}
652 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
653 halt();
654 return;
655 }
656 };
657
f(IntWrapper i)658 void f(IntWrapper i) {
659 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
660
661 i.check(); // tracking-note-re{{{{^}}Calling 'IntWrapper::check'{{$}}}}
662 // tracking-note-re@-1{{{{^}}Returning from 'IntWrapper::check'{{$}}}}
663 if (i.b) // expected-note-re{{{{^}}Field 'b' is not equal to 0{{$}}}}
664 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
665 // debug-note-re@-2{{{{^}}Tracking condition 'i.b'{{$}}}}
666 *x = 5; // expected-warning{{Dereference of null pointer}}
667 // expected-note@-1{{Dereference of null pointer}}
668 }
669
670 } // end of namespace collapse_point_not_in_condition_as_field
671
672 namespace assignemnt_in_condition_in_nested_stackframe {
673 int flag;
674
675 bool coin();
676
677 [[noreturn]] void halt();
678
foo()679 void foo() {
680 if ((flag = coin()))
681 // tracking-note-re@-1{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
682 // tracking-note-re@-2{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}}
683 // tracking-note-re@-3{{{{^}}Taking true branch{{$}}}}
684 return;
685 halt();
686 return;
687 }
688
f()689 void f() {
690 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
691
692 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
693 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
694 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
695 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
696 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
697 *x = 5; // expected-warning{{Dereference of null pointer}}
698 // expected-note@-1{{Dereference of null pointer}}
699 }
700 } // end of namespace assignemnt_in_condition_in_nested_stackframe
701
702 namespace condition_variable_less {
703 int flag;
704
705 bool coin();
706
707 [[noreturn]] void halt();
708
foo()709 void foo() {
710 if (flag > 0)
711 // tracking-note-re@-1{{{{^}}Assuming 'flag' is > 0, which participates in a condition later{{$}}}}
712 // tracking-note-re@-2{{{{^}}Taking true branch{{$}}}}
713 return;
714 halt();
715 return;
716 }
717
f()718 void f() {
719 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
720
721 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
722 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
723 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
724 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
725 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
726 *x = 5; // expected-warning{{Dereference of null pointer}}
727 // expected-note@-1{{Dereference of null pointer}}
728 }
729 } // end of namespace condition_variable_less
730
731 namespace dont_track_assertlike_conditions {
732
733 extern void __assert_fail(__const char *__assertion, __const char *__file,
734 unsigned int __line, __const char *__function)
735 __attribute__((__noreturn__));
736 #define assert(expr) \
737 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__))
738
739 int getInt();
740
741 int cond1;
742
bar()743 void bar() {
744 cond1 = getInt();
745 }
746
f(int flag)747 void f(int flag) {
748 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
749
750 flag = getInt();
751
752 bar();
753 assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
754 // expected-note-re@-1{{{{^}}'?' condition is true{{$}}}}
755
756 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
757 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
758 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
759 *x = 5; // expected-warning{{Dereference of null pointer}}
760 // expected-note@-1{{Dereference of null pointer}}
761 }
762
763 #undef assert
764 } // end of namespace dont_track_assertlike_conditions
765
766 namespace dont_track_assertlike_and_conditions {
767
768 extern void __assert_fail(__const char *__assertion, __const char *__file,
769 unsigned int __line, __const char *__function)
770 __attribute__((__noreturn__));
771 #define assert(expr) \
772 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__))
773
774 int getInt();
775
776 int cond1;
777 int cond2;
778
bar()779 void bar() {
780 cond1 = getInt();
781 cond2 = getInt();
782 }
783
f(int flag)784 void f(int flag) {
785 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
786
787 flag = getInt();
788
789 bar();
790 assert(cond1 && cond2);
791 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
792 // expected-note-re@-2{{{{^}}Assuming 'cond2' is not equal to 0{{$}}}}
793 // expected-note-re@-3{{{{^}}'?' condition is true{{$}}}}
794 // expected-note-re@-4{{{{^}}Left side of '&&' is true{{$}}}}
795
796 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
797 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
798 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
799 *x = 5; // expected-warning{{Dereference of null pointer}}
800 // expected-note@-1{{Dereference of null pointer}}
801 }
802
803 #undef assert
804 } // end of namespace dont_track_assertlike_and_conditions
805
806 namespace dont_track_assertlike_or_conditions {
807
808 extern void __assert_fail(__const char *__assertion, __const char *__file,
809 unsigned int __line, __const char *__function)
810 __attribute__((__noreturn__));
811 #define assert(expr) \
812 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__))
813
814 int getInt();
815
816 int cond1;
817 int cond2;
818
bar()819 void bar() {
820 cond1 = getInt();
821 cond2 = getInt();
822 }
823
f(int flag)824 void f(int flag) {
825 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
826
827 flag = getInt();
828
829 bar();
830 assert(cond1 || cond2);
831 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
832 // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}}
833
834 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
835 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
836 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
837 *x = 5; // expected-warning{{Dereference of null pointer}}
838 // expected-note@-1{{Dereference of null pointer}}
839 }
840
841 #undef assert
842 } // end of namespace dont_track_assertlike_or_conditions
843
844 namespace dont_track_assert2like_conditions {
845
846 extern void __assert_fail(__const char *__assertion, __const char *__file,
847 unsigned int __line, __const char *__function)
848 __attribute__((__noreturn__));
849 #define assert(expr) \
850 do { \
851 if (!(expr)) \
852 __assert_fail(#expr, __FILE__, __LINE__, __func__); \
853 } while (0)
854
855 int getInt();
856
857 int cond1;
858
bar()859 void bar() {
860 cond1 = getInt();
861 }
862
f(int flag)863 void f(int flag) {
864 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
865
866 flag = getInt();
867
868 bar();
869 assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
870 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
871 // expected-note-re@-2{{{{^}}Loop condition is false. Exiting loop{{$}}}}
872
873 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
874 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
875 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
876 *x = 5; // expected-warning{{Dereference of null pointer}}
877 // expected-note@-1{{Dereference of null pointer}}
878 }
879
880 #undef assert
881 } // end of namespace dont_track_assert2like_conditions
882
883 namespace dont_track_assert2like_and_conditions {
884
885 extern void __assert_fail(__const char *__assertion, __const char *__file,
886 unsigned int __line, __const char *__function)
887 __attribute__((__noreturn__));
888 #define assert(expr) \
889 do { \
890 if (!(expr)) \
891 __assert_fail(#expr, __FILE__, __LINE__, __func__); \
892 } while (0)
893
894 int getInt();
895
896 int cond1;
897 int cond2;
898
bar()899 void bar() {
900 cond1 = getInt();
901 cond2 = getInt();
902 }
903
f(int flag)904 void f(int flag) {
905 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
906
907 flag = getInt();
908
909 bar();
910 assert(cond1 && cond2);
911 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
912 // expected-note-re@-2{{{{^}}Left side of '&&' is true{{$}}}}
913 // expected-note-re@-3{{{{^}}Assuming the condition is false{{$}}}}
914 // expected-note-re@-4{{{{^}}Taking false branch{{$}}}}
915 // expected-note-re@-5{{{{^}}Loop condition is false. Exiting loop{{$}}}}
916
917 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
918 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
919 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
920 *x = 5; // expected-warning{{Dereference of null pointer}}
921 // expected-note@-1{{Dereference of null pointer}}
922 }
923
924 #undef assert
925 } // end of namespace dont_track_assert2like_and_conditions
926
927 namespace dont_track_assert2like_or_conditions {
928
929 extern void __assert_fail(__const char *__assertion, __const char *__file,
930 unsigned int __line, __const char *__function)
931 __attribute__((__noreturn__));
932 #define assert(expr) \
933 do { \
934 if (!(expr)) \
935 __assert_fail(#expr, __FILE__, __LINE__, __func__); \
936 } while (0)
937
938 int getInt();
939
940 int cond1;
941 int cond2;
942
bar()943 void bar() {
944 cond1 = getInt();
945 cond2 = getInt();
946 }
947
f(int flag)948 void f(int flag) {
949 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
950
951 flag = getInt();
952
953 bar();
954 assert(cond1 || cond2);
955 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
956 // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}}
957 // expected-note-re@-3{{{{^}}Taking false branch{{$}}}}
958 // expected-note-re@-4{{{{^}}Loop condition is false. Exiting loop{{$}}}}
959
960 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
961 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
962 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
963 *x = 5; // expected-warning{{Dereference of null pointer}}
964 // expected-note@-1{{Dereference of null pointer}}
965 }
966
967 #undef assert
968 } // end of namespace dont_track_assert2like_or_conditions
969
970 namespace only_track_the_evaluated_condition {
971
972 bool coin();
973
bar(int & flag)974 void bar(int &flag) {
975 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
976 }
977
bar2(int & flag2)978 void bar2(int &flag2) {
979 flag2 = coin();
980 }
981
f(int * x)982 void f(int *x) {
983 if (x) // expected-note-re{{{{^}}Assuming 'x' is null{{$}}}}
984 // debug-note-re@-1{{{{^}}Tracking condition 'x'{{$}}}}
985 // expected-note-re@-2{{{{^}}Taking false branch{{$}}}}
986 return;
987
988 int flag, flag2;
989 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}}
990 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}}
991 bar2(flag2);
992
993 if (flag && flag2) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}}
994 // expected-note-re@-1{{{{^}}Left side of '&&' is false{{$}}}}
995 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
996 return;
997
998 *x = 5; // expected-warning{{Dereference of null pointer}}
999 // expected-note@-1{{Dereference of null pointer}}
1000 }
1001
1002 } // end of namespace only_track_the_evaluated_condition
1003