41 lines
1.2 KiB
C++
41 lines
1.2 KiB
C++
|
// 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);
|
||
|
}
|