aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/BugReporter.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-04-23 23:02:12 +0000
committerTed Kremenek <kremenek@apple.com>2008-04-23 23:02:12 +0000
commita43a1eb6e7c773b79898541794bf819601719493 (patch)
treeacad009729d022aa1c5ff244c64e5ea44836841e /lib/Analysis/BugReporter.cpp
parent186350f192bbc6a81bc6d7c3647c2243353f21ba (diff)
When building PathDiagnostics for bug reports, generate a trimmed ExplodedGraph with a single path that BugReport objects can safely walk and introspect.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50194 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/BugReporter.cpp')
-rw-r--r--lib/Analysis/BugReporter.cpp68
1 files changed, 50 insertions, 18 deletions
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index 68b6ad76be..d137cff3e7 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/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);
}
}