| // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s |
| |
| class A { |
| public: |
| int method(); |
| }; |
| |
| A *foo(); |
| void bar(A *); |
| |
| int index; |
| |
| // We want to check here that the notes about the origins of the null pointer |
| // (array[index] = foo()) will get to the final report. |
| // |
| // The analyzer used to drop exploded nodes for array subscripts when it was |
| // time to collect redundant nodes. This GC-like mechanism kicks in only when |
| // the exploded graph is large enough (>1K nodes). For this reason, 'index' |
| // is a global variable, and the sink point is inside of a loop. |
| |
| void test() { |
| A *array[42]; |
| A *found; |
| |
| for (index = 0; (array[index] = foo()); ++index) { // expected-note {{Loop condition is false. Execution continues on line 34}} |
| // expected-note@-1 {{Value assigned to 'index'}} |
| // expected-note@-2 {{Assigning value}} |
| // expected-note@-3 {{Assuming pointer value is null}} |
| if (array[0]) |
| break; |
| } |
| |
| do { |
| found = array[index]; // expected-note {{Null pointer value stored to 'found'}} |
| |
| if (found->method()) // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} |
| // expected-note@-1 {{Called C++ object pointer is null}} |
| bar(found); |
| } while (--index); |
| } |