diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-08-28 00:50:45 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-08-28 00:50:45 +0000 |
commit | 166b7bd43551964d65bcf4918f51a167b8374e2a (patch) | |
tree | acdb99b39e0a5b32e68bac47e00e0387d1a4808c | |
parent | 7aba1171b32265b2206f3fa8f8886953051b58f5 (diff) |
[analyzer] Refactor FindLastStoreBRVisitor to not find the store ahead of time.
As Anna pointed out to me offline, it's a little silly to walk backwards through
the graph to find the store site when BugReporter will do the exact same walk
as part of path diagnostic generation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162719 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 94 |
2 files changed, 40 insertions, 57 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index f53c15f117..1045c28c84 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -100,7 +100,6 @@ class FindLastStoreBRVisitor const MemRegion *R; SVal V; bool satisfied; - const ExplodedNode *StoreSite; public: /// \brief Convenience method to create a visitor given only the MemRegion. @@ -114,7 +113,7 @@ public: static void registerStatementVarDecls(BugReport &BR, const Stmt *S); FindLastStoreBRVisitor(SVal v, const MemRegion *r) - : R(r), V(v), satisfied(false), StoreSite(0) { + : R(r), V(v), satisfied(false) { assert (!V.isUnknown() && "Cannot track unknown value."); // TODO: Does it make sense to allow undef values here? diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index ae8ed00783..a2d05852e8 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -245,79 +245,63 @@ void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const { ID.Add(V); } -PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N, - const ExplodedNode *PrevN, - BugReporterContext &BRC, - BugReport &BR) { +PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, + const ExplodedNode *Pred, + BugReporterContext &BRC, + BugReport &BR) { if (satisfied) return NULL; - if (!StoreSite) { - // Make sure the region is actually bound to value V here. - // This is necessary because the region may not actually be live at the - // report's error node. - if (N->getState()->getSVal(R) != V) - return NULL; - - const ExplodedNode *Node = N, *Last = N; - const Expr *InitE = 0; - - // Now look for the store of V. - for ( ; Node ; Node = Node->getFirstPred()) { - if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { - if (const PostStmt *P = Node->getLocationAs<PostStmt>()) - if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) - if (DS->getSingleDecl() == VR->getDecl()) { - // Record the last seen initialization point. - Last = Node; - InitE = VR->getDecl()->getInit(); - break; - } - } + const ExplodedNode *StoreSite = 0; + const Expr *InitE = 0; - // Does the region still bind to value V? If not, we are done - // looking for store sites. - SVal Current = Node->getState()->getSVal(R); - if (Current != V) { - // If this is an assignment expression, we can track the value - // being assigned. - if (const StmtPoint *SP = Last->getLocationAs<StmtPoint>()) { - const Stmt *S = SP->getStmt(); - if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) - if (BO->isAssignmentOp()) - InitE = BO->getRHS(); + // First see if we reached the declaration of the region. + if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { + if (const PostStmt *P = Pred->getLocationAs<PostStmt>()) { + if (const DeclStmt *DS = P->getStmtAs<DeclStmt>()) { + if (DS->getSingleDecl() == VR->getDecl()) { + StoreSite = Pred; + InitE = VR->getDecl()->getInit(); } - - break; } - - Last = Node; } + } - if (!Node) { - satisfied = true; + // Otherwise, check that Succ has this binding and Pred does not, i.e. this is + // where the binding first occurred. + if (!StoreSite) { + if (Succ->getState()->getSVal(R) != V) + return NULL; + if (Pred->getState()->getSVal(R) == V) return NULL; - } - StoreSite = Last; + StoreSite = Succ; - // If the value that was stored came from an inlined call, make sure we - // step into the call. - if (InitE) { - InitE = InitE->IgnoreParenCasts(); - ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE, BR); - } + // If this is an assignment expression, we can track the value + // being assigned. + if (const PostStmt *P = Succ->getLocationAs<PostStmt>()) + if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>()) + if (BO->isAssignmentOp()) + InitE = BO->getRHS(); } - if (StoreSite != N) + if (!StoreSite) return NULL; - satisfied = true; + + // If the value that was stored came from an inlined call, make sure we + // step into the call. + if (InitE) { + InitE = InitE->IgnoreParenCasts(); + ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE, BR); + } + + // Okay, we've found the binding. Emit an appropriate message. SmallString<256> sbuf; llvm::raw_svector_ostream os(sbuf); - if (const PostStmt *PS = N->getLocationAs<PostStmt>()) { + if (const PostStmt *PS = StoreSite->getLocationAs<PostStmt>()) { if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { @@ -391,7 +375,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *N, } // Construct a new PathDiagnosticPiece. - ProgramPoint P = N->getLocation(); + ProgramPoint P = StoreSite->getLocation(); PathDiagnosticLocation L = PathDiagnosticLocation::create(P, BRC.getSourceManager()); if (!L.isValid()) |