1 // RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s 2 3 class A { 4 public: 5 int method(); 6 }; 7 8 A *foo(); 9 void bar(A *); 10 11 int index; 12 13 // We want to check here that the notes about the origins of the null pointer 14 // (array[index] = foo()) will get to the final report. 15 // 16 // The analyzer used to drop exploded nodes for array subscripts when it was 17 // time to collect redundant nodes. This GC-like mechanism kicks in only when 18 // the exploded graph is large enough (>1K nodes). For this reason, 'index' 19 // is a global variable, and the sink point is inside of a loop. 20 21 void test() { 22 A *array[42]; 23 A *found; 24 25 for (index = 0; (array[index] = foo()); ++index) { // expected-note {{Loop condition is false. Execution continues on line 34}} 26 // expected-note@-1 {{Value assigned to 'index'}} 27 // expected-note@-2 {{Assigning value}} 28 // expected-note@-3 {{Assuming pointer value is null}} 29 if (array[0]) 30 break; 31 } 32 33 do { 34 found = array[index]; // expected-note {{Null pointer value stored to 'found'}} 35 36 if (found->method()) // expected-warning {{Called C++ object pointer is null [core.CallAndMessage]}} 37 // expected-note@-1 {{Called C++ object pointer is null}} 38 bar(found); 39 } while (--index); 40 } 41