25#include "llvm/ADT/DenseSet.h"
26#include "llvm/ADT/FoldingSet.h"
27#include "llvm/ADT/PointerUnion.h"
53bool ExplodedGraph::shouldCollect(
const ExplodedNode *node) {
85 if (node->pred_size() != 1 || node->succ_size() != 1)
100 return !progPoint.
getTag();
113 if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
155 assert(node->pred_size() == 1 || node->succ_size() == 1);
158 pred->replaceSuccessor(succ);
159 succ->replacePredecessor(pred);
161 Nodes.RemoveNode(node);
163 node->~ExplodedNode();
179 if (shouldCollect(node))
199using GroupStorage = llvm::PointerUnion<ExplodedNode *, ExplodedNodeVector *>;
202 assert(!
V->isSink());
204 V->Succs.addNode(
this, G);
207void ExplodedNode::NodeGroup::replaceNode(
ExplodedNode *node) {
220 if (Storage.isNull()) {
234 V->push_back(Old, Ctx);
244unsigned ExplodedNode::NodeGroup::size()
const {
256ExplodedNode *
const *ExplodedNode::NodeGroup::begin()
const {
265 return Storage.getAddrOfPtr1();
268ExplodedNode *
const *ExplodedNode::NodeGroup::end()
const {
277 return Storage.getAddrOfPtr1() + 1;
289 return BEP->getBlock();
305 assert(ParentSF &&
"We don't start analysis from autosynthesized code");
309 assert(ParentSF &&
"We don't start analysis from autosynthesized code");
327 return SP->getStmt();
329 return BE->getSrc()->getTerminatorStmt();
331 return CE->getCallExpr();
333 return CEE->getCalleeStackFrame()->getCallSite();
335 return PIPP->getInitializer()->getInit();
337 return CEB->getReturnStmt();
339 return FEP->getStmt();
341 return LE->getTriggerStmt();
353 switch (S->getStmtClass()) {
354 case Stmt::ChooseExprClass:
355 case Stmt::BinaryConditionalOperatorClass:
356 case Stmt::ConditionalOperatorClass:
358 case Stmt::BinaryOperatorClass: {
360 if (Op == BO_LAnd || Op == BO_LOr)
395 llvm::FoldingSetNodeID profile;
396 void *InsertPos =
nullptr;
399 NodeTy*
V =
Nodes.FindNodeOrInsertPos(profile, InsertPos);
418 Nodes.InsertNode(
V, InsertPos);
420 if (IsNew) *IsNew =
true;
423 if (IsNew) *IsNew =
false;
433 new (
V)
NodeTy(L, State, Id, IsSink);
437std::unique_ptr<ExplodedGraph>
448 using Pass1Ty = llvm::DenseSet<const ExplodedNode *>;
453 Pass2Ty &Pass2 = ForwardMap ? *ForwardMap : Pass2Scratch;
458 for (
const auto Sink : Sinks)
463 while (!WL1.empty()) {
467 if (!Pass1.insert(N).second)
471 if (N->Preds.empty()) {
472 assert(N ==
getRoot() &&
"Found non-root node with no predecessors!");
478 WL1.append(N->Preds.begin(), N->Preds.end());
485 assert(WL2.size() == 1 &&
"There must be only one root!");
488 std::unique_ptr<ExplodedGraph> G = std::make_unique<ExplodedGraph>();
491 while (!WL2.empty()) {
494 auto [Place, Inserted] = Pass2.try_emplace(N);
504 Place->second = NewN;
507 if (InverseMap) (*InverseMap)[NewN] = N;
510 if (N->Preds.empty()) {
512 G->designateAsRoot(NewN);
521 Pass2Ty::iterator PI = Pass2.find(Pred);
522 if (PI == Pass2.end())
533 Pass2Ty::iterator PI = Pass2.find(Succ);
534 if (PI != Pass2.end()) {
540 if (Pass1.count(Succ))
static const StackFrame * findTopAutosynthesizedParentStackFrame(const StackFrame *SF)
llvm::PointerUnion< ExplodedNode *, ExplodedNodeVector * > GroupStorage
BumpVector< ExplodedNode * > ExplodedNodeVector
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
const CFGStmtMap * getCFGStmtMap()
bool isBodyAutosynthesized() const
Represents a single basic block in a source-level CFG.
const CFGBlock * getBlock(const Stmt *S) const
Returns the CFGBlock the specified Stmt* appears in.
Represents a point when we begin processing an inlined call.
Represents a point when we start the call exit sequence (for inlined call).
Represents a point when we finish the call exit sequence (for inlined call).
This represents one expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Represents a point when the lifetime of an automatic object ends.
bool isConsumedExpr(Expr *E) const
Represents a program point after a store evaluation.
Represents a program point just before an implicit call event.
Represents a point after we ran remove dead bindings BEFORE processing the given statement.
const ProgramPointTag * getTag() const
bool isPurgeKind()
Is this a program point corresponding to purge/removal of dead symbols and bindings.
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type.
const StackFrame * getStackFrame() const
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
It represents a stack frame of the call stack.
const ParentMap & getParentMap() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const Expr * getCallSite() const
const StackFrame * getParent() const
It might return null.
const Stmt * getStmt() const
Stmt - This represents one statement.
static bool isCallStmt(const Stmt *S)
Returns true if this is a statement is a function or method call of some kind.
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.
BumpVectorContext & getNodeAllocator()
unsigned ReclaimCounter
Counter to determine when to reclaim nodes.
NodeVector ChangedNodes
A list of recently allocated nodes that can potentially be recycled.
int64_t NumNodes
NumNodes - The number of nodes in the graph.
unsigned ReclaimNodeInterval
Determines how often nodes are reclaimed.
void reclaimRecentlyAllocatedNodes()
Reclaim "uninteresting" nodes created since the last time this method was called.
static bool isInterestingLValueExpr(const Expr *Ex)
Returns true if nodes for the given expression kind are always kept around.
llvm::BumpPtrAllocator & getAllocator()
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...
ExplodedNode * getRoot() const
Get the root node of the graph.
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.
llvm::FoldingSet< ExplodedNode > Nodes
Nodes - The nodes in the graph.
NodeVector FreeNodes
A list of nodes that can be reused.
const CFGBlock * getCFGBlock() const
const ProgramStateRef & getState() const
friend class ExplodedGraph
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
bool isTrivial() const
The node is trivial if it has only one successor, only one predecessor, it's predecessor has only one...
const Stmt * getPreviousStmtForDiagnostics() const
Find the statement that was executed immediately before this node.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...
ExplodedNode * getFirstSucc()
unsigned pred_size() const
static void Profile(llvm::FoldingSetNodeID &ID, const ProgramPoint &Loc, const ProgramStateRef &state, bool IsSink)
ExplodedNode(const ProgramPoint &loc, ProgramStateRef state, int64_t Id, bool IsSink)
const Stmt * getNextStmtForDiagnostics() const
Find the next statement that was executed on this node's execution path.
const Stmt * getCurrentOrPreviousStmtForDiagnostics() const
Find the statement that was executed at or immediately before this node.
ExplodedNode * getFirstPred()
unsigned succ_size() const
const StackFrame * getStackFrame() const
llvm::DenseMap< const ExplodedNode *, const ExplodedNode * > InterExplodedGraphMap
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
U cast(CodeGen::Address addr)