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());
67 Engine.enqueue(DstBegin);
73static std::pair<
const Stmt*,
75 const Stmt *S =
nullptr;
89 S = CEE->getCalleeStackFrame()->getCallSite();
96 std::optional<CallEnter> CE;
101 CE->getCalleeStackFrame() != CEE->getCalleeStackFrame());
109 if (CE->getCalleeStackFrame() == SF)
114 return std::make_pair(
nullptr,
nullptr);
119 return std::make_pair(S, Blk);
136 if (ExpectedTy == ActualTy)
165 const Stmt *LastSt =
nullptr;
168 if (!Blk || !LastSt) {
178 removeDead(Pred, Dst, dyn_cast<ReturnStmt>(LastSt), SF,
186 const Decl *StaticDecl =
Call->getDecl();
187 assert(RuntimeCallee);
198 "The call event is not a destructor call!");
202 auto ThisVal = DtorCall.getCXXThisVal();
204 if (
auto ThisElementRegion = dyn_cast<ElementRegion>(ThisVal.getAsRegion())) {
205 auto ArrayRegion = ThisElementRegion->getAsArrayOffset().getRegion();
206 auto ElementType = ThisElementRegion->getElementType();
211 if (!ElementCount.isConstant())
214 return ElementCount.getAsInteger()->getLimitedValue();
221 ProgramStateRef State,
const CXXConstructExpr *E,
const StackFrame *SF) {
223 assert(SF &&
"Stack frame must be provided!");
227 State = removePendingInitLoop(State, E, SF);
230 State = removeIndexOfElementToConstruct(State, E, SF);
234 State = removePendingArrayDestruction(State, SF);
261 isa_and_nonnull<ReturnStmt>(LastSt) ? Blk : &CEBNode->
getCFG().
getExit();
277 bool ShouldRepeatCall =
false;
279 if (
const auto *DtorDecl =
280 dyn_cast_or_null<CXXDestructorDecl>(
Call->getDecl())) {
282 ShouldRepeatCall = *Idx > 0;
284 auto ThisVal = svalBuilder.getCXXThis(DtorDecl->getParent(), CalleeSF);
285 State = State->killBinding(ThisVal);
291 if (
const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
295 if (RS->getRetValue())
296 V = State->getSVal(RS->getRetValue(), SF);
302 if (!ReturnedTy.
isNull()) {
308 State = State->BindExpr(CE, CallerSF,
V);
314 svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), CalleeSF);
316 ThisV = State->getSVal(ThisV.
castAs<
Loc>());
317 State = State->BindExpr(CCE, CallerSF, ThisV);
319 ShouldRepeatCall = shouldRepeatCtorCall(State, CCE, CallerSF);
322 if (
const auto *CNE = dyn_cast<CXXNewExpr>(CE)) {
328 SVal AllocV = State->getSVal(CNE, CallerSF);
329 AllocV = svalBuilder.evalCast(
334 addObjectUnderConstruction(State, CNE, CalleeSF->
getParent(), AllocV);
338 if (!ShouldRepeatCall) {
339 State = removeStateTraitsUsedForArrayEvaluation(
340 State, dyn_cast_or_null<CXXConstructExpr>(CE), CallerSF);
349 if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {
354 nullptr, &RetValBind)};
361 removeDead(BoundRetNode, CleanedNodes,
nullptr, CalleeSF,
365 CleanedNodes.
insert(CEBNode);
396 if (llvm::isa_and_nonnull<CXXNewExpr>(CE)) {
403 DstPostCall.
insert(DstPostPostCallCallback);
413 AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) {
422 unsigned Idx = CalleeSF->
getIndex() + (ShouldRepeatCall ? 0 : 1);
441 return Cfg->
size() >= AMgr.
options.MinCFGSizeTreatFunctionsAsLarge;
449void ExprEngine::examineStackFrames(
450 const Decl *D, llvm::iterator_range<StackFrame::parent_iterator> Frames,
451 bool &IsRecursive,
unsigned &StackDepth) {
455 for (
const StackFrame &Frame : Frames) {
456 const Decl *DI = Frame.getDecl();
467 AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
468 if (!isSmall(CalleeADC))
480 enum DynamicDispatchMode {
481 DynamicDispatchModeInlined = 1,
482 DynamicDispatchModeConservative
493 if (
Call.isForeign() && !isSecondPhaseCTU()) {
502 const bool BState = State->get<CTUDispatchBifurcation>();
507 State = State->set<CTUDispatchBifurcation>(
true);
509 Dst.
insert(conservativeEvalCall(
Call, Pred, State));
521 const BlockDataRegion *BlockInvocationData =
nullptr;
525 assert(BlockInvocationData &&
526 "If we have the block definition we should have its region");
530 const Expr *CallE =
Call.getOriginExpr();
533 AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);
538 CallEnter Loc(CallE, CalleeSF, CallerSF);
542 State = State->enterStackFrame(
Call, CalleeSF);
544 if (ExplodedNode *N = Engine.makeNode(Loc, State, Pred))
548 Engine.FunctionSummaries->bumpNumTimesInlined(D);
557 if (!isSecondPhaseCTU())
560 VisitedCallees->insert(D);
569 assert(ReplayState == CallE &&
"Backtracked to the wrong call.");
577 if (
const auto *OCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
581 const Decl *Callee = OCE->getCalleeDecl();
582 if (
const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
583 if (MD->isImplicitObjectMemberFunction()) {
587 createTemporaryRegionIfNeeded(State, SF, OCE->getArg(0));
588 if (NewState != State) {
590 Pred = Engine.makeNode(PS, NewState, Pred);
611 evalCall(dstCallEvaluated, N, *CallTemplate);
626 const Expr *E =
Call.getOriginExpr();
633 for (
unsigned CallI = 0, CallN =
Call.getNumArgs(); CallI != CallN; ++CallI) {
634 unsigned I =
Call.getASTArgumentIndex(CallI);
640 ->getParent() == SF);
641 State = finishObjectConstruction(State, {E, I}, SF);
655 if (CleanedState == State) {
660 const Expr *E =
Call.getOriginExpr();
661 const StackFrame *SF =
Call.getStackFrame();
662 static SimpleProgramPointTag
Tag(
"ExprEngine",
663 "Finish argument construction");
664 Dst.
insert(Engine.makeNode(PreStmt(E, SF, &Tag), CleanedState, Pred));
684 dstCallEvaluated, dstPreVisit, CallTemplate, *
this,
EvalCallOptions());
690 finishArgumentConstruction(dstArgumentCleanup, I, CallTemplate);
694 CallTemplate, *
this);
718 if (
const MemRegion *MR =
Call->getArgSVal(Arg).getAsRegion())
726 if (State != I->getState())
727 I = Engine.makeNode(I->getLocation(), State, I);
736 const Expr *E =
Call.getOriginExpr();
743 switch (Msg->getMethodFamily()) {
750 return State->BindExpr(E, SF, Msg->getReceiverSVal());
754 SVal ThisV =
C->getCXXThisVal();
755 ThisV = State->getSVal(ThisV.
castAs<
Loc>());
756 return State->BindExpr(E, SF, ThisV);
765 assert(RTC->getStmt() ==
Call.getOriginExpr());
769 RTC->getConstructionContext(), CallOpts);
780 State = State->invalidateRegions(TargetR, Elem, Count, SF,
790 const auto *CNE = dyn_cast<CXXNewExpr>(E);
791 if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
792 R = svalBuilder.getConjuredHeapSymbolVal(Elem, SF, E->
getType(), Count);
793 const MemRegion *MR = R.getAsRegion()->StripCasts();
797 if (
const Expr *SizeExpr = CNE->getArraySize().value_or(
nullptr)) {
798 ElementCount = State->getSVal(SizeExpr, SF);
800 ElementCount = svalBuilder.makeIntVal(1,
true);
806 svalBuilder.evalBinOp(State, BO_Mul, ElementCount, ElementSize,
807 svalBuilder.getArrayIndexType());
816 R = svalBuilder.conjureSymbolVal(Elem, SF, ResultTy, Count);
819 return State->BindExpr(E, SF, R);
832 return Engine.
makeNode(
Call.getProgramPoint(
false, &PT), State, Pred);
835ExprEngine::CallInlinePolicy
840 switch (
Call.getKind()) {
848 return CIP_DisallowedAlways;
852 return CIP_DisallowedAlways;
862 if (llvm::isa_and_nonnull<NewAllocatedObjectConstructionContext>(CC) &&
863 !Opts.MayInlineCXXAllocator)
864 return CIP_DisallowedOnce;
867 if (!shouldInlineArrayConstruction(Pred->
getState(), CtorExpr, CallerSF))
868 return CIP_DisallowedOnce;
883 return CIP_DisallowedAlways;
889 !Opts.ShouldIncludeTemporaryDtorsInCFG)
890 return CIP_DisallowedOnce;
896 return CIP_DisallowedOnce;
901 return CIP_DisallowedOnce;
913 return CIP_DisallowedAlways;
923 return CIP_DisallowedOnce;
929 !Opts.MayInlineCXXTemporaryDtors)
930 return CIP_DisallowedOnce;
936 return CIP_DisallowedOnce;
942 if (Opts.MayInlineCXXAllocator)
946 return CIP_DisallowedAlways;
948 if (!Opts.MayInlineObjCMethod)
949 return CIP_DisallowedAlways;
952 return CIP_DisallowedAlways;
997 if (II->isStr(
"shared_ptr"))
1008bool ExprEngine::mayInlineDecl(AnalysisDeclContext *CalleeADC)
const {
1009 AnalyzerOptions &Opts = AMgr.getAnalyzerOptions();
1017 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeADC->
getDecl())) {
1019 if (!Opts.MayInlineTemplateFunctions)
1024 if (!Opts.MayInlineCXXStandardLibrary)
1031 if (!Opts.MayInlineCXXContainerMethods)
1032 if (!AMgr.isInCodeFile(FD->getLocation()))
1040 if (!Opts.MayInlineCXXSharedPtrDtor)
1048 const CFG *CalleeCFG = CalleeADC->
getCFG();
1053 if (isHuge(CalleeADC))
1058 if (!CalleeADC->
getAnalysis<RelaxedLiveVariables>())
1064bool ExprEngine::shouldInlineCall(
const CallEvent &
Call,
const Decl *D,
1071 AnalyzerOptions &Opts = AMgr.options;
1072 AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
1073 AnalysisDeclContext *CalleeADC = ADCMgr.
getContext(D);
1081 if (!AMgr.shouldInlineCall())
1085 std::optional<bool> MayInline = Engine.FunctionSummaries->mayInline(D);
1093 if (mayInlineDecl(CalleeADC)) {
1094 Engine.FunctionSummaries->markMayInline(D);
1096 Engine.FunctionSummaries->markShouldNotInline(D);
1105 CallInlinePolicy CIP = mayInlineCallKind(
Call, Pred, Opts, CallOpts);
1106 if (CIP != CIP_Allowed) {
1107 if (CIP == CIP_DisallowedAlways) {
1108 assert(!MayInline || *MayInline);
1109 Engine.FunctionSummaries->markShouldNotInline(D);
1115 bool IsRecursive =
false;
1116 unsigned StackDepth = 0;
1117 examineStackFrames(D, Pred->
stackframes(), IsRecursive, StackDepth);
1119 (!isSmall(CalleeADC) || IsRecursive))
1123 if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
1124 Opts.MaxTimesInlineLarge) &&
1125 isLarge(CalleeADC)) {
1126 NumReachedInlineCountMax++;
1130 if (HowToInline ==
Inline_Minimal && (!isSmall(CalleeADC) || IsRecursive))
1136bool ExprEngine::shouldInlineArrayConstruction(
const ProgramStateRef State,
1137 const CXXConstructExpr *CE,
1138 const StackFrame *SF) {
1143 if (
const auto *CAT = dyn_cast<ConstantArrayType>(CE->
getType())) {
1154 return shouldInlineArrayDestruction(ArrSize);
1159 return shouldInlineArrayDestruction(*Size);
1164bool ExprEngine::shouldInlineArrayDestruction(uint64_t Size) {
1166 uint64_t maxAllowedSize = AMgr.options.maxBlockVisitOnPath;
1169 return Size <= maxAllowedSize && Size > 0;
1173 const CXXConstructExpr *E,
1174 const StackFrame *SF) {
1182 if (
const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
1215 performTrivialCopy(Dst, Pred,
Call);
1219 const Expr *E =
Call.getOriginExpr();
1222 if (InlinedFailedState) {
1224 State = InlinedFailedState;
1229 if (shouldInlineCall(
Call, D, Pred, CallOpts)) {
1241 Dst.
insert(conservativeEvalCall(
Call, Pred, State));
1245 ctuBifurcate(
Call, D, Dst, Pred, State);
1252 State = removeStateTraitsUsedForArrayEvaluation(
1253 State, dyn_cast_or_null<CXXConstructExpr>(E),
Call.getStackFrame());
1256 Dst.
insert(conservativeEvalCall(
Call, Pred, State));
1259void ExprEngine::dynDispatchBifurcate(
const MemRegion *BifurReg,
1269 const unsigned *BState =
1270 State->get<DynamicDispatchBifurcationMap>(BifurReg);
1273 if (*BState == DynamicDispatchModeInlined)
1274 ctuBifurcate(
Call, D, Dst, Pred, State);
1278 Dst.
insert(conservativeEvalCall(
Call, Pred, State));
1285 State->set<DynamicDispatchBifurcationMap>(BifurReg,
1286 DynamicDispatchModeInlined);
1287 ctuBifurcate(
Call, D, Dst, Pred, IState);
1290 State->set<DynamicDispatchBifurcationMap>(BifurReg,
1291 DynamicDispatchModeConservative);
1292 Dst.
insert(conservativeEvalCall(
Call, Pred, NoIState));
1294 NumOfDynamicDispatchPathSplits++;
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
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) 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
ExplodedNode * makeNode(const ProgramPoint &Loc, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false) const
ExplodedNodeSet is a set of ExplodedNode * elements with the invariant that its elements cannot be nu...
void insert(ExplodedNode *N)
const ProgramStateRef & getState() const
pred_iterator pred_begin()
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
std::optional< T > getLocationAs() const &
llvm::iterator_range< StackFrame::parent_iterator > stackframes() const
Iterates over the current stack frame and all of its ancestors.
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...
void defaultEvalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call, const EvalCallOptions &CallOpts={})
Default implementation of call evaluation.
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.
std::pair< ProgramStateRef, SVal > handleConstructionContext(const Expr *E, ProgramStateRef State, const StackFrame *SF, const ConstructionContext *CC, EvalCallOptions &CallOpts, unsigned Idx=0)
A convenient wrapper around computeObjectUnderConstruction and updateObjectsUnderConstruction.
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
AnalysisManager & getAnalysisManager()
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
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.
Top level wrappers for InstallAPI frontend operations.
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.