From: Ted Kremenek Date: Wed, 12 Mar 2008 17:18:20 +0000 (+0000) Subject: Improved ExplodedGraph::Trim to only show nodes reachable from a reverse BFS X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7ec07fd91f6eae8bd619ebb8512805222ca41c92;p=clang Improved ExplodedGraph::Trim to only show nodes reachable from a reverse BFS from the sources, and to try and generate only a single path from sources to roots. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@48286 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/ExplodedGraph.cpp b/Analysis/ExplodedGraph.cpp index 421b9e3846..2ba46d77d6 100644 --- a/Analysis/ExplodedGraph.cpp +++ b/Analysis/ExplodedGraph.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include +#include using namespace clang; @@ -89,7 +90,7 @@ ExplodedNodeImpl::NodeGroup::~NodeGroup() { ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources, ExplodedNodeImpl** EndSources) const{ - typedef llvm::DenseSet Pass1Ty; + typedef llvm::DenseMap Pass1Ty; typedef llvm::DenseMap Pass2Ty; Pass1Ty Pass1; @@ -101,30 +102,58 @@ ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources, // Enqueue the source nodes to the first worklist. - llvm::SmallVector WL1; + std::list > 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)); } } @@ -182,8 +211,12 @@ ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources, // 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()) diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp index e2fec9f88f..61643a440e 100644 --- a/Analysis/GRExprEngine.cpp +++ b/Analysis/GRExprEngine.cpp @@ -1805,23 +1805,49 @@ struct VISIBILITY_HIDDEN DOTGraphTraits : #endif #ifndef NDEBUG + +template +GRExprEngine::NodeTy* GetGraphNode(ITERATOR I) { return *I; } + +template <> +GRExprEngine::NodeTy* +GetGraphNode::iterator> + (llvm::DenseMap::iterator I) { + return I->first; +} + template static void AddSources(llvm::SmallVector& Sources, - ITERATOR I, ITERATOR E) { + ITERATOR I, ITERATOR E) { + + llvm::SmallPtrSet 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 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 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; diff --git a/Analysis/GRSimpleVals.cpp b/Analysis/GRSimpleVals.cpp index 16cd6747a0..75ca27e1b4 100644 --- a/Analysis/GRSimpleVals.cpp +++ b/Analysis/GRSimpleVals.cpp @@ -101,7 +101,7 @@ unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx, CheckerState->setTransferFunctions(GRSV); // Execute the worklist algorithm. - Eng.ExecuteWorkList(50000); + Eng.ExecuteWorkList(100000); SourceManager& SrcMgr = Ctx.getSourceManager();