#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
+#include <list>
using namespace clang;
ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources,
ExplodedNodeImpl** EndSources) const{
- typedef llvm::DenseSet<ExplodedNodeImpl*> Pass1Ty;
+ typedef llvm::DenseMap<ExplodedNodeImpl*, ExplodedNodeImpl*> Pass1Ty;
typedef llvm::DenseMap<ExplodedNodeImpl*, ExplodedNodeImpl*> Pass2Ty;
Pass1Ty Pass1;
// Enqueue the source nodes to the first worklist.
- llvm::SmallVector<ExplodedNodeImpl*, 10> WL1;
+ std::list<std::pair<ExplodedNodeImpl*, ExplodedNodeImpl*> > WL1;
for (ExplodedNodeImpl** I = BeginSources; I != EndSources; ++I)
- WL1.push_back(*I);
+ WL1.push_back(std::make_pair(*I, *I));
// Process the worklist.
while (!WL1.empty()) {
- ExplodedNodeImpl* N = WL1.back();
+ ExplodedNodeImpl* N = WL1.back().first;
+ ExplodedNodeImpl* Src = WL1.back().second;
+
WL1.pop_back();
- if (Pass1.count(N))
+ if (Pass1.find(N) != Pass1.end())
continue;
- Pass1.insert(N);
+ bool PredHasSameSource = false;
+ bool VisitPreds = true;
+
+ for (ExplodedNodeImpl** I=N->Preds.begin(), **E=N->Preds.end();
+ I!=E; ++I) {
+
+ Pass1Ty::iterator pi = Pass1.find(*I);
+
+ if (pi == Pass1.end())
+ continue;
+
+ VisitPreds = false;
+
+ if (pi->second == Src) {
+ PredHasSameSource = true;
+ break;
+ }
+ }
+
+ if (VisitPreds || !PredHasSameSource) {
+
+ Pass1[N] = Src;
- if (N->Preds.empty()) {
- WL2.push_back(N);
- continue;
+ if (N->Preds.empty()) {
+ WL2.push_back(N);
+ continue;
+ }
}
+ else
+ Pass1[N] = NULL;
- for (ExplodedNodeImpl** I=N->Preds.begin(), **E=N->Preds.end(); I!=E; ++I)
- WL1.push_back(*I);
+ if (VisitPreds)
+ for (ExplodedNodeImpl** I=N->Preds.begin(), **E=N->Preds.end();
+ I!=E; ++I)
+ WL1.push_front(std::make_pair(*I, Src));
}
}
// Enqueue nodes to the worklist that were marked during pass 1.
- if (Pass1.count(*I))
- WL2.push_back(*I);
+ Pass1Ty::iterator pi = Pass1.find(*I);
+
+ if (pi == Pass1.end() || pi->second == NULL)
+ continue;
+
+ WL2.push_back(*I);
}
if (N->isSink())
#endif
#ifndef NDEBUG
+
+template <typename ITERATOR>
+GRExprEngine::NodeTy* GetGraphNode(ITERATOR I) { return *I; }
+
+template <>
+GRExprEngine::NodeTy*
+GetGraphNode<llvm::DenseMap<GRExprEngine::NodeTy*, Expr*>::iterator>
+ (llvm::DenseMap<GRExprEngine::NodeTy*, Expr*>::iterator I) {
+ return I->first;
+}
+
template <typename ITERATOR>
static void AddSources(llvm::SmallVector<GRExprEngine::NodeTy*, 10>& Sources,
- ITERATOR I, ITERATOR E) {
+ ITERATOR I, ITERATOR E) {
+
+ llvm::SmallPtrSet<void*,10> CachedSources;
- for ( ; I != E; ++I )
- Sources.push_back(*I);
+ for ( ; I != E; ++I ) {
+ GRExprEngine::NodeTy* N = GetGraphNode(I);
+ void* p = N->getLocation().getRawData();
+
+ if (CachedSources.count(p))
+ continue;
+
+ CachedSources.insert(p);
+
+ Sources.push_back(N);
+ }
}
#endif
void GRExprEngine::ViewGraph(bool trim) {
#ifndef NDEBUG
if (trim) {
- llvm::SmallVector<NodeTy*, 10> Sources;
- AddSources(Sources, null_derefs_begin(), null_derefs_end());
- AddSources(Sources, undef_derefs_begin(), undef_derefs_end());
-
- ViewGraph(&Sources[0], &Sources[0]+Sources.size());
+ llvm::SmallVector<NodeTy*, 10> Src;
+ AddSources(Src, null_derefs_begin(), null_derefs_end());
+ AddSources(Src, undef_derefs_begin(), undef_derefs_end());
+ AddSources(Src, explicit_bad_divides_begin(), explicit_bad_divides_end());
+ AddSources(Src, undef_results_begin(), undef_results_end());
+ AddSources(Src, bad_calls_begin(), bad_calls_end());
+ AddSources(Src, undef_arg_begin(), undef_arg_end());
+
+ ViewGraph(&Src[0], &Src[0]+Src.size());
}
else {
GraphPrintCheckerState = this;
CheckerState->setTransferFunctions(GRSV);
// Execute the worklist algorithm.
- Eng.ExecuteWorkList(50000);
+ Eng.ExecuteWorkList(100000);
SourceManager& SrcMgr = Ctx.getSourceManager();