// 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); }