64#include "llvm/ADT/APSInt.h"
65#include "llvm/ADT/DenseMap.h"
66#include "llvm/ADT/ImmutableMap.h"
67#include "llvm/ADT/ImmutableSet.h"
68#include "llvm/ADT/STLExtras.h"
69#include "llvm/ADT/SmallVector.h"
70#include "llvm/Support/Casting.h"
71#include "llvm/Support/Compiler.h"
72#include "llvm/Support/DOTGraphTraits.h"
73#include "llvm/Support/ErrorHandling.h"
74#include "llvm/Support/GraphWriter.h"
75#include "llvm/Support/IOSandbox.h"
76#include "llvm/Support/TimeProfiler.h"
77#include "llvm/Support/raw_ostream.h"
90#define DEBUG_TYPE "ExprEngine"
93 "The # of times RemoveDeadBindings is called");
95 NumMaxBlockCountReached,
96 "The # of aborted paths due to reaching the maximum block count in "
97 "a top level function");
99 NumMaxBlockCountReachedInInlined,
100 "The # of aborted paths due to reaching the maximum block count in "
101 "an inlined function");
103 "The # of times we re-evaluated a call without inlining");
124class ConstructedObjectKey {
125 using ConstructedObjectKeyImpl =
126 std::pair<ConstructionContextItem, const StackFrame *>;
127 const ConstructedObjectKeyImpl Impl;
134 const ConstructionContextItem &getItem()
const {
return Impl.first; }
135 const StackFrame *getStackFrame()
const {
return Impl.second; }
137 ASTContext &getASTContext()
const {
138 return getStackFrame()->getDecl()->getASTContext();
141 void printJson(llvm::raw_ostream &Out, PrinterHelper *Helper,
142 PrintingPolicy &PP)
const {
143 const Stmt *S = getItem().getStmtOrNull();
144 const CXXCtorInitializer *I =
nullptr;
146 I = getItem().getCXXCtorInitializer();
149 Out <<
"\"stmt_id\": " << S->
getID(getASTContext());
151 Out <<
"\"init_id\": " << I->
getID(getASTContext());
154 Out <<
", \"kind\": \"" << getItem().getKindAsString()
155 <<
"\", \"argument_index\": ";
158 Out << getItem().getIndex();
163 Out <<
", \"pretty\": ";
172 void Profile(llvm::FoldingSetNodeID &ID)
const {
174 ID.AddPointer(Impl.second);
177 bool operator==(
const ConstructedObjectKey &RHS)
const {
178 return Impl == RHS.Impl;
181 bool operator<(
const ConstructedObjectKey &RHS)
const {
182 return Impl < RHS.Impl;
187typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
198typedef llvm::ImmutableMap<
199 std::pair<const CXXConstructExpr *, const StackFrame *>,
unsigned>
200 IndexOfElementToConstructMap;
202 IndexOfElementToConstructMap)
207typedef llvm::ImmutableMap<
208 std::pair<const CXXConstructExpr *, const StackFrame *>,
unsigned>
212typedef llvm::ImmutableMap<const StackFrame *, unsigned>
221static const char* TagProviderName =
"ExprEngine";
226 : CTU(CTU), IsCTUEnabled(mgr.getAnalyzerOptions().IsNaiveCTUEnabled),
228 Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.
getGraph()),
229 StateMgr(
getContext(), mgr.getStoreManagerCreator(),
230 mgr.getConstraintManagerCreator(), G.getAllocator(), this),
232 svalBuilder(StateMgr.
getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
233 BR(mgr, *this), VisitedCallees(VisitedCalleesIn),
234 HowToInline(HowToInlineIn) {
235 unsigned TrimInterval = mgr.
options.GraphTrimInterval;
236 if (TrimInterval != 0) {
238 G.enableNodeReclamation(TrimInterval);
254 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
258 if (!II || !(II->
getName() ==
"main" && FD->getNumParams() > 0))
263 const auto *BT = dyn_cast<BuiltinType>(T);
264 if (!BT || !BT->isInteger())
267 const MemRegion *R = state->getRegion(PD, InitSF);
273 svalBuilder.makeZeroVal(T),
274 svalBuilder.getConditionType());
276 std::optional<DefinedOrUnknownSVal> Constraint =
289 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
293 const MemRegion *R = state->getRegion(SelfD, InitSF);
296 if (std::optional<Loc> LV =
V.getAs<
Loc>()) {
298 state = state->assume(*LV,
true);
299 assert(state &&
"'self' cannot be null");
303 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
304 if (MD->isImplicitObjectMemberFunction()) {
311 SVal V = state->getSVal(L);
312 if (std::optional<Loc> LV =
V.getAs<
Loc>()) {
313 state = state->assume(*LV,
true);
314 assert(state &&
"'this' cannot be null");
326 const SubRegion **OutRegionWithAdjustments) {
332 SVal InitValWithAdjustments = State->getSVal(InitWithAdjustments, SF);
337 if (OutRegionWithAdjustments)
338 *OutRegionWithAdjustments =
nullptr;
341 Result = InitWithAdjustments;
345 assert(!
isa<Loc>(InitValWithAdjustments) ||
347 Result->getType()->isMemberPointerType());
350 ProgramStateManager &StateMgr = State->getStateManager();
351 MemRegionManager &MRMgr = StateMgr.getRegionManager();
352 StoreManager &StoreMgr = StateMgr.getStoreManager();
375 SmallVector<const Expr *, 2> CommaLHSs;
376 SmallVector<SubobjectAdjustment, 2> Adjustments;
379 CommaLHSs, Adjustments);
386 const TypedValueRegion *TR =
nullptr;
387 if (
const auto *MT = dyn_cast<MaterializeTemporaryExpr>(
Result)) {
389 State = finishObjectConstruction(State, MT, SF);
390 State = State->BindExpr(
Result, SF, *
V);
392 }
else if (
const ValueDecl *VD = MT->getExtendingDecl()) {
398 TR = MRMgr.getCXXStaticLifetimeExtendedObjectRegion(
Init, VD);
400 TR = MRMgr.getCXXLifetimeExtendedObjectRegion(
Init, VD, SF);
404 TR = MRMgr.getCXXTempObjectRegion(
Init, SF);
407 TR = MRMgr.getCXXTempObjectRegion(
Init, SF);
410 SVal Reg = loc::MemRegionVal(TR);
414 for (
const SubobjectAdjustment &Adj : llvm::reverse(Adjustments)) {
426 nullptr,
nullptr,
nullptr);
439 SVal InitVal = State->getSVal(
Init, SF);
443 State = State->bindLoc(BaseReg.
castAs<Loc>(), InitVal, SF,
false);
447 if (InitValWithAdjustments.
isUnknown()) {
455 State->bindLoc(Reg.
castAs<Loc>(), InitValWithAdjustments, SF,
false);
457 State = State->bindLoc(BaseReg.
castAs<Loc>(), InitVal, SF,
false);
463 if (
Result->isGLValue()) {
464 State = State->BindExpr(
Result, SF, Reg);
466 State = State->BindExpr(
Result, SF, InitValWithAdjustments);
472 if (OutRegionWithAdjustments)
479 const CXXConstructExpr *E,
480 const StackFrame *SF,
unsigned Idx) {
481 auto Key = std::make_pair(E, SF);
483 assert(!State->contains<IndexOfElementToConstruct>(Key) || Idx > 0);
485 return State->set<IndexOfElementToConstruct>(Key, Idx);
488std::optional<unsigned>
491 const unsigned *
V = State->get<PendingInitLoop>({E, SF});
492 return V ? std::make_optional(*
V) : std::nullopt;
498 auto Key = std::make_pair(E, SF);
500 assert(E && State->contains<PendingInitLoop>(Key));
501 return State->remove<PendingInitLoop>(Key);
508 auto Key = std::make_pair(E, SF);
510 assert(!State->contains<PendingInitLoop>(Key) && Size > 0);
512 return State->set<PendingInitLoop>(Key, Size);
517 const unsigned *
V = State->get<IndexOfElementToConstruct>({E, SF});
518 return V ? std::make_optional(*
V) : std::nullopt;
523 auto Key = std::make_pair(E, SF);
525 assert(E && State->contains<IndexOfElementToConstruct>(Key));
526 return State->remove<IndexOfElementToConstruct>(Key);
529std::optional<unsigned>
532 assert(SF &&
"StackFrame shouldn't be null!");
534 const unsigned *
V = State->get<PendingArrayDestruction>(SF);
535 return V ? std::make_optional(*
V) : std::nullopt;
541 assert(SF &&
"StackFrame shouldn't be null!");
542 return State->set<PendingArrayDestruction>(SF, Idx);
548 assert(SF &&
"StackFrame shouldn't be null!");
549 assert(State->contains<PendingArrayDestruction>(SF));
550 return State->remove<PendingArrayDestruction>(SF);
557 ConstructedObjectKey Key(Item, SF);
561 if (
auto DS = dyn_cast_or_null<DeclStmt>(Item.
getStmtOrNull())) {
562 if (
auto VD = dyn_cast_or_null<VarDecl>(DS->getSingleDecl()))
563 Init = VD->getInit();
566 if (
auto LE = dyn_cast_or_null<LambdaExpr>(Item.
getStmtOrNull()))
575 if (
const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(
Init))
584 assert((!State->get<ObjectsUnderConstruction>(Key) ||
585 Key.getItem().getKind() ==
587 State->contains<IndexOfElementToConstruct>(
588 {dyn_cast_or_null<CXXConstructExpr>(Init), SF})) &&
589 "The object is already marked as `UnderConstruction`, when it's not "
591 return State->set<ObjectsUnderConstruction>(Key,
V);
598 ConstructedObjectKey Key(Item, SF);
599 const SVal *
V = State->get<ObjectsUnderConstruction>(Key);
600 return V ? std::make_optional(*
V) : std::nullopt;
607 ConstructedObjectKey Key(Item, SF);
608 assert(State->contains<ObjectsUnderConstruction>(Key));
609 return State->remove<ObjectsUnderConstruction>(Key);
615 ConstructedObjectKey Key({BTE,
true}, SF);
618 return State->set<ObjectsUnderConstruction>(Key,
UnknownVal());
623 const CXXBindTemporaryExpr *BTE,
624 const StackFrame *SF) {
625 ConstructedObjectKey Key({BTE,
true}, SF);
626 assert(State->contains<ObjectsUnderConstruction>(Key));
627 return State->remove<ObjectsUnderConstruction>(Key);
631 const CXXBindTemporaryExpr *BTE,
632 const StackFrame *SF) {
633 ConstructedObjectKey Key({BTE,
true}, SF);
634 return State->contains<ObjectsUnderConstruction>(Key);
638 const StackFrame *FromSF,
639 const StackFrame *ToSF) {
640 const StackFrame *SF = FromSF;
642 assert(SF &&
"ToSF must be a parent of FromSF!");
643 for (
auto I : State->get<ObjectsUnderConstruction>())
644 if (I.first.getStackFrame() == SF)
659 SVal cond,
bool assumption) {
668 state, invalidated, Explicits, Regions, SF,
Call);
674 unsigned int Space = 0,
bool IsDot =
false) {
679 bool HasItem =
false;
682 const ConstructedObjectKey *LastKey =
nullptr;
683 for (
const auto &I : State->get<ObjectsUnderConstruction>()) {
684 const ConstructedObjectKey &Key = I.first;
685 if (Key.getStackFrame() != SF)
696 for (
const auto &I : State->get<ObjectsUnderConstruction>()) {
697 const ConstructedObjectKey &Key = I.first;
699 if (Key.getStackFrame() != SF)
702 Indent(Out, Space, IsDot) <<
"{ ";
703 Key.printJson(Out,
nullptr, PP);
704 Out <<
", \"value\": \"" <<
Value <<
"\" }";
712 Indent(Out, --Space, IsDot) <<
']';
720 const StackFrame *SF,
unsigned int Space = 0,
bool IsDot =
false) {
721 using KeyT = std::pair<const Expr *, const StackFrame *>;
727 bool HasItem =
false;
731 for (
const auto &I : State->get<IndexOfElementToConstruct>()) {
732 const KeyT &Key = I.first;
733 if (Key.second != SF)
744 for (
const auto &I : State->get<IndexOfElementToConstruct>()) {
745 const KeyT &Key = I.first;
746 unsigned Value = I.second;
747 if (Key.second != SF)
750 Indent(Out, Space, IsDot) <<
"{ ";
753 const Expr *E = Key.first;
754 Out <<
"\"stmt_id\": " << E->
getID(Context);
757 Out <<
", \"kind\": null";
760 Out <<
", \"pretty\": ";
766 Out <<
", \"value\": \"Current index: " <<
Value - 1 <<
"\" }";
774 Indent(Out, --Space, IsDot) <<
']';
782 unsigned int Space = 0,
783 bool IsDot =
false) {
784 using KeyT = std::pair<const CXXConstructExpr *, const StackFrame *>;
790 bool HasItem =
false;
794 for (
const auto &I : State->get<PendingInitLoop>()) {
795 const KeyT &Key = I.first;
796 if (Key.second != SF)
807 for (
const auto &I : State->get<PendingInitLoop>()) {
808 const KeyT &Key = I.first;
809 unsigned Value = I.second;
810 if (Key.second != SF)
813 Indent(Out, Space, IsDot) <<
"{ ";
816 Out <<
"\"stmt_id\": " << E->
getID(Context);
818 Out <<
", \"kind\": null";
819 Out <<
", \"pretty\": ";
825 Out <<
", \"value\": \"Flattened size: " <<
Value <<
"\"}";
833 Indent(Out, --Space, IsDot) <<
']';
842 unsigned int Space = 0,
bool IsDot =
false) {
846 bool HasItem =
false;
849 KeyT LastKey =
nullptr;
850 for (
const auto &I : State->get<PendingArrayDestruction>()) {
851 const KeyT &Key = I.first;
863 for (
const auto &I : State->get<PendingArrayDestruction>()) {
864 const KeyT &Key = I.first;
868 Indent(Out, Space, IsDot) <<
"{ ";
870 Out <<
"\"stmt_id\": null";
871 Out <<
", \"kind\": null";
872 Out <<
", \"pretty\": \"Current index: \"";
873 Out <<
", \"value\": \"" << I.second <<
"\" }";
881 Indent(Out, --Space, IsDot) <<
']';
895template <
typename Trait,
typename Printer,
typename... Args>
898 const char *NL,
unsigned int Space,
bool IsDot,
899 const char *jsonPropertyName, Printer printer, Args &&...args) {
903 unsigned int,
bool, Args &&...);
907 static_assert(std::is_function_v<std::remove_pointer_t<Printer>>,
908 "Printer is not a function!");
909 static_assert(std::is_convertible_v<Printer, RequiredType>,
910 "Printer doesn't have the required type!");
912 if (SF && !State->get<Trait>().isEmpty()) {
913 Indent(Out, Space, IsDot) <<
'\"' << jsonPropertyName <<
"\": ";
917 printer(Out, State, NL, SF, Space, IsDot, std::forward<Args>(args)...);
921 Indent(Out, Space, IsDot) <<
"]," << NL;
927 unsigned int Space,
bool IsDot)
const {
930 Out, State, SF, NL, Space, IsDot,
"constructing_objects",
933 Out, State, SF, NL, Space, IsDot,
"index_of_element",
936 Out, State, SF, NL, Space, IsDot,
"pending_init_loops",
939 Out, State, SF, NL, Space, IsDot,
"pending_destructors",
954 currStmtIdx = StmtIdx;
1019 llvm::TimeTraceScope TimeScope(
"ExprEngine::removeDead");
1022 &&
"PostStmt is not generally supported by the SymbolReaper yet");
1023 assert(SF &&
"Must pass the current (or expiring) StackFrame");
1025 if (!DiagnosticStmt) {
1026 DiagnosticStmt = ReferenceStmt;
1027 assert(DiagnosticStmt &&
"Required for clearing a StackFrame");
1030 NumRemoveDeadBindings++;
1036 if (!ReferenceStmt) {
1038 "Use PostStmtPurgeDeadSymbolsKind for clearing a StackFrame");
1044 for (
auto I : CleanedState->get<ObjectsUnderConstruction>()) {
1045 if (
SymbolRef Sym = I.second.getAsSymbol())
1047 if (
const MemRegion *MR = I.second.getAsRegion())
1056 CleanedState = StateMgr.removeDeadBindingsFromEnvironmentAndStore(
1057 CleanedState, SF, SymReaper);
1064 DiagnosticStmt, *
this, K);
1074 for (
const auto I : CheckedSet) {
1081 assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->
getState()) &&
1082 "Checkers are not allowed to modify the Environment as a part of "
1083 "checkDeadSymbols processing.");
1084 assert(StateMgr.haveEqualStores(CheckerState, Pred->
getState()) &&
1085 "Checkers are not allowed to modify the Store as a part of "
1086 "checkDeadSymbols processing.");
1091 StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
1094 Out.insert(Engine.makeNode(L, CleanedCheckerSt, I));
1105 G.reclaimRecentlyAllocatedNodes();
1109 "Error evaluating statement");
1116 CleanedStates.
insert(Pred);
1120 for (
const auto I : CleanedStates) {
1123 Visit(currStmt, I, DstI);
1128 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1134 "Error evaluating end of the loop");
1137 if(AMgr.options.ShouldUnrollLoops)
1143 Engine.enqueueStmtNode(N,
getCurrBlock(), currStmtIdx);
1150 "Error evaluating end of a lifetime");
1156 Engine.enqueueStmtNodes(Dst, currBldrCtx->getBlock(), currStmtIdx);
1167 "Error evaluating initializer");
1173 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(
decl, SF));
1185 State = finishObjectConstruction(State, BMI, SF);
1187 Tmp.
insert(Engine.makeNode(PS, State, Pred));
1195 FieldLoc = State->getLValue(BMI->
getMember(), thisVal);
1199 if (
Init->getType()->isArrayType()) {
1203 while ((ASE = dyn_cast<ArraySubscriptExpr>(
Init)))
1206 InitVal = State->getSVal(
Init, SF);
1215 InitVal = State->getSVal(BMI->
getInit(), SF);
1219 evalBind(Tmp,
Init, Pred, FieldLoc, InitVal,
true, &PP);
1227 SVal InitVal = State->getSVal(
Init, SF);
1228 evalBind(Tmp,
Init, Pred, BaseLoc, InitVal,
true);
1243 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1246std::pair<ProgramStateRef, uint64_t>
1247ExprEngine::prepareStateForArrayDestruction(
const ProgramStateRef State,
1251 SVal *ElementCountVal) {
1252 assert(Region !=
nullptr &&
"Not-null region expected");
1255 while (
const auto *NTy = dyn_cast<ArrayType>(Ty))
1256 Ty = NTy->getElementType().getDesugaredType(
getContext());
1260 if (ElementCountVal)
1261 *ElementCountVal = ElementCount;
1269 if (!ElementCount.isConstant())
1272 Idx = ElementCount.getAsInteger()->getLimitedValue();
1280 return {setPendingArrayDestruction(State, SF, Idx), Idx};
1303 llvm_unreachable(
"Unexpected dtor kind.");
1307 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1318 if (Opts.MayInlineCXXAllocator)
1326 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1332 const auto *DtorDecl = Dtor.getDestructorDecl(
getContext());
1343 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
1358 std::tie(state, Idx) = prepareStateForArrayDestruction(
1359 state, Region, varType, SF, &ElementCount);
1361 if (ElementCount.isConstant()) {
1362 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1363 assert(ArrayLength &&
1364 "An automatic dtor for a 0 length array shouldn't be triggered!");
1369 "ExprEngine",
"Skipping automatic 0 length array destruction, "
1370 "which shouldn't be in the CFG.");
1373 Engine.makeNode(PP, Pred->
getState(), Pred,
true);
1385 "Prepare for object destruction");
1388 Pred = Engine.makeNode(PP, state, Pred);
1394 false, Pred, Dst, CallOpts);
1405 SVal ArgVal = State->getSVal(Arg, SF);
1409 if (State->isNull(ArgVal).isConstrainedTrue()) {
1419 auto getDtorDecl = [](
const QualType &DTy) {
1431 while (
const auto *AT =
getContext().getAsArrayType(DTy))
1432 DTy = AT->getElementType();
1436 std::tie(State, Idx) =
1437 prepareStateForArrayDestruction(State, ArgR, DTy, SF, &ElementCount);
1441 if (ElementCount.isConstant() &&
1442 ElementCount.getAsInteger()->getLimitedValue() == 0) {
1445 "ExprEngine",
"Skipping 0 length array delete destruction");
1452 ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
1458 "Prepare for object destruction");
1461 Pred = Engine.makeNode(PP, State, Pred);
1485 true, Pred, Dst, CallOpts);
1498 Loc ThisLoc = State->getSVal(ThisStorageLoc).
castAs<
Loc>();
1499 SVal FieldVal = State->getLValue(
Member, ThisLoc);
1504 std::tie(State, Idx) = prepareStateForArrayDestruction(
1505 State, FieldVal.getAsRegion(), T, SF, &ElementCount);
1507 if (ElementCount.isConstant()) {
1508 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1509 assert(ArrayLength &&
1510 "A member dtor for a 0 length array shouldn't be triggered!");
1515 "ExprEngine",
"Skipping member 0 length array destruction, which "
1516 "shouldn't be in the CFG.");
1519 Engine.makeNode(PP, Pred->
getState(), Pred,
true);
1530 "Prepare for object destruction");
1533 Pred = Engine.makeNode(PP, State, Pred);
1539 false, Pred, Dst, CallOpts);
1554 State = finishObjectConstruction(State, BTE, SF);
1555 MR =
V->getAsRegion();
1560 if (isDestructorElided(State, BTE, SF)) {
1561 State = cleanupElidedDestructor(State, BTE, SF);
1564 Dst.
insert(Engine.makeNode(PP, State, Pred));
1568 ExplodedNode *CleanPred = Engine.makePostStmtNode(BTE, State, Pred);
1569 if (!CleanPred || CleanPred->
isSink()) {
1599 T = AT->getElementType();
1610 false, CleanPred, Dst, CallOpts);
1622 if (
const CFGBlock *DstBlock = Obj ? DstT : DstF) {
1624 Dst.
insert(Engine.makeNode(BE, State, Pred));
1642 const StackFrame *SF = Node->getStackFrame();
1648 State = addObjectUnderConstruction(State, BTE, SF,
UnknownVal());
1650 Dst.
insert(Engine.makePostStmtNode(BTE, State, Node));
1658 class CollectReachableSymbolsCallback final :
public SymbolVisitor {
1663 : Symbols(Symbols) {}
1667 bool VisitSymbol(
SymbolRef Sym)
override {
1668 Symbols.insert(Sym);
1673 CollectReachableSymbolsCallback CallBack(Symbols);
1675 State->scanReachableSymbols(
V, CallBack);
1678 State, CallBack.getSymbols(),
Call, K,
nullptr);
1690 case Stmt::CXXDependentScopeMemberExprClass:
1691 case Stmt::CXXReflectExprClass:
1692 case Stmt::CXXTryStmtClass:
1693 case Stmt::CXXTypeidExprClass:
1694 case Stmt::CXXUuidofExprClass:
1695 case Stmt::CXXFoldExprClass:
1696 case Stmt::MSPropertyRefExprClass:
1697 case Stmt::MSPropertySubscriptExprClass:
1698 case Stmt::CXXUnresolvedConstructExprClass:
1699 case Stmt::DependentScopeDeclRefExprClass:
1700 case Stmt::ArrayTypeTraitExprClass:
1701 case Stmt::ExpressionTraitExprClass:
1702 case Stmt::UnresolvedLookupExprClass:
1703 case Stmt::UnresolvedMemberExprClass:
1704 case Stmt::RecoveryExprClass:
1705 case Stmt::CXXNoexceptExprClass:
1706 case Stmt::PackExpansionExprClass:
1707 case Stmt::PackIndexingExprClass:
1708 case Stmt::SubstNonTypeTemplateParmPackExprClass:
1709 case Stmt::FunctionParmPackExprClass:
1710 case Stmt::CoroutineBodyStmtClass:
1711 case Stmt::CoawaitExprClass:
1712 case Stmt::DependentCoawaitExprClass:
1713 case Stmt::CoreturnStmtClass:
1714 case Stmt::CoyieldExprClass:
1715 case Stmt::SEHTryStmtClass:
1716 case Stmt::SEHExceptStmtClass:
1717 case Stmt::SEHLeaveStmtClass:
1718 case Stmt::SEHFinallyStmtClass:
1719 case Stmt::OMPCanonicalLoopClass:
1720 case Stmt::OMPParallelDirectiveClass:
1721 case Stmt::OMPSimdDirectiveClass:
1722 case Stmt::OMPForDirectiveClass:
1723 case Stmt::OMPForSimdDirectiveClass:
1724 case Stmt::OMPSectionsDirectiveClass:
1725 case Stmt::OMPSectionDirectiveClass:
1726 case Stmt::OMPScopeDirectiveClass:
1727 case Stmt::OMPSingleDirectiveClass:
1728 case Stmt::OMPMasterDirectiveClass:
1729 case Stmt::OMPCriticalDirectiveClass:
1730 case Stmt::OMPParallelForDirectiveClass:
1731 case Stmt::OMPParallelForSimdDirectiveClass:
1732 case Stmt::OMPParallelSectionsDirectiveClass:
1733 case Stmt::OMPParallelMasterDirectiveClass:
1734 case Stmt::OMPParallelMaskedDirectiveClass:
1735 case Stmt::OMPTaskDirectiveClass:
1736 case Stmt::OMPTaskyieldDirectiveClass:
1737 case Stmt::OMPBarrierDirectiveClass:
1738 case Stmt::OMPTaskwaitDirectiveClass:
1739 case Stmt::OMPErrorDirectiveClass:
1740 case Stmt::OMPTaskgroupDirectiveClass:
1741 case Stmt::OMPFlushDirectiveClass:
1742 case Stmt::OMPDepobjDirectiveClass:
1743 case Stmt::OMPScanDirectiveClass:
1744 case Stmt::OMPOrderedDirectiveClass:
1745 case Stmt::OMPAtomicDirectiveClass:
1746 case Stmt::OMPAssumeDirectiveClass:
1747 case Stmt::OMPTargetDirectiveClass:
1748 case Stmt::OMPTargetDataDirectiveClass:
1749 case Stmt::OMPTargetEnterDataDirectiveClass:
1750 case Stmt::OMPTargetExitDataDirectiveClass:
1751 case Stmt::OMPTargetParallelDirectiveClass:
1752 case Stmt::OMPTargetParallelForDirectiveClass:
1753 case Stmt::OMPTargetUpdateDirectiveClass:
1754 case Stmt::OMPTeamsDirectiveClass:
1755 case Stmt::OMPCancellationPointDirectiveClass:
1756 case Stmt::OMPCancelDirectiveClass:
1757 case Stmt::OMPTaskLoopDirectiveClass:
1758 case Stmt::OMPTaskLoopSimdDirectiveClass:
1759 case Stmt::OMPMasterTaskLoopDirectiveClass:
1760 case Stmt::OMPMaskedTaskLoopDirectiveClass:
1761 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1762 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1763 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1764 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1765 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1766 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1767 case Stmt::OMPDistributeDirectiveClass:
1768 case Stmt::OMPDistributeParallelForDirectiveClass:
1769 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1770 case Stmt::OMPDistributeSimdDirectiveClass:
1771 case Stmt::OMPTargetParallelForSimdDirectiveClass:
1772 case Stmt::OMPTargetSimdDirectiveClass:
1773 case Stmt::OMPTeamsDistributeDirectiveClass:
1774 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1775 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1776 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1777 case Stmt::OMPTargetTeamsDirectiveClass:
1778 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1779 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1780 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1781 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1782 case Stmt::OMPReverseDirectiveClass:
1783 case Stmt::OMPStripeDirectiveClass:
1784 case Stmt::OMPTileDirectiveClass:
1785 case Stmt::OMPInterchangeDirectiveClass:
1786 case Stmt::OMPSplitDirectiveClass:
1787 case Stmt::OMPFuseDirectiveClass:
1788 case Stmt::OMPInteropDirectiveClass:
1789 case Stmt::OMPDispatchDirectiveClass:
1790 case Stmt::OMPMaskedDirectiveClass:
1791 case Stmt::OMPGenericLoopDirectiveClass:
1792 case Stmt::OMPTeamsGenericLoopDirectiveClass:
1793 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
1794 case Stmt::OMPParallelGenericLoopDirectiveClass:
1795 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1796 case Stmt::CapturedStmtClass:
1797 case Stmt::SYCLKernelCallStmtClass:
1798 case Stmt::UnresolvedSYCLKernelCallStmtClass:
1799 case Stmt::OpenACCComputeConstructClass:
1800 case Stmt::OpenACCLoopConstructClass:
1801 case Stmt::OpenACCCombinedConstructClass:
1802 case Stmt::OpenACCDataConstructClass:
1803 case Stmt::OpenACCEnterDataConstructClass:
1804 case Stmt::OpenACCExitDataConstructClass:
1805 case Stmt::OpenACCHostDataConstructClass:
1806 case Stmt::OpenACCWaitConstructClass:
1807 case Stmt::OpenACCCacheConstructClass:
1808 case Stmt::OpenACCInitConstructClass:
1809 case Stmt::OpenACCShutdownConstructClass:
1810 case Stmt::OpenACCSetConstructClass:
1811 case Stmt::OpenACCUpdateConstructClass:
1812 case Stmt::OpenACCAtomicConstructClass:
1813 case Stmt::OMPUnrollDirectiveClass:
1814 case Stmt::OMPMetaDirectiveClass:
1815 case Stmt::HLSLOutArgExprClass: {
1822 case Stmt::ParenExprClass:
1823 llvm_unreachable(
"ParenExprs already handled.");
1824 case Stmt::GenericSelectionExprClass:
1825 llvm_unreachable(
"GenericSelectionExprs already handled.");
1828 case Stmt::BreakStmtClass:
1829 case Stmt::CaseStmtClass:
1830 case Stmt::CompoundStmtClass:
1831 case Stmt::ContinueStmtClass:
1832 case Stmt::CXXForRangeStmtClass:
1833 case Stmt::DefaultStmtClass:
1834 case Stmt::DoStmtClass:
1835 case Stmt::ForStmtClass:
1836 case Stmt::GotoStmtClass:
1837 case Stmt::IfStmtClass:
1838 case Stmt::IndirectGotoStmtClass:
1839 case Stmt::LabelStmtClass:
1841 case Stmt::NullStmtClass:
1842 case Stmt::SwitchStmtClass:
1843 case Stmt::WhileStmtClass:
1844 case Stmt::DeferStmtClass:
1845 case Expr::MSDependentExistsStmtClass:
1846 llvm_unreachable(
"Stmt should not be in analyzer evaluation loop");
1847 case Stmt::ImplicitValueInitExprClass:
1851 llvm_unreachable(
"Should be pruned from CFG");
1853 case Stmt::ObjCSubscriptRefExprClass:
1854 case Stmt::ObjCPropertyRefExprClass:
1855 llvm_unreachable(
"These are handled by PseudoObjectExpr");
1857 case Stmt::GNUNullExprClass: {
1859 SVal Val = svalBuilder.makeIntValWithWidth(
getContext().VoidPtrTy, 0);
1864 case Stmt::ObjCAtSynchronizedStmtClass:
1868 case Expr::ConstantExprClass:
1869 case Stmt::ExprWithCleanupsClass:
1874 case Stmt::CXXBindTemporaryExprClass: {
1883 case Stmt::ArrayInitLoopExprClass:
1887 case Stmt::DesignatedInitExprClass:
1888 case Stmt::DesignatedInitUpdateExprClass:
1889 case Stmt::ArrayInitIndexExprClass:
1890 case Stmt::ExtVectorElementExprClass:
1891 case Stmt::MatrixElementExprClass:
1892 case Stmt::ImaginaryLiteralClass:
1893 case Stmt::ObjCAtCatchStmtClass:
1894 case Stmt::ObjCAtFinallyStmtClass:
1895 case Stmt::ObjCAtTryStmtClass:
1896 case Stmt::ObjCAutoreleasePoolStmtClass:
1897 case Stmt::ObjCEncodeExprClass:
1898 case Stmt::ObjCIsaExprClass:
1899 case Stmt::ObjCProtocolExprClass:
1900 case Stmt::ObjCSelectorExprClass:
1901 case Stmt::ParenListExprClass:
1902 case Stmt::ShuffleVectorExprClass:
1903 case Stmt::ConvertVectorExprClass:
1904 case Stmt::VAArgExprClass:
1905 case Stmt::CUDAKernelCallExprClass:
1906 case Stmt::OpaqueValueExprClass:
1907 case Stmt::AsTypeExprClass:
1908 case Stmt::ConceptSpecializationExprClass:
1909 case Stmt::CXXRewrittenBinaryOperatorClass:
1910 case Stmt::RequiresExprClass:
1911 case Stmt::EmbedExprClass:
1916 case Stmt::PredefinedExprClass:
1917 case Stmt::AddrLabelExprClass:
1918 case Stmt::IntegerLiteralClass:
1919 case Stmt::FixedPointLiteralClass:
1920 case Stmt::CharacterLiteralClass:
1921 case Stmt::CXXScalarValueInitExprClass:
1922 case Stmt::CXXBoolLiteralExprClass:
1923 case Stmt::ObjCBoolLiteralExprClass:
1924 case Stmt::ObjCAvailabilityCheckExprClass:
1925 case Stmt::FloatingLiteralClass:
1926 case Stmt::NoInitExprClass:
1927 case Stmt::SizeOfPackExprClass:
1928 case Stmt::StringLiteralClass:
1929 case Stmt::SourceLocExprClass:
1930 case Stmt::ObjCStringLiteralClass:
1931 case Stmt::CXXPseudoDestructorExprClass:
1932 case Stmt::SubstNonTypeTemplateParmExprClass:
1933 case Stmt::CXXNullPtrLiteralExprClass:
1934 case Stmt::ArraySectionExprClass:
1935 case Stmt::OMPArrayShapingExprClass:
1936 case Stmt::OMPIteratorExprClass:
1937 case Stmt::SYCLUniqueStableNameExprClass:
1938 case Stmt::OpenACCAsteriskSizeExprClass:
1939 case Stmt::TypeTraitExprClass: {
1946 case Stmt::AttributedStmtClass: {
1951 case Stmt::CXXDefaultArgExprClass:
1952 case Stmt::CXXDefaultInitExprClass: {
1959 if (
const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
1960 ArgE = DefE->getExpr();
1961 else if (
const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
1962 ArgE = DefE->getExpr();
1964 llvm_unreachable(
"unknown constant wrapper kind");
1966 bool IsTemporary =
false;
1967 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
1968 ArgE = MTE->getSubExpr();
1972 std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
1977 for (
const auto I : PreVisit) {
1979 State = State->BindExpr(
cast<Expr>(S), SF, *ConstantVal);
1981 State = createTemporaryRegionIfNeeded(State, SF,
cast<Expr>(S),
1983 Tmp.
insert(Engine.makePostStmtNode(S, State, I));
1991 case Stmt::CXXStdInitializerListExprClass:
1992 case Expr::ObjCArrayLiteralClass:
1993 case Expr::ObjCDictionaryLiteralClass:
1994 case Expr::ObjCBoxedExprClass: {
2001 QualType resultType = Ex->getType();
2003 for (
const auto N : preVisit) {
2005 SVal result = svalBuilder.conjureSymbolVal(
2015 for (
auto Child : Ex->children()) {
2017 const auto *ChildExpr = dyn_cast<Expr>(Child);
2018 SVal Val = ChildExpr ? State->getSVal(ChildExpr, SF) :
UnknownVal();
2022 Tmp.
insert(Engine.makePostStmtNode(S, State, N));
2029 case Stmt::ArraySubscriptExprClass:
2033 case Stmt::MatrixSingleSubscriptExprClass:
2035 "Support for MatrixSingleSubscriptExprClass is not implemented.");
2038 case Stmt::MatrixSubscriptExprClass:
2039 llvm_unreachable(
"Support for MatrixSubscriptExpr is not implemented.");
2042 case Stmt::GCCAsmStmtClass: {
2052 case Stmt::MSAsmStmtClass:
2056 case Stmt::BlockExprClass:
2060 case Stmt::LambdaExprClass:
2061 if (AMgr.options.ShouldInlineLambdas) {
2070 case Stmt::BinaryOperatorClass: {
2072 if (B->isLogicalOp()) {
2075 }
else if (B->getOpcode() == BO_Comma) {
2078 Dst.
insert(Engine.makeNodeWithBinding(Pred, B, Val));
2082 if (AMgr.options.ShouldEagerlyAssume &&
2083 (B->isRelationalOp() || B->isEqualityOp())) {
2094 case Stmt::CXXOperatorCallExprClass:
2095 case Stmt::CallExprClass:
2096 case Stmt::CXXMemberCallExprClass:
2097 case Stmt::UserDefinedLiteralClass:
2101 case Stmt::CXXCatchStmtClass:
2105 case Stmt::CXXTemporaryObjectExprClass:
2106 case Stmt::CXXConstructExprClass:
2110 case Stmt::CXXInheritedCtorInitExprClass:
2115 case Stmt::CXXNewExprClass: {
2121 for (
const auto i : PreVisit)
2128 case Stmt::CXXDeleteExprClass: {
2135 for (
const auto i : PostVisit)
2143 case Stmt::ChooseExprClass: {
2149 case Stmt::CompoundAssignOperatorClass:
2153 case Stmt::CompoundLiteralExprClass:
2157 case Stmt::BinaryConditionalOperatorClass:
2158 case Stmt::ConditionalOperatorClass: {
2164 case Stmt::CXXThisExprClass:
2168 case Stmt::DeclRefExprClass: {
2174 case Stmt::DeclStmtClass:
2178 case Stmt::ImplicitCastExprClass:
2179 case Stmt::CStyleCastExprClass:
2180 case Stmt::CXXStaticCastExprClass:
2181 case Stmt::CXXDynamicCastExprClass:
2182 case Stmt::CXXReinterpretCastExprClass:
2183 case Stmt::CXXConstCastExprClass:
2184 case Stmt::CXXFunctionalCastExprClass:
2185 case Stmt::BuiltinBitCastExprClass:
2186 case Stmt::ObjCBridgedCastExprClass:
2187 case Stmt::CXXAddrspaceCastExprClass: {
2197 case Expr::MaterializeTemporaryExprClass: {
2202 for (
const auto i : dstPrevisit)
2208 case Stmt::InitListExprClass: {
2214 case Expr::CXXParenListInitExprClass: {
2221 case Stmt::MemberExprClass:
2225 case Stmt::AtomicExprClass:
2229 case Stmt::ObjCIvarRefExprClass:
2233 case Stmt::ObjCForCollectionStmtClass:
2237 case Stmt::ObjCMessageExprClass:
2241 case Stmt::ObjCAtThrowStmtClass:
2242 case Stmt::CXXThrowExprClass:
2245 Engine.makePostStmtNode(S, Pred->
getState(), Pred,
true);
2248 case Stmt::ReturnStmtClass:
2252 case Stmt::OffsetOfExprClass: {
2257 for (
const auto Node : PreVisit)
2264 case Stmt::UnaryExprOrTypeTraitExprClass:
2269 case Stmt::StmtExprClass: {
2272 if (SE->getSubStmt()->body_empty()) {
2275 &&
"Empty statement expression must have void type.");
2276 }
else if (
const auto *LastExpr =
2277 dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
2279 Pred = Engine.makeNodeWithBinding(Pred, SE, Val);
2285 case Stmt::UnaryOperatorClass: {
2287 if (AMgr.options.ShouldEagerlyAssume && (
U->getOpcode() == UO_LNot)) {
2297 case Stmt::PseudoObjectExprClass: {
2300 if (
const Expr *
Result = PE->getResultExpr())
2302 Dst.
insert(Engine.makeNodeWithBinding(Pred, PE,
V));
2306 case Expr::ObjCIndirectCopyRestoreExprClass: {
2311 const Expr *E = OIE->getSubExpr();
2313 Dst.
insert(Engine.makeNodeWithBinding(Pred, OIE,
V));
2322 assert(CalleeSF && CallerSF);
2329 BeforeProcessingCall = N;
2344 if (SP->getStmt() == CE)
2349 if (!BeforeProcessingCall)
2385 NumTimesRetriedWithoutInlining++;
2399 if(AMgr.options.ShouldUnrollLoops) {
2400 unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
2404 Pred, maxBlockVisitOnPath);
2405 if (NewState != Pred->
getState()) {
2406 ExplodedNode *UpdatedNode = Builder.generateNode(BE, NewState, Pred);
2420 if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
2421 AMgr.options.ShouldWidenLoops) {
2423 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
2437 Builder.generateNode(BE, WidenedState, Pred);
2442 if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
2446 Builder.generateSink(TaggedLoc, Pred->
getState(), Pred);
2459 Engine.FunctionSummaries->markShouldNotInline(SF->
getDecl());
2465 if ((!AMgr.options.NoRetryExhausted && replayWithoutInlining(Pred, SF)))
2467 NumMaxBlockCountReachedInInlined++;
2469 NumMaxBlockCountReached++;
2472 Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
2479 llvm::PrettyStackTraceFormat CrashInfo(
2480 "Processing block entrance B%d -> B%d",
2498 const auto *Ex = dyn_cast<Expr>(
Condition);
2503 bool bitsInit =
false;
2505 while (
const auto *CE = dyn_cast<CastExpr>(Ex)) {
2508 if (!T->isIntegralOrEnumerationType())
2512 if (!bitsInit || newBits < bits) {
2517 Ex = CE->getSubExpr();
2523 if (!bitsInit || !T->isIntegralOrEnumerationType() ||
2527 return state->getSVal(Ex, SF);
2533 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2534 if (!BO || !BO->isLogicalOp()) {
2537 Condition = BO->getRHS()->IgnoreParens();
2559 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2562 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2563 if (!BO || !BO->isLogicalOp())
2567 "Other kinds of branches are handled separately!");
2578 std::optional<CFGStmt> CS = Elem.getAs<
CFGStmt>();
2581 const Stmt *LastStmt = CS->getStmt();
2585 llvm_unreachable(
"could not resolve condition");
2589 std::pair<const ObjCForCollectionStmt *, const StackFrame *>;
2595 bool HasMoreIteraton) {
2596 assert(!State->contains<ObjCForHasMoreIterations>({O, SF}));
2597 return State->set<ObjCForHasMoreIterations>({O, SF}, HasMoreIteraton);
2603 assert(State->contains<ObjCForHasMoreIterations>({O, SF}));
2604 return State->remove<ObjCForHasMoreIterations>({O, SF});
2610 assert(State->contains<ObjCForHasMoreIterations>({O, SF}));
2611 return *State->get<ObjCForHasMoreIterations>({O, SF});
2617static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
2620 if (
const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(ConditionStmt)) {
2621 bool HasMoreIteraton =
2628 if (HasMoreIteraton)
2629 return std::pair<ProgramStateRef, ProgramStateRef>{State,
nullptr};
2631 return std::pair<ProgramStateRef, ProgramStateRef>{
nullptr, State};
2634 const auto *ConditionExpr = dyn_cast<Expr>(ConditionStmt);
2635 assert(ConditionExpr &&
"The condition must be an Expr from here!");
2639 if (
X.isUnknownOrUndef()) {
2641 if (
const auto *Ex = dyn_cast<Expr>(ConditionExpr)) {
2642 if (Ex->getType()->isIntegralOrEnumerationType()) {
2649 N->
getState()->getStateManager().getContext());
2659 if (
X.isUnknownOrUndef())
2660 return std::nullopt;
2665 return State->assume(
V);
2671 std::optional<unsigned> IterationsCompletedInLoop) {
2673 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2689 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2695 "Error evaluating branch");
2701 if (CheckersOutSet.
empty())
2709 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2711 if (StTrue && StFalse)
2722 (StTrue && StFalse) ||
2741 bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;
2742 bool SkipTrueBranch = BothFeasible && CompletedTwoIterations;
2748 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops) {
2751 Dst.
insert(Engine.makeNode(BE, StTrue, PredN));
2753 }
else if (!AMgr.options.InlineFunctionsWithAmbiguousLoops) {
2770 Engine.FunctionSummaries->markShouldNotInline(SF->
getDecl());
2788 bool BeforeFirstIteration = IterationsCompletedInLoop == std::optional{0};
2789 bool SkipFalseBranch = BothFeasible && BeforeFirstIteration &&
2790 AMgr.options.ShouldAssumeAtLeastOneIteration;
2791 if (!SkipFalseBranch && DstF) {
2793 Dst.
insert(Engine.makeNode(BE, StFalse, PredN));
2802 llvm::ImmutableSet<const VarDecl *>)
2811 bool InitHasRun = State->contains<InitializedGlobalsSet>(VD);
2813 State = State->add<InitializedGlobalsSet>(VD);
2815 if (
const CFGBlock *DstBlock = InitHasRun ? DstT : DstF) {
2849 Dst.
insert(Engine.makeNode(BE, State, Pred));
2867 State = finishArgumentConstruction(
2882 while (SF != ToSF) {
2883 assert(SF &&
"ToSF must be a parent of FromSF!");
2884 for (
auto I : State->get<ObjectsUnderConstruction>())
2885 if (I.first.getStackFrame() == SF) {
2889 assert(I.first.getItem().getKind() ==
2891 I.first.getItem().getKind() ==
2893 State = State->remove<ObjectsUnderConstruction>(I.first);
2901 Pred = Engine.makeNode(Pred->
getLocation(), State, Pred);
2918 for (
const auto I : AfterRemovedDead)
2924 Engine.enqueueEndOfFunction(Dst, RS);
2938 assert(SwitchBlock->
succ_size() &&
"Switch must have at least one successor");
2944 llvm::iterator_range<CFGBlock::const_succ_reverse_iterator> CaseBlocks(
2951 Condition->IgnoreParens(), CheckersOutSet, Pred, *
this);
2961 std::optional<NonLoc> CondNL = CondV.
getAs<
NonLoc>();
2963 for (
const CFGBlock *CaseBlock : CaseBlocks) {
2972 assert(V1.getBitWidth() ==
2978 V2 = E->EvaluateKnownConstInt(ACtx);
2985 std::tie(StateMatching, State) =
2986 State->assumeInclusiveRange(*CondNL, V1, V2);
2990 StateMatching = State;
2993 if (StateMatching) {
2994 BlockEdge BE(SwitchBlock, CaseBlock, SF);
2995 Dst.
insert(Engine.makeNode(BE, StateMatching, Node));
3017 if (
Condition->IgnoreParenImpCasts()->getType()->isEnumeralType()) {
3018 if (
Switch->isAllEnumCasesCovered())
3022 BlockEdge BE(SwitchBlock, DefaultBlock, SF);
3023 Dst.
insert(Engine.makeNode(BE, State, Node));
3037 auto resolveAsLambdaCapturedVar =
3038 [&](
const ValueDecl *VD) -> std::optional<std::pair<SVal, QualType>> {
3039 const auto *MD = dyn_cast<CXXMethodDecl>(SF->
getDecl());
3040 const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
3041 if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
3042 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
3043 MD->getParent()->isLambda()) {
3046 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
3052 if (
const FieldDecl *FD = LambdaCaptureFields[VD]) {
3053 Loc CXXThis = svalBuilder.getCXXThis(MD, SF);
3055 return std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
3059 return std::nullopt;
3062 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
3065 assert(Ex->
isGLValue() || VD->getType()->isVoidType());
3066 std::optional<std::pair<SVal, QualType>> VInfo =
3067 resolveAsLambdaCapturedVar(VD);
3070 VInfo = std::make_pair(state->getLValue(VD, SF), VD->getType());
3072 SVal V = VInfo->first;
3073 bool IsReference = VInfo->second->isReferenceType();
3079 V = state->getSVal(R);
3088 if (
const auto *ED = dyn_cast<EnumConstantDecl>(D)) {
3090 SVal V = svalBuilder.makeIntVal(ED->getInitVal());
3091 Dst.
insert(Engine.makeNodeWithBinding(Pred, Ex,
V));
3094 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
3095 SVal V = svalBuilder.getFunctionPointer(FD);
3106 if (
const auto *BD = dyn_cast<BindingDecl>(D)) {
3108 if (std::optional<std::pair<SVal, QualType>> VInfo =
3109 resolveAsLambdaCapturedVar(BD)) {
3110 auto [
V, T] = VInfo.value();
3112 if (T->isReferenceType()) {
3114 V = state->getSVal(R);
3119 Dst.
insert(Engine.makeNodeWithBinding(Pred, Ex,
V,
3126 SVal Base = state->getLValue(DD, SF);
3127 if (DD->getType()->isReferenceType()) {
3129 Base = state->getSVal(R);
3137 if (
const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
3139 V = state->getLValue(Field,
Base);
3142 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {
3143 SVal Idx = state->getSVal(ASE->getIdx(), SF);
3148 assert(Idx.
isConstant() &&
"BindingDecl array index is not a constant!");
3150 V = state->getLValue(BD->getType(), Idx,
Base);
3153 else if (
const auto *HV = BD->getHoldingVar()) {
3154 V = state->getLValue(HV, SF);
3156 if (HV->getType()->isReferenceType()) {
3158 V = state->getSVal(R);
3163 llvm_unreachable(
"An unknown case of structured binding encountered!");
3167 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3169 V = state->getSVal(R);
3179 if (
const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
3186 llvm_unreachable(
"Support for this Decl not implemented.");
3202 EvalSet.
insert(CheckerPreStmt);
3203 CheckerPreStmt.
clear();
3206 for (
auto *Node : CheckerPreStmt) {
3207 const StackFrame *SF = Node->getStackFrame();
3246 if (
const auto *ME = dyn_cast<MemberExpr>(Arr)) {
3247 Expr *MEBase = ME->getBase();
3250 if (
auto CXXSCE = dyn_cast<CXXStaticCastExpr>(MEBase)) {
3251 MEBase = CXXSCE->getSubExpr();
3272 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arr))
3277 Base = state->getSVal(R);
3281 EvalSet.
insert(Engine.makeNodeWithBinding(Node, Ex,
Base));
3305 (A->
getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
3307 for (
auto *Node : CheckerPreStmt) {
3308 const StackFrame *SF = Node->getStackFrame();
3311 if (IsGLValueLike) {
3317 if (T->isVoidType())
3320 SVal V = state->getLValue(T, state->getSVal(Idx, SF),
3321 state->getSVal(
Base, SF));
3324 }
else if (IsVectorType) {
3326 EvalSet.
insert(Engine.makePostStmtNode(A, state, Node));
3328 llvm_unreachable(
"Array subscript should be an lValue when not \
3329a vector and not a forbidden lvalue type");
3349 for (
const auto I : CheckedSet)
3354 for (
const auto I : CheckedSet) {
3360 if (
const auto *MD = dyn_cast<CXXMethodDecl>(
Member)) {
3361 if (MD->isImplicitObjectMemberFunction())
3362 state = createTemporaryRegionIfNeeded(state, SF, BaseExpr);
3364 SVal MDVal = svalBuilder.getFunctionPointer(MD);
3366 EvalSet.
insert(Engine.makeNodeWithBinding(I, M, MDVal, state));
3372 state = createTemporaryRegionIfNeeded(state, SF, BaseExpr,
3379 if (
const auto *SR =
3380 dyn_cast_or_null<SymbolicRegion>(baseExprVal.
getAsRegion())) {
3381 QualType T = SR->getPointeeStaticType();
3387 SVal L = state->getLValue(field, baseExprVal);
3397 dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
3398 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
3399 llvm_unreachable(
"should always be wrapped in ArrayToPointerDecay");
3403 if (field->getType()->isReferenceType()) {
3405 L = state->getSVal(R);
3410 EvalSet.
insert(Engine.makeNodeWithBinding(
3434 for (
const auto I : AfterPreSet) {
3441 ValuesToInvalidate.push_back(SubExprVal);
3449 AfterInvalidateSet.
insert(
3450 Engine.makeNodeWithBinding(I, AE,
UnknownVal(), State));
3467 for (
const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
3469 const MemRegion *MR = LocAndVal.first.getAsRegion();
3472 Escaped.push_back(LocAndVal.second);
3477 if (
const auto *VR = dyn_cast<VarRegion>(MR->
getBaseRegion()))
3479 VR->getStackFrame()->inTopFrame())
3480 if (
const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3481 if (!RD->hasTrivialDestructor()) {
3482 Escaped.push_back(LocAndVal.second);
3491 SVal StoredVal = State->getSVal(MR);
3492 if (StoredVal != LocAndVal.second)
3495 Escaped.push_back(LocAndVal.second);
3498 if (Escaped.empty())
3507 std::pair<SVal, SVal> LocAndVal(
Loc, Val);
3518 if (!Invalidated || Invalidated->empty())
3531 for (
const auto I : ExplicitRegions) {
3533 SymbolsDirectlyInvalidated.insert(R->getSymbol());
3537 for (
const auto &sym : *Invalidated) {
3538 if (SymbolsDirectlyInvalidated.count(sym))
3540 SymbolsIndirectlyInvalidated.insert(sym);
3543 if (!SymbolsDirectlyInvalidated.empty())
3548 if (!SymbolsIndirectlyInvalidated.empty())
3562 assert(!
isa<NonLoc>(Location) &&
"evalBind location should not be NonLoc!");
3573 StoreE, AtDeclInit, *
this, *PP);
3581 if (
auto AsLoc = Location.getAs<
Loc>()) {
3585 State = State->bindLoc(*AsLoc, Val, SF, !AtDeclInit);
3588 PostStore PS(StoreE, SF, Location.getAsRegion(),
nullptr);
3602 const Expr *LocationE,
3608 const Expr *StoreE = AssignE ? AssignE : LocationE;
3612 evalLocation(Tmp, AssignE, LocationE, Pred, state, location,
false);
3620 for (
const auto I : Tmp)
3621 evalBind(Dst, StoreE, I, location, Val,
false);
3626 const Expr *BoundEx,
3632 assert(!
isa<NonLoc>(location) &&
"location cannot be a NonLoc.");
3637 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location,
true);
3646 for (
const auto I : Tmp) {
3647 state = I->getState();
3653 V = state->getSVal(location.
castAs<
Loc>(), LoadTy);
3657 state->BindExpr(BoundEx, I->getStackFrame(),
V), tag,
3664 const Stmt *BoundEx,
3676 BldrTop.takeNodes(Pred);
3689 Bldr.generateNode(NodeEx, Pred, state, &tag);
3693 NodeEx, BoundEx, *
this);
3694 BldrTop.addNodes(Tmp);
3697std::pair<const ProgramPointTag *, const ProgramPointTag *>
3700 FalseTag(TagProviderName,
"Eagerly Assume False");
3702 return std::make_pair(&TrueTag, &FalseTag);
3726 State = State->set<LastEagerlyAssumeExprIfSuccessful>(
nullptr);
3727 SVal V = State->getSVal(Ex, SF);
3729 if (SEV && SEV->isExpression()) {
3732 auto [StateTrue, StateFalse] = State->assume(*SEV);
3734 if (StateTrue && StateFalse) {
3735 StateTrue = StateTrue->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3736 StateFalse = StateFalse->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3742 StateTrue = StateTrue->BindExpr(Ex, SF, Val);
3743 PostStmt PostStmtTrue(Ex, SF, TrueTag);
3750 StateFalse = StateFalse->BindExpr(Ex, SF, Val);
3751 PostStmt PostStmtFalse(Ex, SF, FalseTag);
3761 const Expr *Ex)
const {
3762 return Ex && State->get<LastEagerlyAssumeExprIfSuccessful>() == Ex;
3780 if (std::optional<Loc> LV =
X.getAs<
Loc>())
3791 if (std::optional<Loc> LV =
X.getAs<
Loc>())
3798 Dst.
insert(Engine.makePostStmtNode(A, state, Pred));
3821 for (
const auto &
Report : Class.getReports()) {
3822 const auto *PR = dyn_cast<PathSensitiveBugReport>(
Report.get());
3840 llvm::function_ref<
void(
const ExplodedNode *)> PreCallback,
3841 llvm::function_ref<
void(
const ExplodedNode *)> PostCallback,
3863 llvm::raw_string_ostream Out(Buf);
3865 const bool IsDot =
true;
3866 const unsigned int Space = 1;
3869 Out <<
"{ \"state_id\": " << State->getID()
3872 Indent(Out, Space, IsDot) <<
"\"program_points\": [\\l";
3878 Indent(Out, Space + 1, IsDot) <<
"{ ";
3880 Out <<
", \"tag\": ";
3882 Out <<
'\"' << Tag->getDebugTag() <<
'\"';
3885 Out <<
", \"node_id\": " << OtherNode->
getID() <<
3886 ", \"is_sink\": " << OtherNode->
isSink() <<
3894 Indent(Out, Space, IsDot) <<
"],\\l";
3907 llvm::DisplayGraph(Filename,
false, llvm::GraphProgram::DOT);
3911 std::string Filename =
DumpGraph(Nodes);
3912 llvm::DisplayGraph(Filename,
false, llvm::GraphProgram::DOT);
3917 std::vector<const ExplodedNode *> Src;
3920 for (
const auto &
Class : BR.equivalenceClasses()) {
3922 dyn_cast<PathSensitiveBugReport>(
Class.getReports()[0].get());
3925 const auto *N =
const_cast<ExplodedNode *
>(R->getErrorNode());
3932 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
3933 return llvm::WriteGraph(&G,
"ExprEngine",
false,
3935 std::string(Filename));
3939 StringRef Filename) {
3940 std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
3943 llvm::errs() <<
"warning: Trimmed ExplodedGraph is empty.\n";
3948 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
3949 return llvm::WriteGraph(TrimmedG.get(),
"TrimmedExprEngine",
3951 "Trimmed Exploded Graph",
3952 std::string(Filename));
3956 static int index = 0;
3960void ExprEngine::anchor() { }
3972 bool IsCompound = T->
isArrayType() || T->isRecordType() ||
3973 T->isAnyComplexType() || T->isVectorType();
3976 if (Args.size() > 1 || (E->
isPRValue() && IsCompound && !IsTransparent)) {
3978 for (
Expr *E : llvm::reverse(Args))
3982 }
else if (Args.size() == 0) {
3985 Val = S->getSVal(Args.front(), SF);
3987 Dst.
insert(Engine.makeNodeWithBinding(Pred, E, Val));
Defines the clang::ASTContext interface.
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
#define STAT_COUNTER(VARNAME, DESC)
Defines the clang::Expr interface and subclasses for C++ expressions.
static const Stmt * getRightmostLeaf(const Stmt *Condition)
static void printIndicesOfElementsToConstructJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const StackFrame *SF, unsigned int Space=0, bool IsDot=false)
static const Stmt * ResolveCondition(const Stmt *Condition, const CFGBlock *B)
std::pair< const ObjCForCollectionStmt *, const StackFrame * > ObjCForLctxPair
static SVal RecoverCastedSymbol(ProgramStateRef state, const Stmt *Condition, const StackFrame *SF, ASTContext &Ctx)
RecoverCastedSymbol - A helper function for ProcessBranch that is used to try to recover some path-se...
static void printStateTraitWithStackFrameJson(raw_ostream &Out, ProgramStateRef State, const StackFrame *SF, const char *NL, unsigned int Space, bool IsDot, const char *jsonPropertyName, Printer printer, Args &&...args)
A helper function to generalize program state trait printing.
static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const StackFrame *SF, unsigned int Space=0, bool IsDot=false)
REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction, ObjectsUnderConstructionMap) typedef llvm REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct, IndexOfElementToConstructMap) typedef llvm typedef llvm::ImmutableMap< const StackFrame *, unsigned > PendingArrayDestructionMap
llvm::ImmutableMap< ConstructedObjectKey, SVal > ObjectsUnderConstructionMap
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S, const ExplodedNode *Pred, const StackFrame *SF)
static void printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const StackFrame *SF, unsigned int Space=0, bool IsDot=false)
static std::optional< std::pair< ProgramStateRef, ProgramStateRef > > assumeCondition(const Stmt *ConditionStmt, ExplodedNode *N)
Split the state on whether there are any more iterations left for this loop.
static void printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const StackFrame *SF, unsigned int Space=0, bool IsDot=false)
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Result
Implement __builtin_bit_cast and related operations.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
This header contains the declarations of functions which are used to decide which loops should be com...
This header contains the declarations of functions which are used to widen loops which do not otherwi...
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
#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.
static bool isRecordType(QualType T)
Defines the clang::SourceLocation class and associated facilities.
Defines various enumerations that describe declaration and type specifiers.
Defines the Objective-C statement AST node classes.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
const clang::PrintingPolicy & getPrintingPolicy() const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
ParentMap & getParentMap()
ASTContext & getASTContext() const
Stores options for the analyzer from the command line.
AnalysisPurgeMode AnalysisPurgeOpt
Represents a loop initializing the elements of an array.
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Expr * getSubExpr() const
Get the initializer to use for each array element.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
const CFGBlock * getPreviousBlock() const
const CFGBlock * getBlock() const
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
Represents C++ object destructor implicitly generated for base object in destructor.
const CXXBaseSpecifier * getBaseSpecifier() const
Represents a single basic block in a source-level CFG.
succ_reverse_iterator succ_rend()
succ_reverse_iterator succ_rbegin()
CFGTerminator getTerminator() const
Stmt * getTerminatorStmt()
unsigned getBlockID() const
unsigned succ_size() const
Represents C++ object destructor generated from a call to delete.
Represents a top-level expression in a basic block.
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
Represents C++ object destructor implicitly generated by compiler on various occasions.
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
Represents C++ base or member initializer from constructor's initialization list.
const CXXCtorInitializer * getInitializer() const
Represents the point where the lifetime of an automatic object ends.
const VarDecl * getVarDecl() const
Represents the point where a loop ends.
const Stmt * getLoopStmt() const
Represents C++ object destructor implicitly generated for member object in destructor.
const FieldDecl * getFieldDecl() const
Represents C++ allocator call.
const CXXNewExpr * getAllocatorExpr() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const Stmt * getTriggerStmt() const
const Stmt * getStmt() const
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
const CXXBindTemporaryExpr * getBindTemporaryExpr() const
bool isStmtBranch() const
Represents a base class of a C++ class.
Represents binding an expression to a temporary.
const Expr * getSubExpr() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a call to a C++ constructor.
Represents a C++ base or member initializer.
FieldDecl * getMember() const
If this is a member initializer, returns the declaration of the non-static data member being initiali...
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
Expr * getInit() const
Get the initializer.
SourceLocation getSourceLocation() const
Determine the source location of the initializer.
bool isAnyMemberInitializer() const
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
bool isIndirectMemberInitializer() const
int64_t getID(const ASTContext &Context) const
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
FieldDecl * getAnyMember() const
IndirectFieldDecl * getIndirectMember() const
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Represents a delete expression for memory deallocation and destructor calls, e.g.
SourceLocation getBeginLoc() const
QualType getDestroyedType() const
Retrieve the type being destroyed.
Represents a C++ destructor within a class.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Represents a list-initialization with parenthesis.
MutableArrayRef< Expr * > getInitExprs()
Represents a C++ struct/union/class.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Represents a point when we begin processing an inlined call.
CaseStmt - Represent a case statement.
Represents a single point (AST node) in the program that requires attention during construction of an...
unsigned getIndex() const
If a single trigger statement triggers multiple constructors, they are usually being enumerated.
const CXXCtorInitializer * getCXXCtorInitializer() const
The construction site is not necessarily a statement.
@ TemporaryDestructorKind
const Stmt * getStmtOrNull() const
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
const Decl * getSingleDecl() const
Decl - This represents one declaration (or definition), e.g.
This is a meta program point, which should be skipped by all the diagnostic reasoning etc.
This represents one expression.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Represents a member of a struct/union/class.
This represents a GCC inline-assembly statement extension.
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Describes an C or C++ initializer list.
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
ArrayRef< Expr * > inits() const
Represents the declaration of a label.
Represents a point when the lifetime of an automatic object ends.
Represents a point when we exit a loop.
This represents a Microsoft inline-assembly statement extension.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents Objective-C's collection statement.
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
bool isConsumedExpr(Expr *E) const
Represents a parameter to a function.
Represents a program point just after an implicit call event.
Represents a program point after a store evaluation.
Represents a program point just before an implicit call event.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
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.
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const StackFrame *SF, const ProgramPointTag *tag)
void printJson(llvm::raw_ostream &Out, const char *NL="\n") const
ProgramPoint withTag(const ProgramPointTag *tag) const
Create a new ProgramPoint object that is the same as the original except for using the specified tag ...
@ PreStmtPurgeDeadSymbolsKind
@ 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.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getCanonicalType() const
SplitQualType split() const
Divides a QualType into its unqualified type and a set of local qualifiers.
std::string getAsString() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
std::string printToString(const SourceManager &SM) const
It represents a stack frame of the call stack.
unsigned getIndex() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const StackFrame *)> printMoreInfoPerStackFrame=[](const StackFrame *) {}) const
Prints out the call stack in json format.
const Expr * getCallSite() const
const Decl * getDecl() const
const StackFrame * getParent() const
It might return null.
const CFGBlock * getCallSiteBlock() const
const Stmt * getStmt() const
Stmt - This represents one statement.
void printJson(raw_ostream &Out, PrinterHelper *Helper, const PrintingPolicy &Policy, bool AddQuotes) const
Pretty-prints in JSON format.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
int64_t getID(const ASTContext &Context) const
SourceLocation getBeginLoc() const LLVM_READONLY
SwitchStmt - This represents a 'switch' stmt.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isReferenceType() const
bool isVectorType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
This class is used for tools that requires cross translation unit capability.
AnalyzerOptions & options
llvm::ImmutableList< SVal > getEmptySValList()
llvm::ImmutableList< SVal > prependSVal(SVal X, llvm::ImmutableList< SVal > L)
BugReporter is a utility class for generating PathDiagnostics for analysis.
llvm::iterator_range< EQClasses_iterator > equivalenceClasses()
Represents an abstract call to a function or method along a particular path.
static bool isCallStmt(const Stmt *S)
Returns true if this is a statement is a function or method call of some kind.
ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const StackFrame *SF, const CallEvent *Call)
Run checkers for region changes.
void runCheckersForLocation(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, bool isLoad, const Stmt *NodeEx, const Stmt *BoundEx, ExprEngine &Eng)
Run checkers for load/store of a location.
void runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, bool AtDeclInit, ExprEngine &Eng, const ProgramPoint &PP)
Run checkers for binding of a value to a location.
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng)
Run checkers for end of analysis.
void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const
Run checkers for debug-printing a ProgramState.
void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SymbolReaper &SymReaper, const Stmt *S, ExprEngine &Eng, ProgramPoint::Kind K)
Run checkers for dead symbols.
void runCheckersForEndFunction(ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, const ReturnStmt *RS)
Run checkers on end of function.
void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper)
Run checkers for live symbols.
void runCheckersForBeginFunction(ExplodedNodeSet &Dst, const BlockEdge &L, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers on beginning of function.
void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting Stmts.
void runCheckersForPreStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng)
Run checkers for pre-visiting Stmts.
void runCheckersForBlockEntrance(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const BlockEntrance &Entrance, ExprEngine &Eng) const
Run checkers after taking a control flow edge.
void runCheckersForBranchCondition(const Stmt *condition, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers for branch condition.
ProgramStateRef runCheckersForPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, RegionAndSymbolInvalidationTraits *ITraits)
Run checkers when pointers escape.
void runCheckersForLifetimeEnd(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const VarDecl *Decl, ExprEngine &Eng)
Run checkers for the end of a variable's lifetime.
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption)
Run checkers for handling assumptions on symbolic values.
virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, SymbolReaper &SymReaper)=0
Scan all symbols referenced by the constraints.
void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx)
Enqueue a single node created as a result of statement processing.
ExplodedNode * makeNode(const ProgramPoint &Loc, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false) 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...
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()
bool isTrivial() const
The node is trivial if it has only one successor, only one predecessor, it's predecessor has only one...
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 succ_size() const
const StackFrame * getStackFrame() const
void VisitBinaryOperator(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBinaryOperator - Transfer function logic for binary operators.
const StackFrame * getRootStackFrame() const
ProgramStateManager & getStateManager()
void processCFGElement(const CFGElement E, ExplodedNode *Pred, unsigned StmtIdx)
processCFGElement - Called by CoreEngine.
void processBranch(const Stmt *Condition, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF, std::optional< unsigned > IterationsCompletedInLoop)
ProcessBranch - Called by CoreEngine.
void VisitArraySubscriptExpr(const ArraySubscriptExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitArraySubscriptExpr - Transfer function for array accesses.
void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred)
void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void ProcessTemporaryDtor(const CFGTemporaryDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
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 VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGuardedExpr - Transfer function logic for ?, __builtin_choose.
void runCheckersForBlockEntrance(const BlockEntrance &Entrance, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCast - Transfer function logic for all casts (implicit and explicit).
BasicValueFactory & getBasicVals()
void VisitLogicalExpr(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitLogicalExpr - Transfer function logic for '&&', '||'.
void processEndOfFunction(ExplodedNode *Pred, const ReturnStmt *RS=nullptr)
Called by CoreEngine.
void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst, EvalCallOptions &Options)
void removeDeadOnEndOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst)
Remove dead bindings/symbols before exiting a function.
void evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex)
evalEagerlyAssumeBifurcation - Given the nodes in 'Src', eagerly assume concrete boolean values for '...
void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for ObjCAtSynchronizedStmts.
void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitReturnStmt - Transfer function logic for return statements.
SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, SVal LHS, SVal RHS, QualType T)
void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitLambdaExpr - Transfer function logic for LambdaExprs.
void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred)
void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitObjCForCollectionStmt - Transfer function logic for ObjCForCollectionStmt.
void VisitUnaryOperator(const UnaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitUnaryOperator - Transfer function logic for unary operators.
void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for computing the lvalue of an Objective-C ivar.
void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitMSAsmStmt - Transfer function logic for MS inline asm.
void processStaticInitializer(const DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
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.
std::string DumpGraph(bool trim=false, StringRef Filename="")
Dump graph to the specified filename.
ProgramStateRef processRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const StackFrame *SF, const CallEvent *Call)
processRegionChanges - Called by ProgramStateManager whenever a change is made to the store.
InliningModes
The modes of inlining, which override the default analysis-wide settings.
void printJson(raw_ostream &Out, ProgramStateRef State, const StackFrame *SF, const char *NL, unsigned int Space, bool IsDot) const
printJson - Called by ProgramStateManager to print checker-specific data.
void ProcessLifetimeEnd(const Stmt *S, const VarDecl *D, ExplodedNode *Pred)
static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const StackFrame *SF)
Retrieves the size of the array in the pending ArrayInitLoopExpr.
ProgramStateRef processAssume(ProgramStateRef state, SVal cond, bool assumption)
evalAssume - Callback function invoked by the ConstraintManager when making assumptions about state v...
AnalysisDeclContextManager & getAnalysisDeclContextManager()
static ProgramStateRef removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O, const StackFrame *SF)
void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBlockExpr - Transfer function logic for BlockExprs.
void ProcessBaseDtor(const CFGBaseDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
static std::pair< const ProgramPointTag *, const ProgramPointTag * > getEagerlyAssumeBifurcationTags()
void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCall - Transfer function for function calls.
void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
ProgramStateRef processRegionChange(ProgramStateRef state, const MemRegion *MR, const StackFrame *SF)
ASTContext & getContext() const
getContext - Return the ASTContext associated with this analysis.
StoreManager & getStoreManager()
void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Create a C++ temporary object for an rvalue.
void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGCCAsmStmt - Transfer function logic for inline asm.
BugReporter & getBugReporter()
void ProcessStmt(const Stmt *S, ExplodedNode *Pred)
ConstCFGElementRef getCFGElementRef() const
ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS, InliningModes HowToInlineIn)
void ViewGraph(bool trim=false)
Visualize the ExplodedGraph created by executing the simulation.
ProgramStateRef notifyCheckersOfPointerEscape(ProgramStateRef State, const InvalidatedSymbols *Invalidated, ArrayRef< const MemRegion * > ExplicitRegions, const CallEvent *Call, RegionAndSymbolInvalidationTraits &ITraits)
Call PointerEscape callback when a value escapes as a result of region invalidation.
static const ProgramPointTag * cleanupNodeTag()
A tag to track convenience transitions, which can be removed at cleanup.
static ProgramStateRef setWhetherHasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const StackFrame *SF, bool HasMoreIteraton)
Note whether this loop has any more iterations to model. These methods.
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.
void ConstructInitList(const Expr *Source, ArrayRef< Expr * > Args, bool IsTransparent, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
ProgramStateRef escapeValues(ProgramStateRef State, ArrayRef< SVal > Vs, PointerEscapeKind K, const CallEvent *Call=nullptr) const
A simple wrapper when you only need to notify checkers of pointer-escape of some values.
void ProcessLoopExit(const Stmt *S, ExplodedNode *Pred)
void processEndWorklist()
Called by CoreEngine when the analysis worklist has terminated.
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,...
SymbolManager & getSymbolManager()
void processBeginOfFunction(ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L)
Called by CoreEngine.
void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAtomicExpr - Transfer function for builtin atomic expressions.
MemRegionManager & getRegionManager()
void ProcessMemberDtor(const CFGMemberDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitMemberExpr - Transfer function for member expressions.
void processSwitch(const SwitchStmt *Switch, ExplodedNode *Pred, ExplodedNodeSet &Dst)
ProcessSwitch - Called by CoreEngine.
void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
static bool hasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const StackFrame *SF)
bool didEagerlyAssumeBifurcateAt(ProgramStateRef State, const Expr *Ex) const
ConstraintManager & getConstraintManager()
ProgramStateRef getInitialState(const StackFrame *InitSF)
getInitialState - Return the initial state used for the root vertex in the ExplodedGraph.
void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
unsigned getNumVisitedCurrent() const
void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitOffsetOfExpr - Transfer function for offsetof.
void evalLoad(ExplodedNodeSet &Dst, const Expr *NodeEx, const Expr *BoundExpr, ExplodedNode *Pred, ProgramStateRef St, SVal location, const ProgramPointTag *tag=nullptr, QualType LoadTy=QualType())
Simulate a read of the result of Ex.
void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Visit - Transfer function logic for all statements.
AnalysisManager & getAnalysisManager()
ExplodedGraph & getGraph()
void ProcessDeleteDtor(const CFGDeleteDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCompoundLiteralExpr - Transfer function logic for compound literals.
SValBuilder & getSValBuilder()
void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitArrayInitLoopExpr - Transfer function for array init loop.
void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, const ProgramPointTag *tag=nullptr)
evalStore - Handle the semantics of a store via an assignment.
void processCFGBlockEntrance(const BlockEdge &L, const BlockEntrance &BE, NodeBuilder &Builder, ExplodedNode *Pred)
Called by CoreEngine when processing the entrance of a CFGBlock.
void VisitAttributedStmt(const AttributedStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAttributedStmt - Transfer function logic for AttributedStmt.
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, ExplodedNodeSet &PreVisit, ExplodedNodeSet &Dst)
const StackFrame * getCurrStackFrame() const
Get the 'current' stack frame corresponding to the current work item (elementary analysis step handle...
const CFGBlock * getCurrBlock() const
Get the 'current' CFGBlock corresponding to the current work item (elementary analysis step handled b...
void processIndirectGoto(ExplodedNodeSet &Dst, const Expr *Tgt, const CFGBlock *Dispatch, ExplodedNode *Pred)
processIndirectGoto - Called by CoreEngine.
void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred)
static bool isLocType(QualType T)
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace(ProgramStateRef State) const
Returns the most specific memory space for this memory region in the given ProgramStateRef.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
This is the simplest builder which generates nodes in the ExplodedGraph.
ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false)
Generates a node in the ExplodedGraph.
While alive, includes the current analysis stack in a crash trace.
Information about invalidation for a particular region/symbol.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
NonLoc makeCompoundVal(QualType type, llvm::ImmutableList< SVal > vals)
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrame *SF)
Return a memory region for the 'this' object reference.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const StackFrame *SF, unsigned count)
Create a new symbol with a unique 'name'.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
bool isUnknownOrUndef() const
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const MemRegion * getAsRegion() const
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 SVal getLValueField(const FieldDecl *D, SVal Base)
SubRegion - A region that subsets another larger region.
A class responsible for cleaning up unused symbols.
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
SymbolicRegion - A special, "non-concrete" region.
Represents symbolic expression that isn't a location.
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
@ PSK_DirectEscapeOnCall
The pointer has been passed to a function call directly.
@ PSK_EscapeOnBind
A pointer escapes due to binding its value to a location that the analyzer cannot track.
@ PSK_IndirectEscapeOnCall
The pointer has been passed to a function indirectly.
@ PSK_EscapeOther
The reason for pointer escape is unknown.
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)
llvm::DenseSet< const Decl * > SetOfConstDecls
llvm::DenseSet< SymbolRef > InvalidatedSymbols
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State)
Updates the given ProgramState.
bool isUnrolledState(ProgramStateRef State)
Returns if the given State indicates that is inside a completely unrolled loop.
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, const StackFrame *SF, unsigned BlockCount, ConstCFGElementRef Elem)
Get the states that result from widening the loop.
void markAllDynamicExtentLive(ProgramStateRef State, SymbolReaper &SymReaper)
ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx, ExplodedNode *Pred, unsigned maxVisitOnPath)
Updates the stack of loops contained by the ProgramState.
bool LE(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
StorageDuration
The storage duration for an object (per C++ [basic.stc]).
@ SD_Thread
Thread storage duration.
@ SD_Static
Static storage duration.
@ SD_FullExpression
Full-expression storage duration (for temporaries).
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)
@ CXXThis
Parameter for C++ 'this' argument.
Diagnostic wrappers for TextAPI types for error reporting.
Describes how types, statements, expressions, and declarations should be printed.
@ DerivedToBaseAdjustment
@ MemberPointerAdjustment
Hints for figuring out if a call should be inlined during evalCall().
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...
Traits for storing the call processing policy inside GDM.
DOTGraphTraits(bool isSimple=false)
static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G)
static bool nodeHasBugReport(const ExplodedNode *N)
static bool traverseHiddenNodes(const ExplodedNode *N, llvm::function_ref< void(const ExplodedNode *)> PreCallback, llvm::function_ref< void(const ExplodedNode *)> PostCallback, llvm::function_ref< bool(const ExplodedNode *)> Stop)
PreCallback: callback before break.
static bool isNodeHidden(const ExplodedNode *N, const ExplodedGraph *G)