26 #include "llvm/ADT/DenseSet.h" 27 #include "llvm/ADT/FoldingSet.h" 28 #include "llvm/ADT/Optional.h" 29 #include "llvm/ADT/PointerUnion.h" 30 #include "llvm/ADT/SmallVector.h" 31 #include "llvm/Support/Casting.h" 35 using namespace clang;
70 return isa<DeclRefExpr>(Ex) ||
71 isa<MemberExpr>(Ex) ||
72 isa<ObjCIvarRefExpr>(Ex);
75 bool ExplodedGraph::shouldCollect(
const ExplodedNode *node) {
122 return !progPoint.
getTag();
135 if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
148 if (isInterestingLValueExpr(Ex))
180 pred->replaceSuccessor(succ);
181 succ->replacePredecessor(pred);
182 FreeNodes.push_back(node);
183 Nodes.RemoveNode(node);
185 node->~ExplodedNode();
189 if (ChangedNodes.empty())
195 assert(ReclaimCounter > 0);
196 if (--ReclaimCounter != 0)
198 ReclaimCounter = ReclaimNodeInterval;
200 for (
const auto node : ChangedNodes)
201 if (shouldCollect(node))
203 ChangedNodes.clear();
221 using GroupStorage = llvm::PointerUnion<ExplodedNode *, ExplodedNodeVector *>;
226 V->Succs.addNode(
this, G);
228 if (NodeAuditor) NodeAuditor->
AddEdge(V,
this);
232 void ExplodedNode::NodeGroup::replaceNode(
ExplodedNode *node) {
245 if (Storage.isNull()) {
270 unsigned ExplodedNode::NodeGroup::size()
const {
275 if (Storage.isNull())
282 ExplodedNode *
const *ExplodedNode::NodeGroup::begin()
const {
287 if (Storage.isNull())
291 return Storage.getAddrOfPtr1();
294 ExplodedNode *
const *ExplodedNode::NodeGroup::end()
const {
299 if (Storage.isNull())
303 return Storage.getAddrOfPtr1() + 1;
311 llvm::FoldingSetNodeID profile;
312 void *InsertPos =
nullptr;
314 NodeTy::Profile(profile, L, State, IsSink);
315 NodeTy* V =
Nodes.FindNodeOrInsertPos(profile, InsertPos);
318 if (!FreeNodes.empty()) {
319 V = FreeNodes.back();
320 FreeNodes.pop_back();
327 new (V)
NodeTy(L, State, IsSink);
329 if (ReclaimNodeInterval)
330 ChangedNodes.push_back(V);
333 Nodes.InsertNode(V, InsertPos);
336 if (IsNew) *IsNew =
true;
339 if (IsNew) *IsNew =
false;
348 new (V)
NodeTy(L, State, IsSink);
352 std::unique_ptr<ExplodedGraph>
364 Pass2Ty &Pass2 = ForwardMap ? *ForwardMap : Pass2Scratch;
369 for (
const auto Sink : Sinks)
374 while (!WL1.empty()) {
378 if (!Pass1.insert(N).second)
382 if (N->Preds.empty()) {
388 WL1.append(N->Preds.begin(), N->Preds.end());
396 std::unique_ptr<ExplodedGraph> G = MakeEmptyGraph();
399 while (!WL2.empty()) {
403 if (Pass2.find(N) != Pass2.end())
412 if (InverseMap) (*InverseMap)[NewN] = N;
415 if (N->Preds.empty())
425 Pass2Ty::iterator PI = Pass2.find(*I);
426 if (PI == Pass2.end())
438 Pass2Ty::iterator PI = Pass2.find(*I);
439 if (PI != Pass2.end()) {
Represents a point when we begin processing an inlined call.
Represents a point after we ran remove dead bindings BEFORE processing the given statement.
Represents a program point just before an implicit call event.
const ProgramStateRef & getState() const
bool isConsumedExpr(Expr *E) const
BoundNodesTreeBuilder Nodes
succ_iterator succ_begin()
Represents a program point after a store evaluation.
std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy *> Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const
Creates a trimmed version of the graph that only contains paths leading to the given nodes...
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
unsigned succ_size() const
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
const LocationContext * getLocationContext() const
unsigned pred_size() const
ExplodedNode * createUncachedNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink=false)
Create a node for a (Location, State) pair, but don't store it for deduplication later.
Expr - This represents one expression.
ExplodedNode *const * succ_iterator
static ExplodedNode::Auditor * NodeAuditor
ExplodedNode * getNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink=false, bool *IsNew=nullptr)
Retrieve the node associated with a (Location,State) pair, where the 'Location' is a ProgramPoint in ...
ParentMap & getParentMap() const
llvm::PointerUnion< ExplodedNode *, ExplodedNodeVector * > GroupStorage
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type...
static bool isCallStmt(const Stmt *S)
Returns true if this is a statement is a function or method call of some kind.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language...
void push_back(const_reference Elt, BumpVectorContext &C)
Dataflow Directional Tag Classes.
BumpVectorContext & getNodeAllocator()
virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst)=0
BumpVector< ExplodedNode * > ExplodedNodeVector
void reclaimRecentlyAllocatedNodes()
Reclaim "uninteresting" nodes created since the last time this method was called. ...
const ProgramPointTag * getTag() const
llvm::DenseMap< const ExplodedNode *, const ExplodedNode * > InterExplodedGraphMap
static void SetAuditor(Auditor *A)
const LocationContext * getLocationContext() const
pred_iterator pred_begin()
llvm::BumpPtrAllocator & getAllocator()
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
ExplodedNode *const * pred_iterator
static bool isInterestingLValueExpr(const Expr *Ex)
Returns true if nodes for the given expression kind are always kept around.