aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/BugReporter.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-02-18 03:48:14 +0000
committerTed Kremenek <kremenek@apple.com>2009-02-18 03:48:14 +0000
commitfe9e543a2a363df7fcaa899367d3b2580b63b27c (patch)
treed6a9cc6935655adbccddcac142da70264be5706e /lib/Analysis/BugReporter.cpp
parent3e030b4c04546229c81449fde66f71b23b3fc550 (diff)
Hooked up the necessary machinery to allow the retain/release checker reference
back to the summary used when evaluating the statement associated with a simulation node. This is now being used to help improve the checker's diagnostics. To get things started, the checker now emits a path diagnostic indicating that 'autorelease' is a no-op in GC mode. Some of these changes are exposing further grossness in the interface between BugReporter and the ExplodedGraph::Trim facilities. These really need to be cleaned up one day. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64881 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/BugReporter.cpp')
-rw-r--r--lib/Analysis/BugReporter.cpp50
1 files changed, 40 insertions, 10 deletions
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index cf1d1b774d..eb0b442bc1 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/lib/Analysis/BugReporter.cpp
@@ -167,7 +167,8 @@ SourceLocation BugReport::getLocation() const {
PathDiagnosticPiece* BugReport::VisitNode(const ExplodedNode<GRState>* N,
const ExplodedNode<GRState>* PrevN,
const ExplodedGraph<GRState>& G,
- BugReporter& BR) {
+ BugReporter& BR,
+ NodeResolver &NR) {
return NULL;
}
@@ -226,7 +227,10 @@ void BugReporter::FlushReports() {
// PathDiagnostics generation.
//===----------------------------------------------------------------------===//
-static std::pair<ExplodedGraph<GRState>*,
+typedef llvm::DenseMap<const ExplodedNode<GRState>*,
+ const ExplodedNode<GRState>*> NodeBackMap;
+
+static std::pair<std::pair<ExplodedGraph<GRState>*, NodeBackMap*>,
std::pair<ExplodedNode<GRState>*, unsigned> >
MakeReportGraph(const ExplodedGraph<GRState>* G,
const ExplodedNode<GRState>** NStart,
@@ -238,7 +242,9 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
// path length.
ExplodedGraph<GRState>* GTrim;
InterExplodedGraphMap<GRState>* NMap;
- llvm::tie(GTrim, NMap) = G->Trim(NStart, NEnd);
+
+ llvm::DenseMap<const void*, const void*> InverseMap;
+ llvm::tie(GTrim, NMap) = G->Trim(NStart, NEnd, &InverseMap);
// Create owning pointers for GTrim and NMap just to ensure that they are
// released when this function exists.
@@ -262,8 +268,8 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
// Create a new (third!) graph with a single path. This is the graph
// that will be returned to the caller.
ExplodedGraph<GRState> *GNew =
- new ExplodedGraph<GRState>(GTrim->getCFG(), GTrim->getCodeDecl(),
- GTrim->getContext());
+ new ExplodedGraph<GRState>(GTrim->getCFG(), GTrim->getCodeDecl(),
+ GTrim->getContext());
// Sometimes the trimmed graph can contain a cycle. Perform a reverse DFS
// to the root node, and then construct a new graph that contains only
@@ -298,6 +304,7 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
// Now walk from the root down the DFS path, always taking the successor
// with the lowest number.
ExplodedNode<GRState> *Last = 0, *First = 0;
+ NodeBackMap *BM = new NodeBackMap();
for ( N = Root ;;) {
// Lookup the number associated with the current node.
@@ -307,7 +314,12 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
// Create the equivalent node in the new graph with the same state
// and location.
ExplodedNode<GRState>* NewN =
- GNew->getNode(N->getLocation(), N->getState());
+ GNew->getNode(N->getLocation(), N->getState());
+
+ // Store the mapping to the original node.
+ llvm::DenseMap<const void*, const void*>::iterator IMitr=InverseMap.find(N);
+ assert(IMitr != InverseMap.end() && "No mapping to original node.");
+ (*BM)[NewN] = (const ExplodedNode<GRState>*) IMitr->second;
// Link up the new node with the previous node.
if (Last)
@@ -344,7 +356,8 @@ MakeReportGraph(const ExplodedGraph<GRState>* G,
}
assert (First);
- return std::make_pair(GNew, std::make_pair(First, NodeIndex));
+ return std::make_pair(std::make_pair(GNew, BM),
+ std::make_pair(First, NodeIndex));
}
static const VarDecl*
@@ -527,6 +540,20 @@ public:
};
} // end anonymous namespace
+namespace {
+class VISIBILITY_HIDDEN NodeMapClosure : public BugReport::NodeResolver {
+ NodeBackMap& M;
+public:
+ NodeMapClosure(NodeBackMap *m) : M(*m) {}
+ ~NodeMapClosure() {}
+
+ const ExplodedNode<GRState>* getOriginalNode(const ExplodedNode<GRState>* N) {
+ NodeBackMap::iterator I = M.find(N);
+ return I == M.end() ? 0 : I->second;
+ }
+};
+}
+
void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
BugReportEquivClass& EQ) {
@@ -542,7 +569,7 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
// Construct a new graph that contains only a single path from the error
// node to a root.
- const std::pair<ExplodedGraph<GRState>*,
+ const std::pair<std::pair<ExplodedGraph<GRState>*, NodeBackMap*>,
std::pair<ExplodedNode<GRState>*, unsigned> >&
GPair = MakeReportGraph(&getGraph(), &Nodes[0], &Nodes[0] + Nodes.size());
@@ -554,7 +581,8 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
assert(R && "No original report found for sliced graph.");
- llvm::OwningPtr<ExplodedGraph<GRState> > ReportGraph(GPair.first);
+ llvm::OwningPtr<ExplodedGraph<GRState> > ReportGraph(GPair.first.first);
+ llvm::OwningPtr<NodeBackMap> BackMap(GPair.first.second);
const ExplodedNode<GRState> *N = GPair.second.first;
// Start building the path diagnostic...
@@ -568,6 +596,7 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
ASTContext& Ctx = getContext();
SourceManager& SMgr = Ctx.getSourceManager();
+ NodeMapClosure NMC(BackMap.get());
while (NextNode) {
@@ -750,7 +779,8 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
}
}
- if (PathDiagnosticPiece* p = R->VisitNode(N, NextNode, *ReportGraph, *this))
+ if (PathDiagnosticPiece* p = R->VisitNode(N, NextNode, *ReportGraph, *this,
+ NMC))
PD.push_front(p);
if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {