26 #include "llvm/ADT/DenseSet.h"
27 #include "llvm/ADT/FoldingSet.h"
28 #include "llvm/ADT/PointerUnion.h"
29 #include "llvm/ADT/SmallVector.h"
30 #include "llvm/Support/Casting.h"
35 using namespace clang;
53 return isa<DeclRefExpr, MemberExpr, ObjCIvarRefExpr, ArraySubscriptExpr>(Ex);
88 if (
node->pred_size() != 1 ||
node->succ_size() != 1)
103 return !progPoint.
getTag();
116 if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
158 assert(
node->pred_size() == 1 ||
node->succ_size() == 1);
161 pred->replaceSuccessor(succ);
162 succ->replacePredecessor(pred);
166 node->~ExplodedNode();
182 if (shouldCollect(
node))
202 using GroupStorage = llvm::PointerUnion<ExplodedNode *, ExplodedNodeVector *>;
205 assert(!
V->isSink());
207 V->Succs.addNode(
this, G);
237 V->push_back(Old, Ctx);
247 unsigned ExplodedNode::NodeGroup::size()
const {
259 ExplodedNode *
const *ExplodedNode::NodeGroup::begin()
const {
268 return Storage.getAddrOfPtr1();
271 ExplodedNode *
const *ExplodedNode::NodeGroup::end()
const {
280 return Storage.getAddrOfPtr1() + 1;
292 return BEP->getBlock();
310 assert(ParentLC &&
"We don't start analysis from autosynthesized code");
314 assert(ParentLC &&
"We don't start analysis from autosynthesized code");
333 return SP->getStmt();
335 return BE->getSrc()->getTerminatorStmt();
337 return CE->getCallExpr();
339 return CEE->getCalleeContext()->getCallSite();
341 return PIPP->getInitializer()->getInit();
343 return CEB->getReturnStmt();
345 return FEP->getStmt();
355 switch (S->getStmtClass()) {
356 case Stmt::ChooseExprClass:
357 case Stmt::BinaryConditionalOperatorClass:
358 case Stmt::ConditionalOperatorClass:
360 case Stmt::BinaryOperatorClass: {
362 if (Op == BO_LAnd || Op == BO_LOr)
397 llvm::FoldingSetNodeID profile;
398 void *InsertPos =
nullptr;
401 NodeTy*
V =
Nodes.FindNodeOrInsertPos(profile, InsertPos);
420 Nodes.InsertNode(
V, InsertPos);
422 if (IsNew) *IsNew =
true;
425 if (IsNew) *IsNew =
false;
439 std::unique_ptr<ExplodedGraph>
451 Pass2Ty &Pass2 = ForwardMap ? *ForwardMap : Pass2Scratch;
456 for (
const auto Sink : Sinks)
461 while (!WL1.empty()) {
465 if (!Pass1.insert(N).second)
469 if (N->Preds.empty()) {
475 WL1.append(N->Preds.begin(), N->Preds.end());
486 while (!WL2.empty()) {
490 if (Pass2.contains(N))
500 if (InverseMap) (*InverseMap)[NewN] = N;
503 if (N->Preds.empty())
512 Pass2Ty::iterator PI = Pass2.find(Pred);
513 if (PI == Pass2.end())
524 Pass2Ty::iterator PI = Pass2.find(Succ);
525 if (PI != Pass2.end()) {
526 const_cast<ExplodedNode *
>(PI->second)->addPredecessor(NewN, *G);
531 if (Pass1.count(Succ))
llvm::PointerUnion< ExplodedNode *, ExplodedNodeVector * > GroupStorage
BumpVector< ExplodedNode * > ExplodedNodeVector
static const LocationContext * findTopAutosynthesizedParentContext(const LocationContext *LC)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
CFGStmtMap * getCFGStmtMap()
bool isBodyAutosynthesized() const
Represents a single basic block in a source-level CFG.
CFGBlock * getBlock(Stmt *S)
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.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const LocationContext * getParent() const
It might return null.
const ParentMap & getParentMap() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
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.
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type.
const ProgramPointTag * getTag() const
const LocationContext * getLocationContext() const
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.
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.
BumpVectorContext & getNodeAllocator()
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.
std::unique_ptr< ExplodedGraph > MakeEmptyGraph() const
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 * 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.
llvm::BumpPtrAllocator & getAllocator()
NodeVector FreeNodes
A list of nodes that can be reused.
ExplodedNode * getFirstPred()
const CFGBlock * getCFGBlock() const
ExplodedNode * getFirstSucc()
const ProgramStateRef & getState() const
const LocationContext * getLocationContext() const
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 ...
unsigned pred_size() const
static void Profile(llvm::FoldingSetNodeID &ID, const ProgramPoint &Loc, const ProgramStateRef &state, 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.
unsigned succ_size() const
llvm::DenseMap< const ExplodedNode *, const ExplodedNode * > InterExplodedGraphMap
The JSON file list parser is used to communicate input to InstallAPI.