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