23#include "llvm/Support/Casting.h"
24#include "llvm/Support/Compiler.h"
25#include "llvm/Support/SaveAndRestore.h"
31#define DEBUG_TYPE "ExprEngine"
34 NumOfDynamicDispatchPathSplits,
35 "The # of times we split the path due to imprecise dynamic dispatch info");
40 "The # of times we reached inline count maximum");
47 assert(Entry->
empty());
71 Engine.enqueue(DstBegin);
77static std::pair<
const Stmt*,
79 const Stmt *S =
nullptr;
93 S = CEE->getCalleeStackFrame()->getCallSite();
100 std::optional<CallEnter> CE;
105 CE->getCalleeStackFrame() != CEE->getCalleeStackFrame());
113 if (CE->getCalleeStackFrame() == SF)
118 return std::make_pair(
nullptr,
nullptr);
123 return std::make_pair(S, Blk);
140 if (ExpectedTy == ActualTy)
169 const Stmt *LastSt =
nullptr;
172 if (!Blk || !LastSt) {
182 removeDead(Pred, Dst, dyn_cast<ReturnStmt>(LastSt), SF,
190 const Decl *StaticDecl =
Call->getDecl();
191 assert(RuntimeCallee);
202 "The call event is not a destructor call!");
206 auto ThisVal = DtorCall.getCXXThisVal();
208 if (
auto ThisElementRegion = dyn_cast<ElementRegion>(ThisVal.getAsRegion())) {
209 auto ArrayRegion = ThisElementRegion->getAsArrayOffset().getRegion();
210 auto ElementType = ThisElementRegion->getElementType();
215 if (!ElementCount.isConstant())
218 return ElementCount.getAsInteger()->getLimitedValue();
225 ProgramStateRef State,
const CXXConstructExpr *E,
const StackFrame *SF) {
227 assert(SF &&
"Stack frame must be provided!");
231 State = removePendingInitLoop(State, E, SF);
234 State = removeIndexOfElementToConstruct(State, E, SF);
238 State = removePendingArrayDestruction(State, SF);
265 isa_and_nonnull<ReturnStmt>(LastSt) ? Blk : &CEBNode->
getCFG().
getExit();
281 bool ShouldRepeatCall =
false;
283 if (
const auto *DtorDecl =
284 dyn_cast_or_null<CXXDestructorDecl>(
Call->getDecl())) {
286 ShouldRepeatCall = *Idx > 0;
288 auto ThisVal = svalBuilder.getCXXThis(DtorDecl->getParent(), CalleeSF);
289 State = State->killBinding(ThisVal);
295 if (
const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
299 if (RS->getRetValue())
300 V = State->getSVal(RS->getRetValue(), SF);
306 if (!ReturnedTy.
isNull()) {
312 State = State->BindExpr(CE, CallerSF,
V);
318 svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), CalleeSF);
320 ThisV = State->getSVal(ThisV.
castAs<
Loc>());
321 State = State->BindExpr(CCE, CallerSF, ThisV);
323 ShouldRepeatCall = shouldRepeatCtorCall(State, CCE, CallerSF);
326 if (
const auto *CNE = dyn_cast<CXXNewExpr>(CE)) {
332 SVal AllocV = State->getSVal(CNE, CallerSF);
333 AllocV = svalBuilder.evalCast(
338 addObjectUnderConstruction(State, CNE, CalleeSF->
getParent(), AllocV);
342 if (!ShouldRepeatCall) {
343 State = removeStateTraitsUsedForArrayEvaluation(
344 State, dyn_cast_or_null<CXXConstructExpr>(CE), CallerSF);
353 if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {
358 nullptr, &RetValBind)};
365 removeDead(BoundRetNode, CleanedNodes,
nullptr, CalleeSF,
369 CleanedNodes.
insert(CEBNode);
400 if (llvm::isa_and_nonnull<CXXNewExpr>(CE)) {
407 DstPostCall.
insert(DstPostPostCallCallback);
417 AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) {
426 unsigned Idx = CalleeSF->
getIndex() + (ShouldRepeatCall ? 0 : 1);
445 return Cfg->
size() >= AMgr.
options.MinCFGSizeTreatFunctionsAsLarge;
453void ExprEngine::examineStackFrames(
const Decl *D,
const StackFrame *SF,
454 bool &IsRecursive,
unsigned &StackDepth) {
471 AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
472 if (!isSmall(CalleeADC))
485 enum DynamicDispatchMode {
486 DynamicDispatchModeInlined = 1,
487 DynamicDispatchModeConservative
499 if (
Call.isForeign() && !isSecondPhaseCTU()) {
508 const bool BState = State->get<CTUDispatchBifurcation>();
513 ConservativeEvalState = State->set<CTUDispatchBifurcation>(
true);
514 conservativeEvalCall(
Call, Bldr, Pred, ConservativeEvalState);
516 conservativeEvalCall(
Call, Bldr, Pred, State);
529 const BlockDataRegion *BlockInvocationData =
nullptr;
533 assert(BlockInvocationData &&
534 "If we have the block definition we should have its region");
538 const Expr *CallE =
Call.getOriginExpr();
541 AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);
546 CallEnter Loc(CallE, CalleeSF, CallerSF);
550 State = State->enterStackFrame(
Call, CalleeSF);
553 if (ExplodedNode *N = G.getNode(Loc, State,
false, &isNew)) {
554 N->addPredecessor(Pred, G);
564 Engine.FunctionSummaries->bumpNumTimesInlined(D);
573 if (!isSecondPhaseCTU())
576 VisitedCallees->insert(D);
585 assert(ReplayState == CallE &&
"Backtracked to the wrong call.");
607 evalCall(dstCallEvaluated, N, *CallTemplate);
622 const Expr *E =
Call.getOriginExpr();
629 for (
unsigned CallI = 0, CallN =
Call.getNumArgs(); CallI != CallN; ++CallI) {
630 unsigned I =
Call.getASTArgumentIndex(CallI);
636 ->getParent() == SF);
637 State = finishObjectConstruction(State, {E, I}, SF);
651 if (CleanedState == State) {
656 const Expr *E =
Call.getOriginExpr();
657 const StackFrame *SF =
Call.getStackFrame();
658 static SimpleProgramPointTag
Tag(
"ExprEngine",
659 "Finish argument construction");
660 Dst.
insert(Engine.makeNode(PreStmt(E, SF, &Tag), CleanedState, Pred));
680 dstCallEvaluated, dstPreVisit, CallTemplate, *
this,
EvalCallOptions());
686 finishArgumentConstruction(dstArgumentCleanup, I, CallTemplate);
690 CallTemplate, *
this);
714 if (
const MemRegion *MR =
Call->getArgSVal(Arg).getAsRegion())
722 if (State != I->getState())
723 I = Engine.makeNode(I->getLocation(), State, I);
732 const Expr *E =
Call.getOriginExpr();
739 switch (Msg->getMethodFamily()) {
746 return State->BindExpr(E, SF, Msg->getReceiverSVal());
750 SVal ThisV =
C->getCXXThisVal();
751 ThisV = State->getSVal(ThisV.
castAs<
Loc>());
752 return State->BindExpr(E, SF, ThisV);
761 assert(RTC->getStmt() ==
Call.getOriginExpr());
765 RTC->getConstructionContext(), CallOpts);
776 State = State->invalidateRegions(TargetR, Elem, Count, SF,
786 const auto *CNE = dyn_cast<CXXNewExpr>(E);
787 if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
788 R = svalBuilder.getConjuredHeapSymbolVal(Elem, SF, E->
getType(), Count);
789 const MemRegion *MR = R.getAsRegion()->StripCasts();
793 if (
const Expr *SizeExpr = CNE->getArraySize().value_or(
nullptr)) {
794 ElementCount = State->getSVal(SizeExpr, SF);
796 ElementCount = svalBuilder.makeIntVal(1,
true);
802 svalBuilder.evalBinOp(State, BO_Mul, ElementCount, ElementSize,
803 svalBuilder.getArrayIndexType());
812 R = svalBuilder.conjureSymbolVal(Elem, SF, ResultTy, Count);
815 return State->BindExpr(E, SF, R);
830ExprEngine::CallInlinePolicy
835 switch (
Call.getKind()) {
843 return CIP_DisallowedAlways;
847 return CIP_DisallowedAlways;
857 if (llvm::isa_and_nonnull<NewAllocatedObjectConstructionContext>(CC) &&
858 !Opts.MayInlineCXXAllocator)
859 return CIP_DisallowedOnce;
862 if (!shouldInlineArrayConstruction(Pred->
getState(), CtorExpr, CallerSF))
863 return CIP_DisallowedOnce;
878 return CIP_DisallowedAlways;
884 !Opts.ShouldIncludeTemporaryDtorsInCFG)
885 return CIP_DisallowedOnce;
891 return CIP_DisallowedOnce;
896 return CIP_DisallowedOnce;
908 return CIP_DisallowedAlways;
918 return CIP_DisallowedOnce;
924 !Opts.MayInlineCXXTemporaryDtors)
925 return CIP_DisallowedOnce;
931 return CIP_DisallowedOnce;
937 if (Opts.MayInlineCXXAllocator)
941 return CIP_DisallowedAlways;
943 if (!Opts.MayInlineObjCMethod)
944 return CIP_DisallowedAlways;
947 return CIP_DisallowedAlways;
992 if (II->isStr(
"shared_ptr"))
1003bool ExprEngine::mayInlineDecl(AnalysisDeclContext *CalleeADC)
const {
1004 AnalyzerOptions &Opts = AMgr.getAnalyzerOptions();
1012 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeADC->
getDecl())) {
1014 if (!Opts.MayInlineTemplateFunctions)
1019 if (!Opts.MayInlineCXXStandardLibrary)
1026 if (!Opts.MayInlineCXXContainerMethods)
1027 if (!AMgr.isInCodeFile(FD->getLocation()))
1035 if (!Opts.MayInlineCXXSharedPtrDtor)
1043 const CFG *CalleeCFG = CalleeADC->
getCFG();
1048 if (isHuge(CalleeADC))
1053 if (!CalleeADC->
getAnalysis<RelaxedLiveVariables>())
1059bool ExprEngine::shouldInlineCall(
const CallEvent &
Call,
const Decl *D,
1066 AnalyzerOptions &Opts = AMgr.options;
1067 AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
1068 AnalysisDeclContext *CalleeADC = ADCMgr.
getContext(D);
1076 if (!AMgr.shouldInlineCall())
1080 std::optional<bool> MayInline = Engine.FunctionSummaries->mayInline(D);
1088 if (mayInlineDecl(CalleeADC)) {
1089 Engine.FunctionSummaries->markMayInline(D);
1091 Engine.FunctionSummaries->markShouldNotInline(D);
1100 CallInlinePolicy CIP = mayInlineCallKind(
Call, Pred, Opts, CallOpts);
1101 if (CIP != CIP_Allowed) {
1102 if (CIP == CIP_DisallowedAlways) {
1103 assert(!MayInline || *MayInline);
1104 Engine.FunctionSummaries->markShouldNotInline(D);
1110 bool IsRecursive =
false;
1111 unsigned StackDepth = 0;
1112 examineStackFrames(D, Pred->
getStackFrame(), IsRecursive, StackDepth);
1114 (!isSmall(CalleeADC) || IsRecursive))
1118 if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
1119 Opts.MaxTimesInlineLarge) &&
1120 isLarge(CalleeADC)) {
1121 NumReachedInlineCountMax++;
1125 if (HowToInline ==
Inline_Minimal && (!isSmall(CalleeADC) || IsRecursive))
1131bool ExprEngine::shouldInlineArrayConstruction(
const ProgramStateRef State,
1132 const CXXConstructExpr *CE,
1133 const StackFrame *SF) {
1138 if (
const auto *CAT = dyn_cast<ConstantArrayType>(CE->
getType())) {
1149 return shouldInlineArrayDestruction(ArrSize);
1154 return shouldInlineArrayDestruction(*Size);
1159bool ExprEngine::shouldInlineArrayDestruction(uint64_t Size) {
1161 uint64_t maxAllowedSize = AMgr.options.maxBlockVisitOnPath;
1164 return Size <= maxAllowedSize && Size > 0;
1168 const CXXConstructExpr *E,
1169 const StackFrame *SF) {
1177 if (
const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
1210 performTrivialCopy(Bldr, Pred,
Call);
1214 const Expr *E =
Call.getOriginExpr();
1217 if (InlinedFailedState) {
1219 State = InlinedFailedState;
1224 if (shouldInlineCall(
Call, D, Pred, CallOpts)) {
1236 conservativeEvalCall(
Call, Bldr, Pred, State);
1240 ctuBifurcate(
Call, D, Bldr, Pred, State);
1247 State = removeStateTraitsUsedForArrayEvaluation(
1248 State, dyn_cast_or_null<CXXConstructExpr>(E),
Call.getStackFrame());
1251 conservativeEvalCall(
Call, Bldr, Pred, State);
1254void ExprEngine::BifurcateCall(
const MemRegion *BifurReg,
1263 const unsigned *BState =
1264 State->get<DynamicDispatchBifurcationMap>(BifurReg);
1267 if (*BState == DynamicDispatchModeInlined)
1268 ctuBifurcate(
Call, D, Bldr, Pred, State);
1272 conservativeEvalCall(
Call, Bldr, Pred, State);
1279 State->set<DynamicDispatchBifurcationMap>(BifurReg,
1280 DynamicDispatchModeInlined);
1281 ctuBifurcate(
Call, D, Bldr, Pred, IState);
1284 State->set<DynamicDispatchBifurcationMap>(BifurReg,
1285 DynamicDispatchModeConservative);
1286 conservativeEvalCall(
Call, Bldr, Pred, NoIState);
1288 NumOfDynamicDispatchPathSplits++;
1300 ei = dstPreVisit.
end(); it != ei; ++it) {
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
#define STAT_COUNTER(VARNAME, DESC)
static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD)
Returns true if the given C++ class is a container or iterator.
static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call, const StackFrame *calleeCtx)
static std::pair< const Stmt *, const CFGBlock * > getLastStmt(const ExplodedNode *Node)
static bool isTrivialObjectAssignment(const CallEvent &Call)
static bool isCXXSharedPtrDtor(const FunctionDecl *FD)
Returns true if the given function is the destructor of a class named "shared_ptr".
static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD, StringRef Name)
Returns true if the given C++ class contains a member with the given name.
static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy, StoreManager &StoreMgr)
Adjusts a return value when the called function's return type does not match the caller's expression ...
static bool isContainerMethod(const ASTContext &Ctx, const FunctionDecl *FD)
Returns true if the given function refers to a method of a C++ container or iterator.
static unsigned getElementCountOfArrayBeingDestructed(const CallEvent &Call, const ProgramStateRef State, SValBuilder &SVB)
static ProgramStateRef getInlineFailedState(ProgramStateRef State, const Expr *CallE)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy.
a trap message and trap category.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
DeclarationNameTable DeclarationNames
const LangOptions & getLangOpts() const
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
AnalysisDeclContext * getContext(const Decl *D)
AnalysisDeclContext contains the context data for the function, method or block under analysis.
const Decl * getDecl() const
static bool isInStdNamespace(const Decl *D)
ASTContext & getASTContext() const
bool isBodyAutosynthesized() const
const StackFrame * getStackFrame(const StackFrame *ParentSF, const void *Data, const Expr *E, const CFGBlock *Blk, unsigned BlockCount, unsigned Index)
Obtain a context of the call stack using its parent context.
CFG::BuildOptions & getCFGBuildOptions()
Stores options for the analyzer from the command line.
bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const
Returns the option controlling which C++ member functions will be considered for inlining.
IPAKind getIPAMode() const
Returns the inter-procedural analysis mode.
CTUPhase1InliningKind getCTUPhase1Inlining() const
unsigned InlineMaxStackDepth
The inlining stack depth limit.
Represents a single basic block in a source-level CFG.
succ_iterator succ_begin()
unsigned succ_size() const
Represents C++ constructor call.
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
bool isLinear() const
Returns true if the CFG has no branches.
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
bool isAmbiguous(CanQualType BaseType) const
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
Represents a call to a C++ constructor.
CXXConstructionKind getConstructionKind() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Represents a C++ struct/union/class.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
bool hasMemberName(DeclarationName N) const
Determine whether this class has a member with the given name, possibly in a non-dependent base class...
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
Represents a point when we begin processing an inlined call.
const StackFrame * getCalleeStackFrame() const
const CFGBlock * getEntry() const
Returns the entry block in the CFG for the entered function.
Represents a point when we finish the call exit sequence (for inlined call).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
ConstructionContext's subclasses describe different ways of constructing an object in C++.
Decl - This represents one declaration (or definition), e.g.
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
This is a meta program point, which should be skipped by all the diagnostic reasoning etc.
This represents one expression.
Represents a function declaration or definition.
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a parameter to a function.
@ PostStmtPurgeDeadSymbolsKind
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...
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getCanonicalType() const
bool isConstQualified() const
Determine whether this type is const-qualified.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
It represents a stack frame of the call stack.
unsigned getIndex() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const Expr * getCallSite() const
const Decl * getDecl() const
const StackFrame * getParent() const
It might return null.
const CFGBlock * getCallSiteBlock() const
Stmt - This represents one statement.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isObjCObjectPointerType() const
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
AnalyzerOptions & options
Represents a call to a C++ constructor.
const CXXConstructorDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
const CXXConstructExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
Represents a non-static C++ member function call, no matter how it is written.
const FunctionDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
Manages the lifetime of CallEvent objects.
CallEventRef getCaller(const StackFrame *CalleeSF, ProgramStateRef State)
Gets an outside caller given a callee context.
CallEventRef getSimpleCall(const CallExpr *E, ProgramStateRef State, const StackFrame *SF, CFGBlock::ConstCFGElementRef ElemRef)
Represents an abstract call to a function or method along a particular path.
CallEventRef< T > cloneWithState(ProgramStateRef NewState) const
Returns a copy of this CallEvent, but using the given state.
static QualType getDeclaredResultType(const Decl *D)
Returns the result type of a function or method declaration.
static bool isVariadic(const Decl *D)
Returns true if the given decl is known to be variadic.
void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng)
Run checkers for pre-visiting function calls (including methods, constructors, destructors etc.
void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng, const EvalCallOptions &CallOpts)
Run checkers for evaluating a call.
void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting obj-c messages.
void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting Stmts.
void runCheckersForNewAllocator(const CXXAllocatorCall &Call, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, bool wasInlined=false)
Run checkers between C++ operator new and constructor calls.
void runCheckersForPreStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng)
Run checkers for pre-visiting Stmts.
void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting function calls (including methods, constructors, destructors etc.
WorkList * getCTUWorkList() const
WorkList * getWorkList() const
ExplodedNodeSet is a set of ExplodedNode * elements with the invariant that its elements cannot be nu...
void insert(ExplodedNode *N)
ImplTy::iterator iterator
const ProgramStateRef & getState() const
pred_iterator pred_begin()
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 ...
std::optional< T > getLocationAs() const &
ExplodedNode * getFirstPred()
const StackFrame * getStackFrame() const
ProgramStateManager & getStateManager()
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const StackFrame *SF, const Stmt *DiagnosticStmt=nullptr, ProgramPoint::Kind K=ProgramPoint::PreStmtPurgeDeadSymbolsKind)
Run the analyzer's garbage collection - remove dead symbols and bindings from the state.
void removeDeadOnEndOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst)
Remove dead bindings/symbols before exiting a function.
void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitReturnStmt - Transfer function logic for return statements.
void processCallEnter(CallEnter CE, ExplodedNode *Pred)
Generate the entry node of the callee.
void processCallExit(ExplodedNode *Pred)
Generate the sequence of nodes that simulate the call exit and the post visit for CallExpr.
CFGElement getCurrentCFGElement()
Return the CFG element corresponding to the worklist element that is currently being processed by Exp...
static std::optional< unsigned > getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const StackFrame *SF)
Retrieves which element is being constructed in a non-POD type array.
@ Inline_Minimal
Do minimal inlining of callees.
ProgramStateRef bindReturnValue(const CallEvent &Call, const StackFrame *SF, ProgramStateRef State)
Create a new state in which the call return value is binded to the call origin expression.
static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const StackFrame *SF)
Retrieves the size of the array in the pending ArrayInitLoopExpr.
void setCurrStackFrameAndBlock(const StackFrame *SF, const CFGBlock *B)
void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCall - Transfer function for function calls.
ASTContext & getContext() const
getContext - Return the ASTContext associated with this analysis.
StoreManager & getStoreManager()
void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call)
Evaluate a call, running pre- and post-call checkers and allowing checkers to be responsible for hand...
ConstCFGElementRef getCFGElementRef() const
static std::optional< unsigned > getPendingArrayDestruction(ProgramStateRef State, const StackFrame *SF)
Retrieves which element is being destructed in a non-POD type array.
ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, ArrayRef< std::pair< SVal, SVal > > LocAndVals, const StackFrame *SF, PointerEscapeKind Kind, const CallEvent *Call)
Call PointerEscape callback when a value escapes as a result of bind.
CheckerManager & getCheckerManager() const
static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const StackFrame *SF)
By looking at a certain item that may be potentially part of an object's ConstructionContext,...
void processBeginOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L)
Called by CoreEngine.
unsigned getNumVisitedCurrent() const
void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, const CallEvent &Call, const EvalCallOptions &CallOpts={})
Default implementation of call evaluation.
AnalysisManager & getAnalysisManager()
std::pair< ProgramStateRef, SVal > handleConstructionContext(const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx, const StackFrame *SF, const ConstructionContext *CC, EvalCallOptions &CallOpts, unsigned Idx=0)
A convenient wrapper around computeObjectUnderConstruction and updateObjectsUnderConstruction.
void resetCurrStackFrameAndBlock()
const CFGBlock * getCurrBlock() const
Get the 'current' CFGBlock corresponding to the current work item (elementary analysis step handled b...
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
This is the simplest builder which generates nodes in the ExplodedGraph.
void takeNodes(const ExplodedNodeSet &S)
ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false)
Generates a node in the ExplodedGraph.
Represents any expression that calls an Objective-C method.
CallEventManager & getCallEventManager()
Information about invalidation for a particular region/symbol.
@ TK_DoNotInvalidateSuperRegion
void setTrait(SymbolRef Sym, InvalidationKinds IK)
Defines the runtime definition of the called function.
const MemRegion * getDispatchRegion()
When other definitions are possible, returns the region whose runtime type determines the method defi...
bool mayHaveOtherDefinitions()
Check if the definition we have is precise.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
QualType getType(const ASTContext &) const
Try to get a reasonable type for the given value.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)
Evaluates a chain of derived-to-base casts through the path specified in Cast.
virtual void enqueue(const WorkListUnit &U)=0
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getRegion() const
Get the underlining region.
@ PSK_EscapeOutParameters
Escape for a new symbol that was generated into a region that the analyzer cannot follow during a con...
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR, DefinedOrUnknownSVal Extent)
Set the dynamic extent Extent of the region MR.
@ CE_CXXInheritedConstructor
DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
CFGBlock::ConstCFGElementRef ConstCFGElementRef
@ IPAK_DynamicDispatch
Enable inlining of dynamically dispatched methods.
@ IPAK_DynamicDispatchBifurcate
Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailabl...
@ CIMK_Destructors
Refers to destructors (implicit or explicit).
@ CIMK_MemberFunctions
Refers to regular member function and operator calls.
@ CIMK_Constructors
Refers to constructors (implicit or explicit).
U cast(CodeGen::Address addr)
Hints for figuring out if a call should be inlined during evalCall().
bool IsTemporaryLifetimeExtendedViaAggregate
This call is a constructor for a temporary that is lifetime-extended by binding it to a reference-typ...
bool IsTemporaryCtorOrDtor
This call is a constructor or a destructor of a temporary value.
bool IsArrayCtorOrDtor
This call is a constructor or a destructor for a single element within an array, a part of array cons...
bool IsCtorOrDtorWithImproperlyModeledTargetRegion
This call is a constructor or a destructor for which we do not currently compute the this-region corr...
Traits for storing the call processing policy inside GDM.