| // RUN: %clang_analyze_cc1 %s -std=c++14 \ |
| // RUN: -verify=expected,tracking \ |
| // RUN: -analyzer-config track-conditions=true \ |
| // RUN: -analyzer-output=text \ |
| // RUN: -analyzer-checker=core |
| |
| // RUN: not %clang_analyze_cc1 -std=c++14 -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 -std=c++14 \ |
| // 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 -std=c++14 -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<int *>(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 |