When building PathDiagnostics for bug reports, generate a trimmed ExplodedGraph with a single path that BugReport objects can safely walk and introspect.
llvm-svn: 50194
This commit is contained in:
parent
8bfd6de8db
commit
f26bc55b9a
|
@ -167,6 +167,10 @@ public:
|
||||||
Profile(ID, getLocation(), getState());
|
Profile(ID, getLocation(), getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addPredecessor(ExplodedNode* V) {
|
||||||
|
ExplodedNodeImpl::addPredecessor(V);
|
||||||
|
}
|
||||||
|
|
||||||
// Iterators over successor and predecessor vertices.
|
// Iterators over successor and predecessor vertices.
|
||||||
typedef ExplodedNode** succ_iterator;
|
typedef ExplodedNode** succ_iterator;
|
||||||
typedef const ExplodedNode** const_succ_iterator;
|
typedef const ExplodedNode** const_succ_iterator;
|
||||||
|
@ -270,7 +274,8 @@ public:
|
||||||
llvm::BumpPtrAllocator& getAllocator() { return Allocator; }
|
llvm::BumpPtrAllocator& getAllocator() { return Allocator; }
|
||||||
CFG& getCFG() { return cfg; }
|
CFG& getCFG() { return cfg; }
|
||||||
ASTContext& getContext() { return Ctx; }
|
ASTContext& getContext() { return Ctx; }
|
||||||
|
|
||||||
|
Decl& getCodeDecl() { return CodeDecl; }
|
||||||
const Decl& getCodeDecl() const { return CodeDecl; }
|
const Decl& getCodeDecl() const { return CodeDecl; }
|
||||||
|
|
||||||
const FunctionDecl* getFunctionDecl() const {
|
const FunctionDecl* getFunctionDecl() const {
|
||||||
|
|
|
@ -139,35 +139,66 @@ PathDiagnosticPiece* BugReport::VisitNode(ExplodedNode<ValueState>* N,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
|
static std::pair<ExplodedGraph<ValueState>*, ExplodedNode<ValueState>*>
|
||||||
BugReport& R) {
|
MakeReportGraph(ExplodedGraph<ValueState>* G, ExplodedNode<ValueState>* N) {
|
||||||
|
|
||||||
ExplodedNode<ValueState>* N = R.getEndNode();
|
|
||||||
|
|
||||||
if (!N)
|
|
||||||
return;
|
|
||||||
|
|
||||||
llvm::OwningPtr<ExplodedGraph<ValueState> > GTrim(getGraph().Trim(&N, &N+1));
|
llvm::OwningPtr<ExplodedGraph<ValueState> > GTrim(G->Trim(&N, &N+1));
|
||||||
|
|
||||||
// Find the sink in the trimmed graph.
|
// Find the sink node in the trimmed graph.
|
||||||
// FIXME: Should we eventually have a sink iterator?
|
|
||||||
|
|
||||||
ExplodedNode<ValueState>* NewN = 0;
|
N = NULL;
|
||||||
|
|
||||||
for (ExplodedGraph<ValueState>::node_iterator
|
for (ExplodedGraph<ValueState>::node_iterator
|
||||||
I = GTrim->nodes_begin(), E = GTrim->nodes_end(); I != E; ++I) {
|
I = GTrim->nodes_begin(), E = GTrim->nodes_end(); I != E; ++I) {
|
||||||
|
|
||||||
if (I->isSink()) {
|
if (I->isSink()) {
|
||||||
NewN = &*I;
|
N = &*I;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (NewN);
|
assert(N);
|
||||||
assert (NewN->getLocation() == N->getLocation());
|
|
||||||
|
|
||||||
N = NewN;
|
|
||||||
|
|
||||||
|
// 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))
|
if (PathDiagnosticPiece* Piece = R.getEndPath(*this, N))
|
||||||
PD.push_back(Piece);
|
PD.push_back(Piece);
|
||||||
else
|
else
|
||||||
|
@ -350,7 +381,8 @@ void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (PathDiagnosticPiece* piece = R.VisitNode(N, NextNode, *GTrim, *this))
|
if (PathDiagnosticPiece* piece = R.VisitNode(N, NextNode,
|
||||||
|
*ReportGraph, *this))
|
||||||
PD.push_front(piece);
|
PD.push_front(piece);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue