aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/ExplodedGraph.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/ExplodedGraph.cpp')
-rw-r--r--lib/Analysis/ExplodedGraph.cpp39
1 files changed, 34 insertions, 5 deletions
diff --git a/lib/Analysis/ExplodedGraph.cpp b/lib/Analysis/ExplodedGraph.cpp
index 2ba46d77d6..3788551be0 100644
--- a/lib/Analysis/ExplodedGraph.cpp
+++ b/lib/Analysis/ExplodedGraph.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
+#include "clang/AST/Stmt.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
@@ -103,18 +104,30 @@ ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources,
// Enqueue the source nodes to the first worklist.
std::list<std::pair<ExplodedNodeImpl*, ExplodedNodeImpl*> > WL1;
+ std::list<std::pair<ExplodedNodeImpl*, ExplodedNodeImpl*> > WL1_Loops;
for (ExplodedNodeImpl** I = BeginSources; I != EndSources; ++I)
WL1.push_back(std::make_pair(*I, *I));
// Process the worklist.
- while (!WL1.empty()) {
+ while (! (WL1.empty() && WL1_Loops.empty())) {
- ExplodedNodeImpl* N = WL1.back().first;
- ExplodedNodeImpl* Src = WL1.back().second;
+ ExplodedNodeImpl *N, *Src;
+
+ // Only dequeue from the "loops" worklist if WL1 has no items.
+ // Thus we prioritize for paths that don't span loop boundaries.
- WL1.pop_back();
+ if (WL1.empty()) {
+ N = WL1_Loops.back().first;
+ Src = WL1_Loops.back().second;
+ WL1_Loops.pop_back();
+ }
+ else {
+ N = WL1.back().first;
+ Src = WL1.back().second;
+ WL1.pop_back();
+ }
if (Pass1.find(N) != Pass1.end())
continue;
@@ -152,8 +165,24 @@ ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources,
if (VisitPreds)
for (ExplodedNodeImpl** I=N->Preds.begin(), **E=N->Preds.end();
- I!=E; ++I)
+ I!=E; ++I) {
+
+ ProgramPoint P = Src->getLocation();
+
+ if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P))
+ if (Stmt* T = BE->getSrc()->getTerminator())
+ switch (T->getStmtClass()) {
+ default: break;
+ case Stmt::ForStmtClass:
+ case Stmt::WhileStmtClass:
+ case Stmt::DoStmtClass:
+ WL1_Loops.push_front(std::make_pair(*I, Src));
+ continue;
+
+ }
+
WL1.push_front(std::make_pair(*I, Src));
+ }
}
}