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