diff options
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/ExplodedGraph.h | 7 | ||||
-rw-r--r-- | clang/lib/Analysis/BugReporter.cpp | 68 |
2 files changed, 56 insertions, 19 deletions
diff --git a/clang/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/clang/include/clang/Analysis/PathSensitive/ExplodedGraph.h index 0d8f31fb826..39a064d4c60 100644 --- a/clang/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/clang/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -167,6 +167,10 @@ public: Profile(ID, getLocation(), getState()); } + void addPredecessor(ExplodedNode* V) { + ExplodedNodeImpl::addPredecessor(V); + } + // Iterators over successor and predecessor vertices. typedef ExplodedNode** succ_iterator; typedef const ExplodedNode** const_succ_iterator; @@ -270,7 +274,8 @@ public: llvm::BumpPtrAllocator& getAllocator() { return Allocator; } CFG& getCFG() { return cfg; } ASTContext& getContext() { return Ctx; } - + + Decl& getCodeDecl() { return CodeDecl; } const Decl& getCodeDecl() const { return CodeDecl; } const FunctionDecl* getFunctionDecl() const { diff --git a/clang/lib/Analysis/BugReporter.cpp b/clang/lib/Analysis/BugReporter.cpp index 68b6ad76be1..d137cff3e7b 100644 --- a/clang/lib/Analysis/BugReporter.cpp +++ b/clang/lib/Analysis/BugReporter.cpp @@ -139,35 +139,66 @@ PathDiagnosticPiece* BugReport::VisitNode(ExplodedNode<ValueState>* N, return NULL; } -void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, - BugReport& R) { - - ExplodedNode<ValueState>* N = R.getEndNode(); - - if (!N) - return; +static std::pair<ExplodedGraph<ValueState>*, ExplodedNode<ValueState>*> +MakeReportGraph(ExplodedGraph<ValueState>* G, ExplodedNode<ValueState>* N) { - llvm::OwningPtr<ExplodedGraph<ValueState> > GTrim(getGraph().Trim(&N, &N+1)); - - // Find the sink in the trimmed graph. - // FIXME: Should we eventually have a sink iterator? + llvm::OwningPtr<ExplodedGraph<ValueState> > GTrim(G->Trim(&N, &N+1)); + + // Find the sink node in the trimmed graph. - ExplodedNode<ValueState>* NewN = 0; + N = NULL; for (ExplodedGraph<ValueState>::node_iterator I = GTrim->nodes_begin(), E = GTrim->nodes_end(); I != E; ++I) { if (I->isSink()) { - NewN = &*I; + N = &*I; break; } } - assert (NewN); - assert (NewN->getLocation() == N->getLocation()); - - N = NewN; + assert(N); + + // Create a new graph with a single path. + + G = new ExplodedGraph<ValueState>(GTrim->getCFG(), GTrim->getCodeDecl(), + GTrim->getContext()); + + + ExplodedNode<ValueState>* Last = 0; + + while (N) { + ExplodedNode<ValueState>* NewN = + G->getNode(N->getLocation(), N->getState()); + + if (Last) Last->addPredecessor(NewN); + Last = NewN; + N = N->pred_empty() ? 0 : *(N->pred_begin()); + } + + return std::make_pair(G, Last); +} + +void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, + BugReport& R) { + + ExplodedNode<ValueState>* N = R.getEndNode(); + + if (!N) return; + + // Construct a new graph that contains only a single path from the error + // node to a root. + + const std::pair<ExplodedGraph<ValueState>*,ExplodedNode<ValueState>*> + GPair = MakeReportGraph(&getGraph(), N); + + llvm::OwningPtr<ExplodedGraph<ValueState> > ReportGraph(GPair.first); + assert(GPair.second->getLocation() == N->getLocation()); + N = GPair.second; + + // Start building the path diagnostic... + if (PathDiagnosticPiece* Piece = R.getEndPath(*this, N)) PD.push_back(Piece); else @@ -350,7 +381,8 @@ void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, } } else - if (PathDiagnosticPiece* piece = R.VisitNode(N, NextNode, *GTrim, *this)) + if (PathDiagnosticPiece* piece = R.VisitNode(N, NextNode, + *ReportGraph, *this)) PD.push_front(piece); } } |