// RUN: %clang_analyze_cc1 %s \ // RUN: -verify=expected,tracking \ // RUN: -analyzer-config track-conditions=true \ // RUN: -analyzer-output=text \ // RUN: -analyzer-checker=core // RUN: not %clang_analyze_cc1 -verify %s \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-config track-conditions=false \ // RUN: -analyzer-config track-conditions-debug=true \ // RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-DEBUG // CHECK-INVALID-DEBUG: (frontend): invalid input for analyzer-config option // CHECK-INVALID-DEBUG-SAME: 'track-conditions-debug', that expects // CHECK-INVALID-DEBUG-SAME: 'track-conditions' to also be enabled // // RUN: %clang_analyze_cc1 %s \ // RUN: -verify=expected,tracking,debug \ // RUN: -analyzer-config track-conditions=true \ // RUN: -analyzer-config track-conditions-debug=true \ // RUN: -analyzer-output=text \ // RUN: -analyzer-checker=core // RUN: %clang_analyze_cc1 %s -verify \ // RUN: -analyzer-output=text \ // RUN: -analyzer-config track-conditions=false \ // RUN: -analyzer-checker=core namespace example_1 { int flag; bool coin(); void foo() { flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} } void test() { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} flag = 1; foo(); // TODO: Add nodes here about flag's value being invalidated. if (flag) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}} // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} x = new int; foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} if (flag) // expected-note-re {{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace example_1 namespace example_2 { int flag; bool coin(); void foo() { flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} } void test() { int *x = 0; flag = 1; foo(); if (flag) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}} // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} x = new int; x = 0; // expected-note-re{{{{^}}Null pointer value stored to 'x'{{$}}}} foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} if (flag) // expected-note-re {{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace example_2 namespace global_variable_invalidation { int flag; bool coin(); void foo() { // coin() could write bar, do it's invalidated. flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} // tracking-note-re@-1{{{{^}}Value assigned to 'bar', which participates in a condition later{{$}}}} } int bar; void test() { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} flag = 1; foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} if (bar) // expected-note-re {{{{^}}Assuming 'bar' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'bar'{{$}}}} if (flag) // expected-note-re {{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace global_variable_invalidation namespace variable_declaration_in_condition { bool coin(); bool foo() { return coin(); } int bar; void test() { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} if (int flag = foo()) // debug-note-re{{{{^}}Tracking condition 'flag'{{$}}}} // expected-note-re@-1{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-2{{{{^}}Taking true branch{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace variable_declaration_in_condition namespace conversion_to_bool { bool coin(); struct ConvertsToBool { operator bool() const { return coin(); } }; void test() { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} if (ConvertsToBool()) // debug-note-re@-1{{{{^}}Tracking condition 'ConvertsToBool()'{{$}}}} // expected-note-re@-2{{{{^}}Assuming the condition is true{{$}}}} // expected-note-re@-3{{{{^}}Taking true branch{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace variable_declaration_in_condition namespace note_from_different_but_not_nested_stackframe { void nullptrDeref(int *ptr, bool True) { if (True) // expected-note-re{{{{^}}'True' is true{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'True'{{$}}}} *ptr = 5; // expected-note@-1{{Dereference of null pointer (loaded from variable 'ptr')}} // expected-warning@-2{{Dereference of null pointer (loaded from variable 'ptr')}} } void f() { int *ptr = nullptr; // expected-note-re@-1{{{{^}}'ptr' initialized to a null pointer value{{$}}}} bool True = true; nullptrDeref(ptr, True); // expected-note-re@-1{{{{^}}Passing null pointer value via 1st parameter 'ptr'{{$}}}} // expected-note-re@-2{{{{^}}Calling 'nullptrDeref'{{$}}}} } } // end of namespace note_from_different_but_not_nested_stackframe namespace important_returning_pointer_loaded_from { bool coin(); int *getIntPtr(); void storeValue(int **i) { *i = getIntPtr(); // tracking-note-re{{{{^}}Value assigned to 'i', which participates in a condition later{{$}}}} } int *conjurePointer() { int *i; storeValue(&i); // tracking-note-re{{{{^}}Calling 'storeValue'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'storeValue'{{$}}}} return i; // tracking-note-re{{{{^}}Returning pointer (loaded from 'i'), which participates in a condition later{{$}}}} } void f(int *ptr) { if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} ; if (!conjurePointer()) // tracking-note-re@-1{{{{^}}Calling 'conjurePointer'{{$}}}} // tracking-note-re@-2{{{{^}}Returning from 'conjurePointer'{{$}}}} // debug-note-re@-3{{{{^}}Tracking condition '!conjurePointer()'{{$}}}} // expected-note-re@-4{{{{^}}Assuming the condition is true{{$}}}} // expected-note-re@-5{{{{^}}Taking true branch{{$}}}} *ptr = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace important_returning_pointer_loaded_from namespace unimportant_returning_pointer_loaded_from { bool coin(); int *getIntPtr(); int *conjurePointer() { int *i = getIntPtr(); return i; } void f(int *ptr) { if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} ; if (!conjurePointer()) // debug-note-re@-1{{{{^}}Tracking condition '!conjurePointer()'{{$}}}} // expected-note-re@-2{{{{^}}Assuming the condition is true{{$}}}} // expected-note-re@-3{{{{^}}Taking true branch{{$}}}} *ptr = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace unimportant_returning_pointer_loaded_from namespace unimportant_returning_pointer_loaded_from_through_cast { void *conjure(); int *cast(void *P) { return static_cast(P); } void f() { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} if (cast(conjure())) // debug-note-re@-1{{{{^}}Tracking condition 'cast(conjure())'{{$}}}} // expected-note-re@-2{{{{^}}Assuming the condition is false{{$}}}} // expected-note-re@-3{{{{^}}Taking false branch{{$}}}} return; *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace unimportant_returning_pointer_loaded_from_through_cast namespace unimportant_returning_value_note { bool coin(); bool flipCoin() { return coin(); } void i(int *ptr) { if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} ; if (!flipCoin()) // debug-note-re@-1{{{{^}}Tracking condition '!flipCoin()'{{$}}}} // expected-note-re@-2{{{{^}}Assuming the condition is true{{$}}}} // expected-note-re@-3{{{{^}}Taking true branch{{$}}}} *ptr = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace unimportant_returning_value_note namespace important_returning_value_note { bool coin(); bool flipCoin() { if (coin()) // tracking-note-re{{{{^}}Assuming the condition is false{{$}}}} // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'coin()'{{$}}}} return true; return coin(); // tracking-note-re{{{{^}}Returning value, which participates in a condition later{{$}}}} } void i(int *ptr) { if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} ; if (!flipCoin()) // tracking-note-re@-1{{{{^}}Calling 'flipCoin'{{$}}}} // tracking-note-re@-2{{{{^}}Returning from 'flipCoin'{{$}}}} // debug-note-re@-3{{{{^}}Tracking condition '!flipCoin()'{{$}}}} // expected-note-re@-4{{{{^}}Assuming the condition is true{{$}}}} // expected-note-re@-5{{{{^}}Taking true branch{{$}}}} *ptr = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace important_returning_value_note namespace important_returning_value_note_in_linear_function { bool coin(); struct super_complicated_template_hackery { static constexpr bool value = false; }; bool flipCoin() { if (super_complicated_template_hackery::value) // tracking-note-re@-1{{{{^}}'value' is false{{$}}}} // tracking-note-re@-2{{{{^}}Taking false branch{{$}}}} return true; return coin(); // tracking-note-re{{{{^}}Returning value, which participates in a condition later{{$}}}} } void i(int *ptr) { if (ptr) // expected-note-re{{{{^}}Assuming 'ptr' is null{{$}}}} // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} ; if (!flipCoin()) // tracking-note-re@-1{{{{^}}Calling 'flipCoin'{{$}}}} // tracking-note-re@-2{{{{^}}Returning from 'flipCoin'{{$}}}} // debug-note-re@-3{{{{^}}Tracking condition '!flipCoin()'{{$}}}} // expected-note-re@-4{{{{^}}Assuming the condition is true{{$}}}} // expected-note-re@-5{{{{^}}Taking true branch{{$}}}} *ptr = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace important_returning_value_note_in_linear_function namespace tracked_condition_is_only_initialized { int getInt(); void f() { int flag = getInt(); int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace tracked_condition_is_only_initialized namespace tracked_condition_written_in_same_stackframe { int flag; int getInt(); void f(int y) { y = 1; flag = y; int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace tracked_condition_written_in_same_stackframe namespace tracked_condition_written_in_nested_stackframe { int flag; int getInt(); void foo() { int y; y = 1; flag = y; // tracking-note-re{{{{^}}The value 1 is assigned to 'flag', which participates in a condition later{{$}}}} } void f(int y) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} if (flag) // expected-note-re{{{{^}}'flag' is 1{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace tracked_condition_written_in_nested_stackframe namespace condition_written_in_nested_stackframe_before_assignment { int flag = 0; int getInt(); void foo() { flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} } void f() { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} int y = 0; foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} y = flag; if (y) // expected-note-re{{{{^}}Assuming 'y' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'y'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace condition_written_in_nested_stackframe_before_assignment namespace dont_explain_foreach_loops { struct Iterator { int *pos; bool operator!=(Iterator other) const { return pos && other.pos && pos != other.pos; } int operator*(); Iterator operator++(); }; struct Container { Iterator begin(); Iterator end(); }; void f(Container Cont) { int flag = 0; int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} for (int i : Cont) if (i) // expected-note-re {{{{^}}Assuming 'i' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'i'{{$}}}} flag = i; if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace dont_explain_foreach_loops namespace condition_lambda_capture_by_reference_last_write { int getInt(); [[noreturn]] void halt(); void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} auto lambda = [&flag]() { flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} }; lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace condition_lambda_capture_by_reference_last_write namespace condition_lambda_capture_by_value_assumption { int getInt(); [[noreturn]] void halt(); void bar(int &flag) { flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} auto lambda = [flag]() { if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}} // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} halt(); }; bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}} lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace condition_lambda_capture_by_value_assumption namespace condition_lambda_capture_by_reference_assumption { int getInt(); [[noreturn]] void halt(); void bar(int &flag) { flag = getInt(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} auto lambda = [&flag]() { if (!flag) // tracking-note-re{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}} // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} halt(); }; bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}} lambda(); // tracking-note-re{{{{^}}Calling 'operator()'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'operator()'{{$}}}} if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace condition_lambda_capture_by_reference_assumption namespace collapse_point_not_in_condition_bool { [[noreturn]] void halt(); void check(bool b) { if (!b) // tracking-note-re{{{{^}}Assuming 'b' is true, which participates in a condition later{{$}}}} // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} halt(); } void f(bool flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}} if (flag) // expected-note-re{{{{^}}'flag' is true{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace collapse_point_not_in_condition_bool namespace collapse_point_not_in_condition { [[noreturn]] void halt(); void assert(int b) { if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}} // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} halt(); } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}} if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace collapse_point_not_in_condition namespace unimportant_write_before_collapse_point { [[noreturn]] void halt(); void assert(int b) { if (!b) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 0, which participates in a condition later{{$}}}} // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} halt(); } int getInt(); void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} flag = getInt(); assert(flag); // tracking-note-re{{{{^}}Calling 'assert'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'assert'{{$}}}} if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace unimportant_write_before_collapse_point namespace dont_crash_on_nonlogical_binary_operator { void f6(int x) { int a[20]; if (x == 25) {} // expected-note{{Assuming 'x' is equal to 25}} // expected-note@-1{{Taking true branch}} if (a[x] == 123) {} // expected-warning{{The left operand of '==' is a garbage value due to array index out of bounds}} // expected-note@-1{{The left operand of '==' is a garbage value due to array index out of bounds}} } } // end of namespace dont_crash_on_nonlogical_binary_operator namespace collapse_point_not_in_condition_binary_op { [[noreturn]] void halt(); void check(int b) { if (b == 1) // tracking-note-re{{{{^}}Assuming 'b' is not equal to 1, which participates in a condition later{{$}}}} // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} halt(); } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} check(flag); // tracking-note-re{{{{^}}Calling 'check'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'check'{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace collapse_point_not_in_condition_binary_op namespace collapse_point_not_in_condition_as_field { [[noreturn]] void halt(); struct IntWrapper { int b; IntWrapper(); void check() { if (!b) // tracking-note-re{{{{^}}Assuming field 'b' is not equal to 0, which participates in a condition later{{$}}}} // tracking-note-re@-1{{{{^}}Taking false branch{{$}}}} halt(); return; } }; void f(IntWrapper i) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} i.check(); // tracking-note-re{{{{^}}Calling 'IntWrapper::check'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'IntWrapper::check'{{$}}}} if (i.b) // expected-note-re{{{{^}}Field 'b' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'i.b'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace collapse_point_not_in_condition_as_field namespace assignemnt_in_condition_in_nested_stackframe { int flag; bool coin(); [[noreturn]] void halt(); void foo() { if ((flag = coin())) // tracking-note-re@-1{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} // tracking-note-re@-2{{{{^}}Assuming 'flag' is not equal to 0, which participates in a condition later{{$}}}} // tracking-note-re@-3{{{{^}}Taking true branch{{$}}}} return; halt(); return; } void f() { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace assignemnt_in_condition_in_nested_stackframe namespace condition_variable_less { int flag; bool coin(); [[noreturn]] void halt(); void foo() { if (flag > 0) // tracking-note-re@-1{{{{^}}Assuming 'flag' is > 0, which participates in a condition later{{$}}}} // tracking-note-re@-2{{{{^}}Taking true branch{{$}}}} return; halt(); return; } void f() { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} foo(); // tracking-note-re{{{{^}}Calling 'foo'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'foo'{{$}}}} if (flag) // expected-note-re{{{{^}}'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace condition_variable_less namespace dont_track_assertlike_conditions { extern void __assert_fail(__const char *__assertion, __const char *__file, unsigned int __line, __const char *__function) __attribute__((__noreturn__)); #define assert(expr) \ ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__)) int getInt(); int cond1; void bar() { cond1 = getInt(); } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} flag = getInt(); bar(); assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}'?' condition is true{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } #undef assert } // end of namespace dont_track_assertlike_conditions namespace dont_track_assertlike_and_conditions { extern void __assert_fail(__const char *__assertion, __const char *__file, unsigned int __line, __const char *__function) __attribute__((__noreturn__)); #define assert(expr) \ ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__)) int getInt(); int cond1; int cond2; void bar() { cond1 = getInt(); cond2 = getInt(); } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} flag = getInt(); bar(); assert(cond1 && cond2); // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} // expected-note-re@-2{{{{^}}Assuming 'cond2' is not equal to 0{{$}}}} // expected-note-re@-3{{{{^}}'?' condition is true{{$}}}} // expected-note-re@-4{{{{^}}Left side of '&&' is true{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } #undef assert } // end of namespace dont_track_assertlike_and_conditions namespace dont_track_assertlike_or_conditions { extern void __assert_fail(__const char *__assertion, __const char *__file, unsigned int __line, __const char *__function) __attribute__((__noreturn__)); #define assert(expr) \ ((expr) ? (void)(0) : __assert_fail(#expr, __FILE__, __LINE__, __func__)) int getInt(); int cond1; int cond2; void bar() { cond1 = getInt(); cond2 = getInt(); } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} flag = getInt(); bar(); assert(cond1 || cond2); // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } #undef assert } // end of namespace dont_track_assertlike_or_conditions namespace dont_track_assert2like_conditions { extern void __assert_fail(__const char *__assertion, __const char *__file, unsigned int __line, __const char *__function) __attribute__((__noreturn__)); #define assert(expr) \ do { \ if (!(expr)) \ __assert_fail(#expr, __FILE__, __LINE__, __func__); \ } while (0) int getInt(); int cond1; void bar() { cond1 = getInt(); } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} flag = getInt(); bar(); assert(cond1); // expected-note-re{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking false branch{{$}}}} // expected-note-re@-2{{{{^}}Loop condition is false. Exiting loop{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } #undef assert } // end of namespace dont_track_assert2like_conditions namespace dont_track_assert2like_and_conditions { extern void __assert_fail(__const char *__assertion, __const char *__file, unsigned int __line, __const char *__function) __attribute__((__noreturn__)); #define assert(expr) \ do { \ if (!(expr)) \ __assert_fail(#expr, __FILE__, __LINE__, __func__); \ } while (0) int getInt(); int cond1; int cond2; void bar() { cond1 = getInt(); cond2 = getInt(); } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} flag = getInt(); bar(); assert(cond1 && cond2); // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} // expected-note-re@-2{{{{^}}Left side of '&&' is true{{$}}}} // expected-note-re@-3{{{{^}}Assuming the condition is false{{$}}}} // expected-note-re@-4{{{{^}}Taking false branch{{$}}}} // expected-note-re@-5{{{{^}}Loop condition is false. Exiting loop{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } #undef assert } // end of namespace dont_track_assert2like_and_conditions namespace dont_track_assert2like_or_conditions { extern void __assert_fail(__const char *__assertion, __const char *__file, unsigned int __line, __const char *__function) __attribute__((__noreturn__)); #define assert(expr) \ do { \ if (!(expr)) \ __assert_fail(#expr, __FILE__, __LINE__, __func__); \ } while (0) int getInt(); int cond1; int cond2; void bar() { cond1 = getInt(); cond2 = getInt(); } void f(int flag) { int *x = 0; // expected-note-re{{{{^}}'x' initialized to a null pointer value{{$}}}} flag = getInt(); bar(); assert(cond1 || cond2); // expected-note-re@-1{{{{^}}Assuming 'cond1' is not equal to 0{{$}}}} // expected-note-re@-2{{{{^}}Left side of '||' is true{{$}}}} // expected-note-re@-3{{{{^}}Taking false branch{{$}}}} // expected-note-re@-4{{{{^}}Loop condition is false. Exiting loop{{$}}}} if (flag) // expected-note-re{{{{^}}Assuming 'flag' is not equal to 0{{$}}}} // expected-note-re@-1{{{{^}}Taking true branch{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } #undef assert } // end of namespace dont_track_assert2like_or_conditions namespace only_track_the_evaluated_condition { bool coin(); void bar(int &flag) { flag = coin(); // tracking-note-re{{{{^}}Value assigned to 'flag', which participates in a condition later{{$}}}} } void bar2(int &flag2) { flag2 = coin(); } void f(int *x) { if (x) // expected-note-re{{{{^}}Assuming 'x' is null{{$}}}} // debug-note-re@-1{{{{^}}Tracking condition 'x'{{$}}}} // expected-note-re@-2{{{{^}}Taking false branch{{$}}}} return; int flag, flag2; bar(flag); // tracking-note-re{{{{^}}Calling 'bar'{{$}}}} // tracking-note-re@-1{{{{^}}Returning from 'bar'{{$}}}} bar2(flag2); if (flag && flag2) // expected-note-re {{{{^}}Assuming 'flag' is 0{{$}}}} // expected-note-re@-1{{{{^}}Left side of '&&' is false{{$}}}} // debug-note-re@-2{{{{^}}Tracking condition 'flag'{{$}}}} return; *x = 5; // expected-warning{{Dereference of null pointer}} // expected-note@-1{{Dereference of null pointer}} } } // end of namespace only_track_the_evaluated_condition