aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-08-11 00:03:02 +0000
committerTed Kremenek <kremenek@apple.com>2010-08-11 00:03:02 +0000
commitf598087b4adfea164acdd5b53ea2951bde740a2d (patch)
treeee8ef8d6f8ccf2970d2066019cbf80465a753605
parent594ca4325cdf6f2c3e2ae584df069faafeaf145e (diff)
Have GRCoreEngine record the blocks where analysis was aborted because we visited a block too many times along a given path. This is to support the unreachable code analysis.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110755 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Checker/PathSensitive/GRCoreEngine.h27
-rw-r--r--lib/Checker/GRCoreEngine.cpp7
2 files changed, 22 insertions, 12 deletions
diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h
index dbef757826..0426194c5e 100644
--- a/include/clang/Checker/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h
@@ -58,9 +58,13 @@ class GRCoreEngine {
/// number of times different CFGBlocks have been visited along a path.
GRBlockCounter::Factory BCounterFactory;
- /// A flag that indicates whether paths were halted because
- /// ProcessBlockEntrace returned false.
- bool BlockAborted;
+
+ typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
+ BlocksAborted;
+
+ /// The locations where we stopped doing work because we visited a location
+ /// too many times.
+ BlocksAborted blocksAborted;
void GenerateNode(const ProgramPoint& Loc, const GRState* State,
ExplodedNode* Pred);
@@ -129,16 +133,14 @@ public:
GRCoreEngine(GRSubEngine& subengine)
: SubEngine(subengine), G(new ExplodedGraph()),
WList(GRWorkList::MakeBFS()),
- BCounterFactory(G->getAllocator()),
- BlockAborted(false) {}
+ BCounterFactory(G->getAllocator()) {}
/// Construct a GRCoreEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm.
/// The GRCoreEngine object assumes ownership of 'wlist'.
GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine)
: SubEngine(subengine), G(new ExplodedGraph()), WList(wlist),
- BCounterFactory(G->getAllocator()),
- BlockAborted(false) {}
+ BCounterFactory(G->getAllocator()) {}
~GRCoreEngine() {
delete WList;
@@ -160,10 +162,17 @@ public:
ExplodedNodeSet &Dst);
// Functions for external checking of whether we have unfinished work
- bool wasBlockAborted() const { return BlockAborted; }
- bool hasWorkRemaining() const { return BlockAborted || WList->hasWork(); }
+ bool wasBlockAborted() const { return !blocksAborted.empty(); }
+ bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); }
GRWorkList *getWorkList() const { return WList; }
+
+ BlocksAborted::const_iterator blocks_aborted_begin() const {
+ return blocksAborted.begin();
+ }
+ BlocksAborted::const_iterator blocks_aborted_end() const {
+ return blocksAborted.end();
+ }
};
class GRStmtNodeBuilder {
diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp
index c2a3322537..e0524d9ef4 100644
--- a/lib/Checker/GRCoreEngine.cpp
+++ b/lib/Checker/GRCoreEngine.cpp
@@ -200,7 +200,7 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
}
}
- SubEngine.ProcessEndWorklist(WList->hasWork() || BlockAborted);
+ SubEngine.ProcessEndWorklist(hasWorkRemaining());
return WList->hasWork();
}
@@ -250,8 +250,9 @@ void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
if (ProcessBlockEntrance(Blk, Pred, WList->getBlockCounter()))
GenerateNode(BlockEntrance(Blk, Pred->getLocationContext()),
Pred->State, Pred);
- else
- BlockAborted = true;
+ else {
+ blocksAborted.push_back(std::make_pair(L, Pred));
+ }
}
void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,