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;
53 return isa<DeclRefExpr>(Ex) ||
54 isa<MemberExpr>(Ex) ||
55 isa<ObjCIvarRefExpr>(Ex);
105 return !progPoint.
getTag();
118 if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
163 pred->replaceSuccessor(succ);
164 succ->replacePredecessor(pred);
166 Nodes.RemoveNode(node);
168 node->~ExplodedNode();
184 if (shouldCollect(node))
186 ChangedNodes.clear();
204 using GroupStorage = llvm::PointerUnion<ExplodedNode *, ExplodedNodeVector *>;
209 V->Succs.addNode(
this, G);
212 void ExplodedNode::NodeGroup::replaceNode(
ExplodedNode *node) {
225 if (Storage.isNull()) {
250 unsigned ExplodedNode::NodeGroup::size()
const {
255 if (Storage.isNull())
262 ExplodedNode *
const *ExplodedNode::NodeGroup::begin()
const {
267 if (Storage.isNull())
271 return Storage.getAddrOfPtr1();
274 ExplodedNode *
const *ExplodedNode::NodeGroup::end()
const {
279 if (Storage.isNull())
283 return Storage.getAddrOfPtr1() + 1;
287 return pred_size() == 1 && succ_size() == 1 &&
288 getFirstPred()->getState()->getID() == getState()->getID() &&
289 getFirstPred()->succ_size() == 1;
295 return BEP->getBlock();
300 if (
const Stmt *S = getStmtForDiagnostics())
301 return getLocationContext()
302 ->getAnalysisDeclContext()
313 assert(ParentLC &&
"We don't start analysis from autosynthesized code");
314 while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
317 assert(ParentLC &&
"We don't start analysis from autosynthesized code");
336 return SP->getStmt();
338 return BE->getSrc()->getTerminatorStmt();
340 return CE->getCallExpr();
342 return CEE->getCalleeContext()->getCallSite();
344 return PIPP->getInitializer()->getInit();
346 return CEB->getReturnStmt();
348 return FEP->getStmt();
358 switch (S->getStmtClass()) {
359 case Stmt::ChooseExprClass:
360 case Stmt::BinaryConditionalOperatorClass:
361 case Stmt::ConditionalOperatorClass:
363 case Stmt::BinaryOperatorClass: {
365 if (Op == BO_LAnd || Op == BO_LOr)
389 if (
const Stmt *S = getStmtForDiagnostics())
392 return getPreviousStmtForDiagnostics();
400 llvm::FoldingSetNodeID profile;
401 void *InsertPos =
nullptr;
404 NodeTy*
V =
Nodes.FindNodeOrInsertPos(profile, InsertPos);
417 new (
V)
NodeTy(L, State, NumNodes, IsSink);
423 Nodes.InsertNode(V, InsertPos);
425 if (IsNew) *IsNew =
true;
428 if (IsNew) *IsNew =
false;
438 new (
V)
NodeTy(L, State, Id, IsSink);
442 std::unique_ptr<ExplodedGraph>
454 Pass2Ty &Pass2 = ForwardMap ? *ForwardMap : Pass2Scratch;
459 for (
const auto Sink : Sinks)
464 while (!WL1.empty()) {
468 if (!Pass1.insert(N).second)
472 if (N->Preds.empty()) {
478 WL1.append(N->Preds.begin(), N->Preds.end());
489 while (!WL2.empty()) {
493 if (Pass2.find(N) != Pass2.end())
503 if (InverseMap) (*InverseMap)[NewN] = N;
506 if (N->Preds.empty())
516 Pass2Ty::iterator PI = Pass2.find(*I);
517 if (PI == Pass2.end())
529 Pass2Ty::iterator PI = Pass2.find(*I);
530 if (PI != Pass2.end()) {
531 const_cast<ExplodedNode *
>(PI->second)->addPredecessor(NewN, *G);
unsigned ReclaimCounter
Counter to determine when to reclaim nodes.
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
const Stmt * getCurrentOrPreviousStmtForDiagnostics() const
Find the statement that was executed at or immediately before this node.
Stmt - This represents one statement.
NodeVector FreeNodes
A list of nodes that can be reused.
Represents a point when we begin processing an inlined call.
const CFGBlock * getCFGBlock() const
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
int64_t NumNodes
NumNodes - The number of nodes in the graph.
NodeVector ChangedNodes
A list of recently allocated nodes that can potentially be recycled.
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
Represents a point when we start the call exit sequence (for inlined call).
unsigned succ_size() const
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
const LocationContext * getLocationContext() const
std::unique_ptr< ExplodedGraph > MakeEmptyGraph() const
const LocationContext * getParent() const
ExplodedNode * getFirstPred()
unsigned pred_size() const
Represents a single basic block in a source-level CFG.
Represents a point when we finish the call exit sequence (for inlined call).
This represents one expression.
ExplodedNode * getFirstSucc()
ExplodedNode *const * succ_iterator
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
ExplodedNode * createUncachedNode(const ProgramPoint &L, ProgramStateRef State, int64_t Id, bool IsSink=false)
Create a node for a (Location, State) pair, but don't store it for deduplication later.
static void Profile(llvm::FoldingSetNodeID &ID, const ProgramPoint &Loc, const ProgramStateRef &state, bool IsSink)
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 ...
llvm::PointerUnion< ExplodedNode *, ExplodedNodeVector * > GroupStorage
unsigned ReclaimNodeInterval
Determines how often nodes are reclaimed.
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.
llvm::FoldingSet< ExplodedNode > Nodes
Nodes - The nodes in the graph.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
const Stmt * getPreviousStmtForDiagnostics() const
Find the statement that was executed immediately before this 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()
BumpVector< ExplodedNode * > ExplodedNodeVector
void reclaimRecentlyAllocatedNodes()
Reclaim "uninteresting" nodes created since the last time this method was called. ...
bool isTrivial() const
The node is trivial if it has only one successor, only one predecessor, it's predecessor has only one...
const ProgramPointTag * getTag() const
llvm::DenseMap< const ExplodedNode *, const ExplodedNode * > InterExplodedGraphMap
const LocationContext * getLocationContext() const
const ParentMap & getParentMap() const
pred_iterator pred_begin()
llvm::BumpPtrAllocator & getAllocator()
const Stmt * getNextStmtForDiagnostics() const
Find the next statement that was executed on this node's execution path.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
AnalysisDeclContext * getAnalysisDeclContext() const
ExplodedNode *const * pred_iterator
static bool isInterestingLValueExpr(const Expr *Ex)
Returns true if nodes for the given expression kind are always kept around.