1 // RUN: %clang_analyze_cc1 %s -std=c++17 \
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++17 -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++17 \
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++17 -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 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}}
153 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}}
154 *x = 5; // expected-warning{{Dereference of null pointer}}
155 // expected-note@-1{{Dereference of null pointer}}
156 }
157
158 } // namespace conversion_to_bool
159
160 namespace note_from_different_but_not_nested_stackframe {
161
nullptrDeref(int * ptr,bool True)162 void nullptrDeref(int *ptr, bool True) {
163 if (True) // expected-note-re{{{{^}}'True' is true{{$}}}}
164 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
165 // debug-note-re@-2{{{{^}}Tracking condition 'True'{{$}}}}
166 *ptr = 5;
167 // expected-note@-1{{Dereference of null pointer (loaded from variable 'ptr')}}
168 // expected-warning@-2{{Dereference of null pointer (loaded from variable 'ptr')}}
169 }
170
f()171 void f() {
172 int *ptr = nullptr;
173 // expected-note-re@-1{{{{^}}'ptr' initialized to a null pointer value{{$}}}}
174 bool True = true;
175 nullptrDeref(ptr, True);
176 // expected-note-re@-1{{{{^}}Passing null pointer value via 1st parameter 'ptr'{{$}}}}
177 // expected-note-re@-2{{{{^}}Calling 'nullptrDeref'{{$}}}}
178 }
179
180 } // end of namespace note_from_different_but_not_nested_stackframe
181
182 namespace important_returning_pointer_loaded_from {
183 bool coin();
184
185 int *getIntPtr();
186
storeValue(int ** i)187 void storeValue(int **i) {
188 *i = getIntPtr();
189 }
190
conjurePointer()191 int *conjurePointer() {
192 int *i;
193 storeValue(&i);
194 return i;
195 }
196
f(int * ptr)197 void f(int *ptr) {
198 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
199 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
200 ;
201 if (!conjurePointer())
202 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}}
203 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}}
204 *ptr = 5; // expected-warning{{Dereference of null pointer}}
205 // expected-note@-1{{Dereference of null pointer}}
206 }
207 } // end of namespace important_returning_pointer_loaded_from
208
209 namespace unimportant_returning_pointer_loaded_from {
210 bool coin();
211
212 int *getIntPtr();
213
conjurePointer()214 int *conjurePointer() {
215 int *i = getIntPtr();
216 return i;
217 }
218
f(int * ptr)219 void f(int *ptr) {
220 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
221 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
222 ;
223 if (!conjurePointer())
224 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}}
225 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}}
226 *ptr = 5; // expected-warning{{Dereference of null pointer}}
227 // expected-note@-1{{Dereference of null pointer}}
228 }
229 } // end of namespace unimportant_returning_pointer_loaded_from
230
231 namespace unimportant_returning_pointer_loaded_from_through_cast {
232
233 void *conjure();
234
cast(void * P)235 int *cast(void *P) {
236 return static_cast<int *>(P);
237 }
238
f()239 void f() {
240 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
241
242 if (cast(conjure()))
243 // expected-note-re@-1{{{{^}}Assuming the condition is false{{$}}}}
244 // expected-note-re@-2{{{{^}}Taking false branch{{$}}}}
245 return;
246 *x = 5; // expected-warning{{Dereference of null pointer}}
247 // expected-note@-1{{Dereference of null pointer}}
248 }
249
250 } // end of namespace unimportant_returning_pointer_loaded_from_through_cast
251
252 namespace unimportant_returning_value_note {
253 bool coin();
254
flipCoin()255 bool flipCoin() { return coin(); }
256
i(int * ptr)257 void i(int *ptr) {
258 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
259 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
260 ;
261 if (!flipCoin())
262 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}}
263 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}}
264 *ptr = 5; // expected-warning{{Dereference of null pointer}}
265 // expected-note@-1{{Dereference of null pointer}}
266 }
267 } // end of namespace unimportant_returning_value_note
268
269 namespace important_returning_value_note {
270 bool coin();
271
flipCoin()272 bool flipCoin() {
273 if (coin())
274 return true;
275 return coin();
276 }
277
i(int * ptr)278 void i(int *ptr) {
279 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
280 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
281 ;
282 if (!flipCoin())
283 // expected-note-re@-1{{{{^}}Assuming the condition is true{{$}}}}
284 // expected-note-re@-2{{{{^}}Taking true branch{{$}}}}
285 *ptr = 5; // expected-warning{{Dereference of null pointer}}
286 // expected-note@-1{{Dereference of null pointer}}
287 }
288 } // end of namespace important_returning_value_note
289
290 namespace important_returning_value_note_in_linear_function {
291 bool coin();
292 int flag;
293
294 struct super_complicated_template_hackery {
295 static constexpr bool value = false;
296 };
297
flipCoin()298 void flipCoin() {
299 if (super_complicated_template_hackery::value)
300 // tracking-note-re@-1{{{{^}}'value' is false{{$}}}}
301 // tracking-note-re@-2{{{{^}}Taking false branch{{$}}}}
302 return;
303 flag = false; // tracking-note-re{{{{^}}The value 0 is assigned to 'flag', which participates in a condition later{{$}}}}
304 }
305
i(int * ptr)306 void i(int *ptr) {
307 flag = true;
308 if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}}
309 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
310 ;
311 flipCoin();
312 // tracking-note-re@-1{{{{^}}Calling 'flipCoin'{{$}}}}
313 // tracking-note-re@-2{{{{^}}Returning from 'flipCoin'{{$}}}}
314 if (!flag)
315 // debug-note-re@-1{{{{^}}Tracking condition '!flag'{{$}}}}
316 // expected-note-re@-2{{{{^}}'flag' is 0{{$}}}}
317 // expected-note-re@-3{{{{^}}Taking true branch{{$}}}}
318 *ptr = 5; // expected-warning{{Dereference of null pointer}}
319 // expected-note@-1{{Dereference of null pointer}}
320 }
321 } // end of namespace important_returning_value_note_in_linear_function
322
323 namespace tracked_condition_is_only_initialized {
324 int getInt();
325
f()326 void f() {
327 int flag = getInt();
328 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
329 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
330 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
331 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
332 *x = 5; // expected-warning{{Dereference of null pointer}}
333 // expected-note@-1{{Dereference of null pointer}}
334 }
335 } // end of namespace tracked_condition_is_only_initialized
336
337 namespace tracked_condition_written_in_same_stackframe {
338 int flag;
339 int getInt();
340
f(int y)341 void f(int y) {
342 y = 1;
343 flag = y;
344
345 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
346 if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}}
347 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
348 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
349 *x = 5; // expected-warning{{Dereference of null pointer}}
350 // expected-note@-1{{Dereference of null pointer}}
351 }
352 } // end of namespace tracked_condition_written_in_same_stackframe
353
354 namespace tracked_condition_written_in_nested_stackframe {
355 int flag;
356 int getInt();
357
foo()358 void foo() {
359 int y;
360 y = 1;
361 flag = y; // tracking-note-re{{{{^}}The value 1 is assigned to 'flag', which participates in a condition later{{$}}}}
362 }
363
f(int y)364 void f(int y) {
365 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
366
367 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
368 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
369
370 if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}}
371 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
372 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
373 *x = 5; // expected-warning{{Dereference of null pointer}}
374 // expected-note@-1{{Dereference of null pointer}}
375 }
376 } // end of namespace tracked_condition_written_in_nested_stackframe
377
378 namespace condition_written_in_nested_stackframe_before_assignment {
379 int flag = 0;
380 int getInt();
381
foo()382 void foo() {
383 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
384 }
385
f()386 void f() {
387 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
388 int y = 0;
389
390 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
391 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
392 y = flag;
393
394 if (y) // expected-note-re{{{{^}}Assuming 'y' is not equal to 0{{$}}}}
395 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
396 // debug-note-re@-2{{{{^}}Tracking condition 'y'{{$}}}}
397 *x = 5; // expected-warning{{Dereference of null pointer}}
398 // expected-note@-1{{Dereference of null pointer}}
399 }
400 } // end of namespace condition_written_in_nested_stackframe_before_assignment
401
402 namespace dont_explain_foreach_loops {
403
404 struct Iterator {
405 int *pos;
operator !=dont_explain_foreach_loops::Iterator406 bool operator!=(Iterator other) const {
407 return pos && other.pos && pos != other.pos;
408 }
409 int operator*();
410 Iterator operator++();
411 };
412
413 struct Container {
414 Iterator begin();
415 Iterator end();
416 };
417
f(Container Cont)418 void f(Container Cont) {
419 int flag = 0;
420 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
421 for (int i : Cont)
422 if (i) // expected-note-re {{{{^}}Assuming 'i' is not equal to 0{{$}}}}
423 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
424 // debug-note-re@-2{{{{^}}Tracking condition 'i'{{$}}}}
425 flag = i;
426
427 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
428 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
429 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
430 *x = 5; // expected-warning{{Dereference of null pointer}}
431 // expected-note@-1{{Dereference of null pointer}}
432 }
433 } // end of namespace dont_explain_foreach_loops
434
435 namespace condition_lambda_capture_by_reference_last_write {
436 int getInt();
437
438 [[noreturn]] void halt();
439
f(int flag)440 void f(int flag) {
441 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
442
443 auto lambda = [&flag]() {
444 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
445 };
446
447 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}}
448 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}}
449
450 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
451 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
452 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
453 *x = 5; // expected-warning{{Dereference of null pointer}}
454 // expected-note@-1{{Dereference of null pointer}}
455 }
456 } // end of namespace condition_lambda_capture_by_reference_last_write
457
458 namespace condition_lambda_capture_by_value_assumption {
459 int getInt();
460
461 [[noreturn]] void halt();
462
bar(int & flag)463 void bar(int &flag) {
464 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
465 }
466
f(int flag)467 void f(int flag) {
468 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
469
470 auto lambda = [flag]() {
471 if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}}
472 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
473 halt();
474 };
475
476 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}}
477 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}}
478 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}}
479 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}}
480
481 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
482 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
483 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
484 *x = 5; // expected-warning{{Dereference of null pointer}}
485 // expected-note@-1{{Dereference of null pointer}}
486 }
487 } // end of namespace condition_lambda_capture_by_value_assumption
488
489 namespace condition_lambda_capture_by_reference_assumption {
490 int getInt();
491
492 [[noreturn]] void halt();
493
bar(int & flag)494 void bar(int &flag) {
495 flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
496 }
497
f(int flag)498 void f(int flag) {
499 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
500
501 auto lambda = [&flag]() {
502 if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}}
503 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
504 halt();
505 };
506
507 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}}
508 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}}
509 lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}}
510 // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}}
511
512 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
513 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
514 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
515 *x = 5; // expected-warning{{Dereference of null pointer}}
516 // expected-note@-1{{Dereference of null pointer}}
517 }
518 } // end of namespace condition_lambda_capture_by_reference_assumption
519
520 namespace collapse_point_not_in_condition_bool {
521
522 [[noreturn]] void halt();
523
check(bool b)524 void check(bool b) {
525 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is true, which participates in a condition later{{$}}}}
526 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
527 halt();
528 }
529
f(bool flag)530 void f(bool flag) {
531 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
532
533 check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}}
534 // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}}
535
536 if (flag) // expected-note-re{{{{^}}'flag' is true{{$}}}}
537 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
538 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
539 *x = 5; // expected-warning{{Dereference of null pointer}}
540 // expected-note@-1{{Dereference of null pointer}}
541 }
542 } // end of namespace collapse_point_not_in_condition_bool
543
544 namespace collapse_point_not_in_condition {
545
546 [[noreturn]] void halt();
547
assert(int b)548 void assert(int b) {
549 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}}
550 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
551 halt();
552 }
553
f(int flag)554 void f(int flag) {
555 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
556
557 assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}}
558 // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}}
559
560 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
561 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
562 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
563 *x = 5; // expected-warning{{Dereference of null pointer}}
564 // expected-note@-1{{Dereference of null pointer}}
565 }
566
567 } // end of namespace collapse_point_not_in_condition
568
569 namespace unimportant_write_before_collapse_point {
570
571 [[noreturn]] void halt();
572
assert(int b)573 void assert(int b) {
574 if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}}
575 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
576 halt();
577 }
578 int getInt();
579
f(int flag)580 void f(int flag) {
581 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
582
583 flag = getInt();
584 assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}}
585 // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}}
586
587 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
588 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
589 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
590 *x = 5; // expected-warning{{Dereference of null pointer}}
591 // expected-note@-1{{Dereference of null pointer}}
592 }
593
594 } // end of namespace unimportant_write_before_collapse_point
595
596 namespace dont_crash_on_nonlogical_binary_operator {
597
f6(int x)598 void f6(int x) {
599 int a[20];
600 if (x == 25) {} // expected-note{{Assuming 'x' is equal to 25}}
601 // expected-note@-1{{Taking true branch}}
602 if (a[x] == 123) {} // expected-warning{{The left operand of '==' is a garbage value due to array index out of bounds}}
603 // expected-note@-1{{The left operand of '==' is a garbage value due to array index out of bounds}}
604 }
605
606 } // end of namespace dont_crash_on_nonlogical_binary_operator
607
608 namespace collapse_point_not_in_condition_binary_op {
609
610 [[noreturn]] void halt();
611
check(int b)612 void check(int b) {
613 if (b == 1) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 1, which participates in a condition later{{$}}}}
614 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
615 halt();
616 }
617
f(int flag)618 void f(int flag) {
619 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
620
621 check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}}
622 // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}}
623
624 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
625 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
626 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
627 *x = 5; // expected-warning{{Dereference of null pointer}}
628 // expected-note@-1{{Dereference of null pointer}}
629 }
630
631 } // end of namespace collapse_point_not_in_condition_binary_op
632
633 namespace collapse_point_not_in_condition_as_field {
634
635 [[noreturn]] void halt();
636 struct IntWrapper {
637 int b;
638 IntWrapper();
639
checkcollapse_point_not_in_condition_as_field::IntWrapper640 void check() {
641 if (!b) // tracking-note-re{{{{^}}Assuming field 'b' is not equal to 0, which participates in a condition later{{$}}}}
642 // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}}
643 halt();
644 return;
645 }
646 };
647
f(IntWrapper i)648 void f(IntWrapper i) {
649 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
650
651 i.check(); // tracking-note-re{{{{^}}Calling 'IntWrapper::check'{{$}}}}
652 // tracking-note-re@-1{{{{^}}Returning from 'IntWrapper::check'{{$}}}}
653 if (i.b) // expected-note-re{{{{^}}Field 'b' is not equal to 0{{$}}}}
654 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
655 // debug-note-re@-2{{{{^}}Tracking condition 'i.b'{{$}}}}
656 *x = 5; // expected-warning{{Dereference of null pointer}}
657 // expected-note@-1{{Dereference of null pointer}}
658 }
659
660 } // end of namespace collapse_point_not_in_condition_as_field
661
662 namespace assignemnt_in_condition_in_nested_stackframe {
663 int flag;
664
665 bool coin();
666
667 [[noreturn]] void halt();
668
foo()669 void foo() {
670 if ((flag = coin()))
671 // tracking-note-re@-1{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
672 // tracking-note-re@-2{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}}
673 // tracking-note-re@-3{{{{^}}Taking true branch{{$}}}}
674 return;
675 halt();
676 return;
677 }
678
f()679 void f() {
680 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
681
682 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
683 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
684 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
685 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
686 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
687 *x = 5; // expected-warning{{Dereference of null pointer}}
688 // expected-note@-1{{Dereference of null pointer}}
689 }
690 } // end of namespace assignemnt_in_condition_in_nested_stackframe
691
692 namespace condition_variable_less {
693 int flag;
694
695 bool coin();
696
697 [[noreturn]] void halt();
698
foo()699 void foo() {
700 if (flag > 0)
701 // tracking-note-re@-1{{{{^}}Assuming 'flag' is > 0, which participates in a condition later{{$}}}}
702 // tracking-note-re@-2{{{{^}}Taking true branch{{$}}}}
703 return;
704 halt();
705 return;
706 }
707
f()708 void f() {
709 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
710
711 foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}}
712 // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}}
713 if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}}
714 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
715 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
716 *x = 5; // expected-warning{{Dereference of null pointer}}
717 // expected-note@-1{{Dereference of null pointer}}
718 }
719 } // end of namespace condition_variable_less
720
721 namespace dont_track_assertlike_conditions {
722
723 extern void __assert_fail(__const char *__assertion, __const char *__file,
724 unsigned int __line, __const char *__function)
725 __attribute__((__noreturn__));
726 #define assert(expr) \
727 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__))
728
729 int getInt();
730
731 int cond1;
732
bar()733 void bar() {
734 cond1 = getInt();
735 }
736
f(int flag)737 void f(int flag) {
738 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
739
740 flag = getInt();
741
742 bar();
743 assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
744 // expected-note-re@-1{{{{^}}'?' condition is true{{$}}}}
745
746 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
747 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
748 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
749 *x = 5; // expected-warning{{Dereference of null pointer}}
750 // expected-note@-1{{Dereference of null pointer}}
751 }
752
753 #undef assert
754 } // end of namespace dont_track_assertlike_conditions
755
756 namespace dont_track_assertlike_and_conditions {
757
758 extern void __assert_fail(__const char *__assertion, __const char *__file,
759 unsigned int __line, __const char *__function)
760 __attribute__((__noreturn__));
761 #define assert(expr) \
762 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__))
763
764 int getInt();
765
766 int cond1;
767 int cond2;
768
bar()769 void bar() {
770 cond1 = getInt();
771 cond2 = getInt();
772 }
773
f(int flag)774 void f(int flag) {
775 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
776
777 flag = getInt();
778
779 bar();
780 assert(cond1 && cond2);
781 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
782 // expected-note-re@-2{{{{^}}Assuming 'cond2' is not equal to 0{{$}}}}
783 // expected-note-re@-3{{{{^}}'?' condition is true{{$}}}}
784 // expected-note-re@-4{{{{^}}Left side of '&&' is true{{$}}}}
785
786 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
787 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
788 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
789 *x = 5; // expected-warning{{Dereference of null pointer}}
790 // expected-note@-1{{Dereference of null pointer}}
791 }
792
793 #undef assert
794 } // end of namespace dont_track_assertlike_and_conditions
795
796 namespace dont_track_assertlike_or_conditions {
797
798 extern void __assert_fail(__const char *__assertion, __const char *__file,
799 unsigned int __line, __const char *__function)
800 __attribute__((__noreturn__));
801 #define assert(expr) \
802 ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__))
803
804 int getInt();
805
806 int cond1;
807 int cond2;
808
bar()809 void bar() {
810 cond1 = getInt();
811 cond2 = getInt();
812 }
813
f(int flag)814 void f(int flag) {
815 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
816
817 flag = getInt();
818
819 bar();
820 assert(cond1 || cond2);
821 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
822 // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}}
823
824 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
825 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
826 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
827 *x = 5; // expected-warning{{Dereference of null pointer}}
828 // expected-note@-1{{Dereference of null pointer}}
829 }
830
831 #undef assert
832 } // end of namespace dont_track_assertlike_or_conditions
833
834 namespace dont_track_assert2like_conditions {
835
836 extern void __assert_fail(__const char *__assertion, __const char *__file,
837 unsigned int __line, __const char *__function)
838 __attribute__((__noreturn__));
839 #define assert(expr) \
840 do { \
841 if (!(expr)) \
842 __assert_fail(#expr, __FILE__, __LINE__, __func__); \
843 } while (0)
844
845 int getInt();
846
847 int cond1;
848
bar()849 void bar() {
850 cond1 = getInt();
851 }
852
f(int flag)853 void f(int flag) {
854 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
855
856 flag = getInt();
857
858 bar();
859 assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
860 // expected-note-re@-1{{{{^}}Taking false branch{{$}}}}
861 // expected-note-re@-2{{{{^}}Loop condition is false. Exiting loop{{$}}}}
862
863 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
864 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
865 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
866 *x = 5; // expected-warning{{Dereference of null pointer}}
867 // expected-note@-1{{Dereference of null pointer}}
868 }
869
870 #undef assert
871 } // end of namespace dont_track_assert2like_conditions
872
873 namespace dont_track_assert2like_and_conditions {
874
875 extern void __assert_fail(__const char *__assertion, __const char *__file,
876 unsigned int __line, __const char *__function)
877 __attribute__((__noreturn__));
878 #define assert(expr) \
879 do { \
880 if (!(expr)) \
881 __assert_fail(#expr, __FILE__, __LINE__, __func__); \
882 } while (0)
883
884 int getInt();
885
886 int cond1;
887 int cond2;
888
bar()889 void bar() {
890 cond1 = getInt();
891 cond2 = getInt();
892 }
893
f(int flag)894 void f(int flag) {
895 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
896
897 flag = getInt();
898
899 bar();
900 assert(cond1 && cond2);
901 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
902 // expected-note-re@-2{{{{^}}Left side of '&&' is true{{$}}}}
903 // expected-note-re@-3{{{{^}}Assuming the condition is false{{$}}}}
904 // expected-note-re@-4{{{{^}}Taking false branch{{$}}}}
905 // expected-note-re@-5{{{{^}}Loop condition is false. Exiting loop{{$}}}}
906
907 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
908 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
909 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
910 *x = 5; // expected-warning{{Dereference of null pointer}}
911 // expected-note@-1{{Dereference of null pointer}}
912 }
913
914 #undef assert
915 } // end of namespace dont_track_assert2like_and_conditions
916
917 namespace dont_track_assert2like_or_conditions {
918
919 extern void __assert_fail(__const char *__assertion, __const char *__file,
920 unsigned int __line, __const char *__function)
921 __attribute__((__noreturn__));
922 #define assert(expr) \
923 do { \
924 if (!(expr)) \
925 __assert_fail(#expr, __FILE__, __LINE__, __func__); \
926 } while (0)
927
928 int getInt();
929
930 int cond1;
931 int cond2;
932
bar()933 void bar() {
934 cond1 = getInt();
935 cond2 = getInt();
936 }
937
f(int flag)938 void f(int flag) {
939 int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}}
940
941 flag = getInt();
942
943 bar();
944 assert(cond1 || cond2);
945 // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}}
946 // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}}
947 // expected-note-re@-3{{{{^}}Taking false branch{{$}}}}
948 // expected-note-re@-4{{{{^}}Loop condition is false. Exiting loop{{$}}}}
949
950 if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}}
951 // expected-note-re@-1{{{{^}}Taking true branch{{$}}}}
952 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
953 *x = 5; // expected-warning{{Dereference of null pointer}}
954 // expected-note@-1{{Dereference of null pointer}}
955 }
956
957 #undef assert
958 } // end of namespace dont_track_assert2like_or_conditions
959
960 namespace only_track_the_evaluated_condition {
961
962 bool coin();
963
bar(int & flag)964 void bar(int &flag) {
965 flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}}
966 }
967
bar2(int & flag2)968 void bar2(int &flag2) {
969 flag2 = coin();
970 }
971
f(int * x)972 void f(int *x) {
973 if (x) // expected-note-re{{{{^}}Assuming 'x' is null{{$}}}}
974 // debug-note-re@-1{{{{^}}Tracking condition 'x'{{$}}}}
975 // expected-note-re@-2{{{{^}}Taking false branch{{$}}}}
976 return;
977
978 int flag, flag2;
979 bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}}
980 // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}}
981 bar2(flag2);
982
983 if (flag && flag2) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}}
984 // expected-note-re@-1{{{{^}}Left side of '&&' is false{{$}}}}
985 // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}}
986 return;
987
988 *x = 5; // expected-warning{{Dereference of null pointer}}
989 // expected-note@-1{{Dereference of null pointer}}
990 }
991
992 } // end of namespace only_track_the_evaluated_condition
993
994 namespace operator_call_in_condition_point {
995
996 struct Error {
operator booloperator_call_in_condition_point::Error997 explicit operator bool() {
998 return true;
999 }
1000 };
1001
1002 Error couldFail();
1003
f(int * x)1004 void f(int *x) {
1005 x = nullptr; // expected-note {{Null pointer value stored to 'x'}}
1006 if (auto e = couldFail()) // expected-note {{Taking true branch}}
1007 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}}
1008 // expected-note@-1 {{Dereference}}
1009 }
1010
1011 } // namespace operator_call_in_condition_point
1012
1013 namespace cxx17_ifinit__operator_call_in_condition_point {
1014
1015 struct Error {
operator boolcxx17_ifinit__operator_call_in_condition_point::Error1016 explicit operator bool() {
1017 return true;
1018 }
1019 };
1020
1021 Error couldFail();
1022
f(int * x)1023 void f(int *x) {
1024 x = nullptr; // expected-note {{Null pointer value stored to 'x'}}
1025 if (auto e = couldFail(); e) // expected-note {{Taking true branch}}
1026 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}}
1027 // expected-note@-1 {{Dereference}}
1028 }
1029
1030 } // namespace cxx17_ifinit__operator_call_in_condition_point
1031
1032 namespace funcion_call_in_condition_point {
1033
alwaysTrue()1034 int alwaysTrue() {
1035 return true;
1036 }
1037
f(int * x)1038 void f(int *x) {
1039 x = nullptr; // expected-note {{Null pointer value stored to 'x'}}
1040 if (alwaysTrue()) // expected-note {{Taking true branch}}
1041 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}}
1042 // expected-note@-1 {{Dereference}}
1043 }
1044
1045 } // namespace funcion_call_in_condition_point
1046
1047 namespace funcion_call_negated_in_condition_point {
1048
alwaysFalse()1049 int alwaysFalse() {
1050 return false;
1051 }
1052
f(int * x)1053 void f(int *x) {
1054 x = nullptr; // expected-note {{Null pointer value stored to 'x'}}
1055 if (!alwaysFalse()) // expected-note {{Taking true branch}}
1056 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}}
1057 // expected-note@-1 {{Dereference}}
1058 }
1059
1060 } // namespace funcion_call_negated_in_condition_point
1061
1062 namespace funcion_call_part_of_logical_expr_in_condition_point {
1063
alwaysFalse()1064 int alwaysFalse() {
1065 return false;
1066 }
1067
f(int * x)1068 void f(int *x) {
1069 x = nullptr; // expected-note {{Null pointer value stored to 'x'}}
1070 if (!alwaysFalse() && true) // expected-note {{Taking true branch}}
1071 // expected-note@-1 {{Left side of '&&' is true}}
1072 *x = 5; // expected-warning {{Dereference of null pointer (loaded from variable 'x') [core.NullDereference]}}
1073 // expected-note@-1 {{Dereference}}
1074 }
1075
1076 } // namespace funcion_call_part_of_logical_expr_in_condition_point
1077