vsavchenko created this revision. vsavchenko added reviewers: NoQ, dcoughlin. Herald added subscribers: cfe-commits, ASDenysPetrov, martong, Charusso, dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun. Herald added a project: clang.
Static analyzer has a mechanism of clearing redundant nodes when analysis hits a certain threshold with a number of nodes in exploded graph (default is 1000). It is similar to GC and aims removing nodes not useful for analysis. Unfortunately nodes corresponding to array subscript expressions (that actively participate in data propagation) get removed during the cleanup. This might prevent the analyzer from generating useful notes about where it thinks the data came from. This fix is pretty much consistent with the way analysis works already. Lvalue "interestingness" stands for the analyzer's possibility of tracking values through them. rdar://problem/53280338 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D78638 Files: clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp clang/test/Analysis/PR53280338.cpp Index: clang/test/Analysis/PR53280338.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/PR53280338.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s + +class A { +public: + int method(); +}; + +A *foo(); +void bar(A *); + +int index; + +void test() { + A *array[42]; + A *found; + + for (index = 0; (array[index] = foo()); ++index) { // expected-note {{Loop condition is false. Execution continues on line 26}} + // 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); +} Index: clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp +++ clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp @@ -50,9 +50,8 @@ bool ExplodedGraph::isInterestingLValueExpr(const Expr *Ex) { if (!Ex->isLValue()) return false; - return isa<DeclRefExpr>(Ex) || - isa<MemberExpr>(Ex) || - isa<ObjCIvarRefExpr>(Ex); + return isa<DeclRefExpr>(Ex) || isa<MemberExpr>(Ex) || + isa<ObjCIvarRefExpr>(Ex) || isa<ArraySubscriptExpr>(Ex); } bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
Index: clang/test/Analysis/PR53280338.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/PR53280338.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=text -verify %s + +class A { +public: + int method(); +}; + +A *foo(); +void bar(A *); + +int index; + +void test() { + A *array[42]; + A *found; + + for (index = 0; (array[index] = foo()); ++index) { // expected-note {{Loop condition is false. Execution continues on line 26}} + // 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); +} Index: clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp +++ clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp @@ -50,9 +50,8 @@ bool ExplodedGraph::isInterestingLValueExpr(const Expr *Ex) { if (!Ex->isLValue()) return false; - return isa<DeclRefExpr>(Ex) || - isa<MemberExpr>(Ex) || - isa<ObjCIvarRefExpr>(Ex); + return isa<DeclRefExpr>(Ex) || isa<MemberExpr>(Ex) || + isa<ObjCIvarRefExpr>(Ex) || isa<ArraySubscriptExpr>(Ex); } bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits