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");
1158 Engine.enqueueStmtNodes(Dst, currBldrCtx->getBlock(), currStmtIdx);
1169 "Error evaluating initializer");
1175 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(
decl, SF));
1187 State = finishObjectConstruction(State, BMI, SF);
1189 Tmp.
insert(Engine.makeNode(PS, State, Pred));
1197 FieldLoc = State->getLValue(BMI->
getMember(), thisVal);
1201 if (
Init->getType()->isArrayType()) {
1205 while ((ASE = dyn_cast<ArraySubscriptExpr>(
Init)))
1208 InitVal = State->getSVal(
Init, SF);
1217 InitVal = State->getSVal(BMI->
getInit(), SF);
1221 evalBind(Tmp,
Init, Pred, FieldLoc, InitVal,
true, &PP);
1229 SVal InitVal = State->getSVal(
Init, SF);
1230 evalBind(Tmp,
Init, Pred, BaseLoc, InitVal,
true);
1245 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1248std::pair<ProgramStateRef, uint64_t>
1249ExprEngine::prepareStateForArrayDestruction(
const ProgramStateRef State,
1253 SVal *ElementCountVal) {
1254 assert(Region !=
nullptr &&
"Not-null region expected");
1257 while (
const auto *NTy = dyn_cast<ArrayType>(Ty))
1258 Ty = NTy->getElementType().getDesugaredType(
getContext());
1262 if (ElementCountVal)
1263 *ElementCountVal = ElementCount;
1271 if (!ElementCount.isConstant())
1274 Idx = ElementCount.getAsInteger()->getLimitedValue();
1282 return {setPendingArrayDestruction(State, SF, Idx), Idx};
1305 llvm_unreachable(
"Unexpected dtor kind.");
1309 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1320 if (Opts.MayInlineCXXAllocator)
1328 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1345 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
1360 std::tie(state, Idx) = prepareStateForArrayDestruction(
1361 state, Region, varType, SF, &ElementCount);
1363 if (ElementCount.isConstant()) {
1364 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1365 assert(ArrayLength &&
1366 "An automatic dtor for a 0 length array shouldn't be triggered!");
1371 "ExprEngine",
"Skipping automatic 0 length array destruction, "
1372 "which shouldn't be in the CFG.");
1375 Engine.makeNode(PP, Pred->
getState(), Pred,
true);
1387 "Prepare for object destruction");
1390 Pred = Engine.makeNode(PP, state, Pred);
1396 false, Pred, Dst, CallOpts);
1407 SVal ArgVal = State->getSVal(Arg, SF);
1411 if (State->isNull(ArgVal).isConstrainedTrue()) {
1421 auto getDtorDecl = [](
const QualType &DTy) {
1433 while (
const auto *AT =
getContext().getAsArrayType(DTy))
1434 DTy = AT->getElementType();
1438 std::tie(State, Idx) =
1439 prepareStateForArrayDestruction(State, ArgR, DTy, SF, &ElementCount);
1443 if (ElementCount.isConstant() &&
1444 ElementCount.getAsInteger()->getLimitedValue() == 0) {
1447 "ExprEngine",
"Skipping 0 length array delete destruction");
1454 ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
1460 "Prepare for object destruction");
1463 Pred = Engine.makeNode(PP, State, Pred);
1487 true, Pred, Dst, CallOpts);
1500 Loc ThisLoc = State->getSVal(ThisStorageLoc).
castAs<
Loc>();
1501 SVal FieldVal = State->getLValue(
Member, ThisLoc);
1506 std::tie(State, Idx) = prepareStateForArrayDestruction(
1507 State, FieldVal.getAsRegion(), T, SF, &ElementCount);
1509 if (ElementCount.isConstant()) {
1510 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1511 assert(ArrayLength &&
1512 "A member dtor for a 0 length array shouldn't be triggered!");
1517 "ExprEngine",
"Skipping member 0 length array destruction, which "
1518 "shouldn't be in the CFG.");
1521 Engine.makeNode(PP, Pred->
getState(), Pred,
true);
1532 "Prepare for object destruction");
1535 Pred = Engine.makeNode(PP, State, Pred);
1541 false, Pred, Dst, CallOpts);
1556 State = finishObjectConstruction(State, BTE, SF);
1557 MR =
V->getAsRegion();
1562 if (isDestructorElided(State, BTE, SF)) {
1563 State = cleanupElidedDestructor(State, BTE, SF);
1566 Dst.
insert(Engine.makeNode(PP, State, Pred));
1570 ExplodedNode *CleanPred = Engine.makePostStmtNode(BTE, State, Pred);
1571 if (!CleanPred || CleanPred->
isSink()) {
1601 T = AT->getElementType();
1612 false, CleanPred, Dst, CallOpts);
1624 if (
const CFGBlock *DstBlock = Obj ? DstT : DstF) {
1626 Dst.
insert(Engine.makeNode(BE, State, Pred));
1645 const StackFrame *SF = Node->getStackFrame();
1651 State = addObjectUnderConstruction(State, BTE, SF,
UnknownVal());
1653 Builder.generateNode(BTE, Node, State);
1661 class CollectReachableSymbolsCallback final :
public SymbolVisitor {
1666 : Symbols(Symbols) {}
1670 bool VisitSymbol(
SymbolRef Sym)
override {
1671 Symbols.insert(Sym);
1676 CollectReachableSymbolsCallback CallBack(Symbols);
1678 State->scanReachableSymbols(
V, CallBack);
1681 State, CallBack.getSymbols(),
Call, K,
nullptr);
1693 case Stmt::CXXDependentScopeMemberExprClass:
1694 case Stmt::CXXReflectExprClass:
1695 case Stmt::CXXTryStmtClass:
1696 case Stmt::CXXTypeidExprClass:
1697 case Stmt::CXXUuidofExprClass:
1698 case Stmt::CXXFoldExprClass:
1699 case Stmt::MSPropertyRefExprClass:
1700 case Stmt::MSPropertySubscriptExprClass:
1701 case Stmt::CXXUnresolvedConstructExprClass:
1702 case Stmt::DependentScopeDeclRefExprClass:
1703 case Stmt::ArrayTypeTraitExprClass:
1704 case Stmt::ExpressionTraitExprClass:
1705 case Stmt::UnresolvedLookupExprClass:
1706 case Stmt::UnresolvedMemberExprClass:
1707 case Stmt::RecoveryExprClass:
1708 case Stmt::CXXNoexceptExprClass:
1709 case Stmt::PackExpansionExprClass:
1710 case Stmt::PackIndexingExprClass:
1711 case Stmt::SubstNonTypeTemplateParmPackExprClass:
1712 case Stmt::FunctionParmPackExprClass:
1713 case Stmt::CoroutineBodyStmtClass:
1714 case Stmt::CoawaitExprClass:
1715 case Stmt::DependentCoawaitExprClass:
1716 case Stmt::CoreturnStmtClass:
1717 case Stmt::CoyieldExprClass:
1718 case Stmt::SEHTryStmtClass:
1719 case Stmt::SEHExceptStmtClass:
1720 case Stmt::SEHLeaveStmtClass:
1721 case Stmt::SEHFinallyStmtClass:
1722 case Stmt::OMPCanonicalLoopClass:
1723 case Stmt::OMPParallelDirectiveClass:
1724 case Stmt::OMPSimdDirectiveClass:
1725 case Stmt::OMPForDirectiveClass:
1726 case Stmt::OMPForSimdDirectiveClass:
1727 case Stmt::OMPSectionsDirectiveClass:
1728 case Stmt::OMPSectionDirectiveClass:
1729 case Stmt::OMPScopeDirectiveClass:
1730 case Stmt::OMPSingleDirectiveClass:
1731 case Stmt::OMPMasterDirectiveClass:
1732 case Stmt::OMPCriticalDirectiveClass:
1733 case Stmt::OMPParallelForDirectiveClass:
1734 case Stmt::OMPParallelForSimdDirectiveClass:
1735 case Stmt::OMPParallelSectionsDirectiveClass:
1736 case Stmt::OMPParallelMasterDirectiveClass:
1737 case Stmt::OMPParallelMaskedDirectiveClass:
1738 case Stmt::OMPTaskDirectiveClass:
1739 case Stmt::OMPTaskyieldDirectiveClass:
1740 case Stmt::OMPBarrierDirectiveClass:
1741 case Stmt::OMPTaskwaitDirectiveClass:
1742 case Stmt::OMPErrorDirectiveClass:
1743 case Stmt::OMPTaskgroupDirectiveClass:
1744 case Stmt::OMPFlushDirectiveClass:
1745 case Stmt::OMPDepobjDirectiveClass:
1746 case Stmt::OMPScanDirectiveClass:
1747 case Stmt::OMPOrderedDirectiveClass:
1748 case Stmt::OMPAtomicDirectiveClass:
1749 case Stmt::OMPAssumeDirectiveClass:
1750 case Stmt::OMPTargetDirectiveClass:
1751 case Stmt::OMPTargetDataDirectiveClass:
1752 case Stmt::OMPTargetEnterDataDirectiveClass:
1753 case Stmt::OMPTargetExitDataDirectiveClass:
1754 case Stmt::OMPTargetParallelDirectiveClass:
1755 case Stmt::OMPTargetParallelForDirectiveClass:
1756 case Stmt::OMPTargetUpdateDirectiveClass:
1757 case Stmt::OMPTeamsDirectiveClass:
1758 case Stmt::OMPCancellationPointDirectiveClass:
1759 case Stmt::OMPCancelDirectiveClass:
1760 case Stmt::OMPTaskLoopDirectiveClass:
1761 case Stmt::OMPTaskLoopSimdDirectiveClass:
1762 case Stmt::OMPMasterTaskLoopDirectiveClass:
1763 case Stmt::OMPMaskedTaskLoopDirectiveClass:
1764 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1765 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1766 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1767 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1768 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1769 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1770 case Stmt::OMPDistributeDirectiveClass:
1771 case Stmt::OMPDistributeParallelForDirectiveClass:
1772 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1773 case Stmt::OMPDistributeSimdDirectiveClass:
1774 case Stmt::OMPTargetParallelForSimdDirectiveClass:
1775 case Stmt::OMPTargetSimdDirectiveClass:
1776 case Stmt::OMPTeamsDistributeDirectiveClass:
1777 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1778 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1779 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1780 case Stmt::OMPTargetTeamsDirectiveClass:
1781 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1782 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1783 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1784 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1785 case Stmt::OMPReverseDirectiveClass:
1786 case Stmt::OMPStripeDirectiveClass:
1787 case Stmt::OMPTileDirectiveClass:
1788 case Stmt::OMPInterchangeDirectiveClass:
1789 case Stmt::OMPSplitDirectiveClass:
1790 case Stmt::OMPFuseDirectiveClass:
1791 case Stmt::OMPInteropDirectiveClass:
1792 case Stmt::OMPDispatchDirectiveClass:
1793 case Stmt::OMPMaskedDirectiveClass:
1794 case Stmt::OMPGenericLoopDirectiveClass:
1795 case Stmt::OMPTeamsGenericLoopDirectiveClass:
1796 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
1797 case Stmt::OMPParallelGenericLoopDirectiveClass:
1798 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1799 case Stmt::CapturedStmtClass:
1800 case Stmt::SYCLKernelCallStmtClass:
1801 case Stmt::UnresolvedSYCLKernelCallStmtClass:
1802 case Stmt::OpenACCComputeConstructClass:
1803 case Stmt::OpenACCLoopConstructClass:
1804 case Stmt::OpenACCCombinedConstructClass:
1805 case Stmt::OpenACCDataConstructClass:
1806 case Stmt::OpenACCEnterDataConstructClass:
1807 case Stmt::OpenACCExitDataConstructClass:
1808 case Stmt::OpenACCHostDataConstructClass:
1809 case Stmt::OpenACCWaitConstructClass:
1810 case Stmt::OpenACCCacheConstructClass:
1811 case Stmt::OpenACCInitConstructClass:
1812 case Stmt::OpenACCShutdownConstructClass:
1813 case Stmt::OpenACCSetConstructClass:
1814 case Stmt::OpenACCUpdateConstructClass:
1815 case Stmt::OpenACCAtomicConstructClass:
1816 case Stmt::OMPUnrollDirectiveClass:
1817 case Stmt::OMPMetaDirectiveClass:
1818 case Stmt::HLSLOutArgExprClass: {
1825 case Stmt::ParenExprClass:
1826 llvm_unreachable(
"ParenExprs already handled.");
1827 case Stmt::GenericSelectionExprClass:
1828 llvm_unreachable(
"GenericSelectionExprs already handled.");
1831 case Stmt::BreakStmtClass:
1832 case Stmt::CaseStmtClass:
1833 case Stmt::CompoundStmtClass:
1834 case Stmt::ContinueStmtClass:
1835 case Stmt::CXXForRangeStmtClass:
1836 case Stmt::DefaultStmtClass:
1837 case Stmt::DoStmtClass:
1838 case Stmt::ForStmtClass:
1839 case Stmt::GotoStmtClass:
1840 case Stmt::IfStmtClass:
1841 case Stmt::IndirectGotoStmtClass:
1842 case Stmt::LabelStmtClass:
1844 case Stmt::NullStmtClass:
1845 case Stmt::SwitchStmtClass:
1846 case Stmt::WhileStmtClass:
1847 case Stmt::DeferStmtClass:
1848 case Expr::MSDependentExistsStmtClass:
1849 llvm_unreachable(
"Stmt should not be in analyzer evaluation loop");
1850 case Stmt::ImplicitValueInitExprClass:
1854 llvm_unreachable(
"Should be pruned from CFG");
1856 case Stmt::ObjCSubscriptRefExprClass:
1857 case Stmt::ObjCPropertyRefExprClass:
1858 llvm_unreachable(
"These are handled by PseudoObjectExpr");
1860 case Stmt::GNUNullExprClass: {
1862 SVal Val = svalBuilder.makeIntValWithWidth(
getContext().VoidPtrTy, 0);
1867 case Stmt::ObjCAtSynchronizedStmtClass:
1871 case Expr::ConstantExprClass:
1872 case Stmt::ExprWithCleanupsClass:
1877 case Stmt::CXXBindTemporaryExprClass: {
1886 case Stmt::ArrayInitLoopExprClass:
1890 case Stmt::DesignatedInitExprClass:
1891 case Stmt::DesignatedInitUpdateExprClass:
1892 case Stmt::ArrayInitIndexExprClass:
1893 case Stmt::ExtVectorElementExprClass:
1894 case Stmt::MatrixElementExprClass:
1895 case Stmt::ImaginaryLiteralClass:
1896 case Stmt::ObjCAtCatchStmtClass:
1897 case Stmt::ObjCAtFinallyStmtClass:
1898 case Stmt::ObjCAtTryStmtClass:
1899 case Stmt::ObjCAutoreleasePoolStmtClass:
1900 case Stmt::ObjCEncodeExprClass:
1901 case Stmt::ObjCIsaExprClass:
1902 case Stmt::ObjCProtocolExprClass:
1903 case Stmt::ObjCSelectorExprClass:
1904 case Stmt::ParenListExprClass:
1905 case Stmt::ShuffleVectorExprClass:
1906 case Stmt::ConvertVectorExprClass:
1907 case Stmt::VAArgExprClass:
1908 case Stmt::CUDAKernelCallExprClass:
1909 case Stmt::OpaqueValueExprClass:
1910 case Stmt::AsTypeExprClass:
1911 case Stmt::ConceptSpecializationExprClass:
1912 case Stmt::CXXRewrittenBinaryOperatorClass:
1913 case Stmt::RequiresExprClass:
1914 case Stmt::EmbedExprClass:
1919 case Stmt::PredefinedExprClass:
1920 case Stmt::AddrLabelExprClass:
1921 case Stmt::IntegerLiteralClass:
1922 case Stmt::FixedPointLiteralClass:
1923 case Stmt::CharacterLiteralClass:
1924 case Stmt::CXXScalarValueInitExprClass:
1925 case Stmt::CXXBoolLiteralExprClass:
1926 case Stmt::ObjCBoolLiteralExprClass:
1927 case Stmt::ObjCAvailabilityCheckExprClass:
1928 case Stmt::FloatingLiteralClass:
1929 case Stmt::NoInitExprClass:
1930 case Stmt::SizeOfPackExprClass:
1931 case Stmt::StringLiteralClass:
1932 case Stmt::SourceLocExprClass:
1933 case Stmt::ObjCStringLiteralClass:
1934 case Stmt::CXXPseudoDestructorExprClass:
1935 case Stmt::SubstNonTypeTemplateParmExprClass:
1936 case Stmt::CXXNullPtrLiteralExprClass:
1937 case Stmt::ArraySectionExprClass:
1938 case Stmt::OMPArrayShapingExprClass:
1939 case Stmt::OMPIteratorExprClass:
1940 case Stmt::SYCLUniqueStableNameExprClass:
1941 case Stmt::OpenACCAsteriskSizeExprClass:
1942 case Stmt::TypeTraitExprClass: {
1949 case Stmt::AttributedStmtClass: {
1954 case Stmt::CXXDefaultArgExprClass:
1955 case Stmt::CXXDefaultInitExprClass: {
1962 if (
const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
1963 ArgE = DefE->getExpr();
1964 else if (
const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
1965 ArgE = DefE->getExpr();
1967 llvm_unreachable(
"unknown constant wrapper kind");
1969 bool IsTemporary =
false;
1970 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
1971 ArgE = MTE->getSubExpr();
1975 std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
1980 for (
const auto I : PreVisit) {
1982 State = State->BindExpr(
cast<Expr>(S), SF, *ConstantVal);
1984 State = createTemporaryRegionIfNeeded(State, SF,
cast<Expr>(S),
1986 Tmp.
insert(Engine.makePostStmtNode(S, State, I));
1994 case Stmt::CXXStdInitializerListExprClass:
1995 case Expr::ObjCArrayLiteralClass:
1996 case Expr::ObjCDictionaryLiteralClass:
1997 case Expr::ObjCBoxedExprClass: {
2004 QualType resultType = Ex->getType();
2006 for (
const auto N : preVisit) {
2008 SVal result = svalBuilder.conjureSymbolVal(
2018 for (
auto Child : Ex->children()) {
2020 const auto *ChildExpr = dyn_cast<Expr>(Child);
2021 SVal Val = ChildExpr ? State->getSVal(ChildExpr, SF) :
UnknownVal();
2025 Tmp.
insert(Engine.makePostStmtNode(S, State, N));
2032 case Stmt::ArraySubscriptExprClass:
2036 case Stmt::MatrixSingleSubscriptExprClass:
2038 "Support for MatrixSingleSubscriptExprClass is not implemented.");
2041 case Stmt::MatrixSubscriptExprClass:
2042 llvm_unreachable(
"Support for MatrixSubscriptExpr is not implemented.");
2045 case Stmt::GCCAsmStmtClass: {
2055 case Stmt::MSAsmStmtClass:
2059 case Stmt::BlockExprClass:
2063 case Stmt::LambdaExprClass:
2064 if (AMgr.options.ShouldInlineLambdas) {
2073 case Stmt::BinaryOperatorClass: {
2075 if (B->isLogicalOp()) {
2078 }
else if (B->getOpcode() == BO_Comma) {
2081 Dst.
insert(Engine.makeNodeWithBinding(Pred, B, Val));
2085 if (AMgr.options.ShouldEagerlyAssume &&
2086 (B->isRelationalOp() || B->isEqualityOp())) {
2097 case Stmt::CXXOperatorCallExprClass:
2098 case Stmt::CallExprClass:
2099 case Stmt::CXXMemberCallExprClass:
2100 case Stmt::UserDefinedLiteralClass:
2104 case Stmt::CXXCatchStmtClass:
2108 case Stmt::CXXTemporaryObjectExprClass:
2109 case Stmt::CXXConstructExprClass:
2113 case Stmt::CXXInheritedCtorInitExprClass:
2118 case Stmt::CXXNewExprClass: {
2124 for (
const auto i : PreVisit)
2131 case Stmt::CXXDeleteExprClass: {
2138 for (
const auto i : PostVisit)
2146 case Stmt::ChooseExprClass: {
2152 case Stmt::CompoundAssignOperatorClass:
2156 case Stmt::CompoundLiteralExprClass:
2160 case Stmt::BinaryConditionalOperatorClass:
2161 case Stmt::ConditionalOperatorClass: {
2167 case Stmt::CXXThisExprClass:
2171 case Stmt::DeclRefExprClass: {
2177 case Stmt::DeclStmtClass:
2181 case Stmt::ImplicitCastExprClass:
2182 case Stmt::CStyleCastExprClass:
2183 case Stmt::CXXStaticCastExprClass:
2184 case Stmt::CXXDynamicCastExprClass:
2185 case Stmt::CXXReinterpretCastExprClass:
2186 case Stmt::CXXConstCastExprClass:
2187 case Stmt::CXXFunctionalCastExprClass:
2188 case Stmt::BuiltinBitCastExprClass:
2189 case Stmt::ObjCBridgedCastExprClass:
2190 case Stmt::CXXAddrspaceCastExprClass: {
2200 case Expr::MaterializeTemporaryExprClass: {
2205 for (
const auto i : dstPrevisit)
2211 case Stmt::InitListExprClass: {
2217 case Expr::CXXParenListInitExprClass: {
2224 case Stmt::MemberExprClass:
2228 case Stmt::AtomicExprClass:
2232 case Stmt::ObjCIvarRefExprClass:
2236 case Stmt::ObjCForCollectionStmtClass:
2240 case Stmt::ObjCMessageExprClass:
2244 case Stmt::ObjCAtThrowStmtClass:
2245 case Stmt::CXXThrowExprClass:
2248 Engine.makePostStmtNode(S, Pred->
getState(), Pred,
true);
2251 case Stmt::ReturnStmtClass:
2255 case Stmt::OffsetOfExprClass: {
2260 for (
const auto Node : PreVisit)
2267 case Stmt::UnaryExprOrTypeTraitExprClass:
2272 case Stmt::StmtExprClass: {
2275 if (SE->getSubStmt()->body_empty()) {
2278 &&
"Empty statement expression must have void type.");
2279 }
else if (
const auto *LastExpr =
2280 dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
2282 Pred = Engine.makeNodeWithBinding(Pred, SE, Val);
2288 case Stmt::UnaryOperatorClass: {
2290 if (AMgr.options.ShouldEagerlyAssume && (
U->getOpcode() == UO_LNot)) {
2300 case Stmt::PseudoObjectExprClass: {
2303 if (
const Expr *
Result = PE->getResultExpr())
2305 Dst.
insert(Engine.makeNodeWithBinding(Pred, PE,
V));
2309 case Expr::ObjCIndirectCopyRestoreExprClass: {
2314 const Expr *E = OIE->getSubExpr();
2316 Dst.
insert(Engine.makeNodeWithBinding(Pred, OIE,
V));
2325 assert(CalleeSF && CallerSF);
2332 BeforeProcessingCall = N;
2347 if (SP->getStmt() == CE)
2352 if (!BeforeProcessingCall)
2388 NumTimesRetriedWithoutInlining++;
2402 if(AMgr.options.ShouldUnrollLoops) {
2403 unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
2407 Pred, maxBlockVisitOnPath);
2408 if (NewState != Pred->
getState()) {
2409 ExplodedNode *UpdatedNode = Builder.generateNode(BE, NewState, Pred);
2423 if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
2424 AMgr.options.ShouldWidenLoops) {
2426 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
2440 Builder.generateNode(BE, WidenedState, Pred);
2445 if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
2449 Builder.generateSink(TaggedLoc, Pred->
getState(), Pred);
2462 Engine.FunctionSummaries->markShouldNotInline(SF->
getDecl());
2468 if ((!AMgr.options.NoRetryExhausted && replayWithoutInlining(Pred, SF)))
2470 NumMaxBlockCountReachedInInlined++;
2472 NumMaxBlockCountReached++;
2475 Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
2482 llvm::PrettyStackTraceFormat CrashInfo(
2483 "Processing block entrance B%d -> B%d",
2501 const auto *Ex = dyn_cast<Expr>(
Condition);
2506 bool bitsInit =
false;
2508 while (
const auto *CE = dyn_cast<CastExpr>(Ex)) {
2511 if (!T->isIntegralOrEnumerationType())
2515 if (!bitsInit || newBits < bits) {
2520 Ex = CE->getSubExpr();
2526 if (!bitsInit || !T->isIntegralOrEnumerationType() ||
2530 return state->getSVal(Ex, SF);
2536 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2537 if (!BO || !BO->isLogicalOp()) {
2540 Condition = BO->getRHS()->IgnoreParens();
2562 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2565 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2566 if (!BO || !BO->isLogicalOp())
2570 "Other kinds of branches are handled separately!");
2581 std::optional<CFGStmt> CS = Elem.getAs<
CFGStmt>();
2584 const Stmt *LastStmt = CS->getStmt();
2588 llvm_unreachable(
"could not resolve condition");
2592 std::pair<const ObjCForCollectionStmt *, const StackFrame *>;
2598 bool HasMoreIteraton) {
2599 assert(!State->contains<ObjCForHasMoreIterations>({O, SF}));
2600 return State->set<ObjCForHasMoreIterations>({O, SF}, HasMoreIteraton);
2606 assert(State->contains<ObjCForHasMoreIterations>({O, SF}));
2607 return State->remove<ObjCForHasMoreIterations>({O, SF});
2613 assert(State->contains<ObjCForHasMoreIterations>({O, SF}));
2614 return *State->get<ObjCForHasMoreIterations>({O, SF});
2620static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
2623 if (
const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(ConditionStmt)) {
2624 bool HasMoreIteraton =
2631 if (HasMoreIteraton)
2632 return std::pair<ProgramStateRef, ProgramStateRef>{State,
nullptr};
2634 return std::pair<ProgramStateRef, ProgramStateRef>{
nullptr, State};
2637 const auto *ConditionExpr = dyn_cast<Expr>(ConditionStmt);
2638 assert(ConditionExpr &&
"The condition must be an Expr from here!");
2642 if (
X.isUnknownOrUndef()) {
2644 if (
const auto *Ex = dyn_cast<Expr>(ConditionExpr)) {
2645 if (Ex->getType()->isIntegralOrEnumerationType()) {
2652 N->
getState()->getStateManager().getContext());
2662 if (
X.isUnknownOrUndef())
2663 return std::nullopt;
2668 return State->assume(
V);
2674 std::optional<unsigned> IterationsCompletedInLoop) {
2676 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2692 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2698 "Error evaluating branch");
2704 if (CheckersOutSet.
empty())
2712 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2714 if (StTrue && StFalse)
2725 (StTrue && StFalse) ||
2744 bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;
2745 bool SkipTrueBranch = BothFeasible && CompletedTwoIterations;
2751 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops) {
2754 Dst.
insert(Engine.makeNode(BE, StTrue, PredN));
2756 }
else if (!AMgr.options.InlineFunctionsWithAmbiguousLoops) {
2773 Engine.FunctionSummaries->markShouldNotInline(SF->
getDecl());
2791 bool BeforeFirstIteration = IterationsCompletedInLoop == std::optional{0};
2792 bool SkipFalseBranch = BothFeasible && BeforeFirstIteration &&
2793 AMgr.options.ShouldAssumeAtLeastOneIteration;
2794 if (!SkipFalseBranch && DstF) {
2796 Dst.
insert(Engine.makeNode(BE, StFalse, PredN));
2805 llvm::ImmutableSet<const VarDecl *>)
2814 bool InitHasRun = State->contains<InitializedGlobalsSet>(VD);
2816 State = State->add<InitializedGlobalsSet>(VD);
2818 if (
const CFGBlock *DstBlock = InitHasRun ? DstT : DstF) {
2852 Dst.
insert(Engine.makeNode(BE, State, Pred));
2870 State = finishArgumentConstruction(
2885 while (SF != ToSF) {
2886 assert(SF &&
"ToSF must be a parent of FromSF!");
2887 for (
auto I : State->get<ObjectsUnderConstruction>())
2888 if (I.first.getStackFrame() == SF) {
2892 assert(I.first.getItem().getKind() ==
2894 I.first.getItem().getKind() ==
2896 State = State->remove<ObjectsUnderConstruction>(I.first);
2904 Pred = Engine.makeNode(Pred->
getLocation(), State, Pred);
2921 for (
const auto I : AfterRemovedDead)
2927 Engine.enqueueEndOfFunction(Dst, RS);
2941 assert(SwitchBlock->
succ_size() &&
"Switch must have at least one successor");
2947 llvm::iterator_range<CFGBlock::const_succ_reverse_iterator> CaseBlocks(
2954 Condition->IgnoreParens(), CheckersOutSet, Pred, *
this);
2964 std::optional<NonLoc> CondNL = CondV.
getAs<
NonLoc>();
2966 for (
const CFGBlock *CaseBlock : CaseBlocks) {
2975 assert(V1.getBitWidth() ==
2981 V2 = E->EvaluateKnownConstInt(ACtx);
2988 std::tie(StateMatching, State) =
2989 State->assumeInclusiveRange(*CondNL, V1, V2);
2993 StateMatching = State;
2996 if (StateMatching) {
2997 BlockEdge BE(SwitchBlock, CaseBlock, SF);
2998 Dst.
insert(Engine.makeNode(BE, StateMatching, Node));
3020 if (
Condition->IgnoreParenImpCasts()->getType()->isEnumeralType()) {
3021 if (
Switch->isAllEnumCasesCovered())
3025 BlockEdge BE(SwitchBlock, DefaultBlock, SF);
3026 Dst.
insert(Engine.makeNode(BE, State, Node));
3040 auto resolveAsLambdaCapturedVar =
3041 [&](
const ValueDecl *VD) -> std::optional<std::pair<SVal, QualType>> {
3042 const auto *MD = dyn_cast<CXXMethodDecl>(SF->
getDecl());
3043 const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
3044 if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
3045 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
3046 MD->getParent()->isLambda()) {
3049 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
3055 if (
const FieldDecl *FD = LambdaCaptureFields[VD]) {
3056 Loc CXXThis = svalBuilder.getCXXThis(MD, SF);
3058 return std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
3062 return std::nullopt;
3065 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
3068 assert(Ex->
isGLValue() || VD->getType()->isVoidType());
3069 std::optional<std::pair<SVal, QualType>> VInfo =
3070 resolveAsLambdaCapturedVar(VD);
3073 VInfo = std::make_pair(state->getLValue(VD, SF), VD->getType());
3075 SVal V = VInfo->first;
3076 bool IsReference = VInfo->second->isReferenceType();
3082 V = state->getSVal(R);
3091 if (
const auto *ED = dyn_cast<EnumConstantDecl>(D)) {
3093 SVal V = svalBuilder.makeIntVal(ED->getInitVal());
3094 Dst.
insert(Engine.makeNodeWithBinding(Pred, Ex,
V));
3097 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
3098 SVal V = svalBuilder.getFunctionPointer(FD);
3109 if (
const auto *BD = dyn_cast<BindingDecl>(D)) {
3111 if (std::optional<std::pair<SVal, QualType>> VInfo =
3112 resolveAsLambdaCapturedVar(BD)) {
3113 auto [
V, T] = VInfo.value();
3115 if (T->isReferenceType()) {
3117 V = state->getSVal(R);
3122 Dst.
insert(Engine.makeNodeWithBinding(Pred, Ex,
V,
3129 SVal Base = state->getLValue(DD, SF);
3130 if (DD->getType()->isReferenceType()) {
3132 Base = state->getSVal(R);
3140 if (
const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
3142 V = state->getLValue(Field,
Base);
3145 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {
3146 SVal Idx = state->getSVal(ASE->getIdx(), SF);
3151 assert(Idx.
isConstant() &&
"BindingDecl array index is not a constant!");
3153 V = state->getLValue(BD->getType(), Idx,
Base);
3156 else if (
const auto *HV = BD->getHoldingVar()) {
3157 V = state->getLValue(HV, SF);
3159 if (HV->getType()->isReferenceType()) {
3161 V = state->getSVal(R);
3166 llvm_unreachable(
"An unknown case of structured binding encountered!");
3170 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3172 V = state->getSVal(R);
3182 if (
const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
3189 llvm_unreachable(
"Support for this Decl not implemented.");
3200 NodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
3204 for (
auto *Node : CheckerPreStmt) {
3210 const StackFrame *SF = Node->getStackFrame();
3249 if (
const auto *ME = dyn_cast<MemberExpr>(Arr)) {
3250 Expr *MEBase = ME->getBase();
3253 if (
auto CXXSCE = dyn_cast<CXXStaticCastExpr>(MEBase)) {
3254 MEBase = CXXSCE->getSubExpr();
3275 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arr))
3280 Base = state->getSVal(R);
3308 (A->
getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
3310 for (
auto *Node : CheckerPreStmt) {
3311 const StackFrame *SF = Node->getStackFrame();
3314 if (IsGLValueLike) {
3320 if (T->isVoidType())
3323 SVal V = state->getLValue(T, state->getSVal(Idx, SF),
3324 state->getSVal(
Base, SF));
3327 }
else if (IsVectorType) {
3329 EvalSet.
insert(Engine.makePostStmtNode(A, state, Node));
3331 llvm_unreachable(
"Array subscript should be an lValue when not \
3332a vector and not a forbidden lvalue type");
3352 for (
const auto I : CheckedSet)
3355 NodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
3358 for (
const auto I : CheckedSet) {
3364 if (
const auto *MD = dyn_cast<CXXMethodDecl>(
Member)) {
3365 if (MD->isImplicitObjectMemberFunction())
3366 state = createTemporaryRegionIfNeeded(state, SF, BaseExpr);
3368 SVal MDVal = svalBuilder.getFunctionPointer(MD);
3369 state = state->BindExpr(M, SF, MDVal);
3377 state = createTemporaryRegionIfNeeded(state, SF, BaseExpr,
3384 if (
const auto *SR =
3385 dyn_cast_or_null<SymbolicRegion>(baseExprVal.
getAsRegion())) {
3386 QualType T = SR->getPointeeStaticType();
3392 SVal L = state->getLValue(field, baseExprVal);
3402 dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
3403 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
3404 llvm_unreachable(
"should always be wrapped in ArrayToPointerDecay");
3408 if (field->getType()->isReferenceType()) {
3410 L = state->getSVal(R);
3415 Bldr.
generateNode(M, I, state->BindExpr(M, SF, L),
nullptr,
3437 NodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx);
3439 for (
const auto I : AfterPreSet) {
3444 for (
unsigned SI = 0, Count = AE->
getNumSubExprs(); SI != Count; SI++) {
3446 SVal SubExprVal = State->getSVal(SubExpr, SF);
3447 ValuesToInvalidate.push_back(SubExprVal);
3456 State = State->BindExpr(AE, SF, ResultVal);
3475 for (
const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
3477 const MemRegion *MR = LocAndVal.first.getAsRegion();
3480 Escaped.push_back(LocAndVal.second);
3485 if (
const auto *VR = dyn_cast<VarRegion>(MR->
getBaseRegion()))
3487 VR->getStackFrame()->inTopFrame())
3488 if (
const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3489 if (!RD->hasTrivialDestructor()) {
3490 Escaped.push_back(LocAndVal.second);
3499 SVal StoredVal = State->getSVal(MR);
3500 if (StoredVal != LocAndVal.second)
3503 Escaped.push_back(LocAndVal.second);
3506 if (Escaped.empty())
3515 std::pair<SVal, SVal> LocAndVal(
Loc, Val);
3526 if (!Invalidated || Invalidated->empty())
3539 for (
const auto I : ExplicitRegions) {
3541 SymbolsDirectlyInvalidated.insert(R->getSymbol());
3545 for (
const auto &sym : *Invalidated) {
3546 if (SymbolsDirectlyInvalidated.count(sym))
3548 SymbolsIndirectlyInvalidated.insert(sym);
3551 if (!SymbolsDirectlyInvalidated.empty())
3556 if (!SymbolsIndirectlyInvalidated.empty())
3570 assert(!
isa<NonLoc>(Location) &&
"evalBind location should not be NonLoc!");
3581 StoreE, AtDeclInit, *
this, *PP);
3589 if (
auto AsLoc = Location.getAs<
Loc>()) {
3593 State = State->bindLoc(*AsLoc, Val, SF, !AtDeclInit);
3596 PostStore PS(StoreE, SF, Location.getAsRegion(),
nullptr);
3610 const Expr *LocationE,
3616 const Expr *StoreE = AssignE ? AssignE : LocationE;
3620 evalLocation(Tmp, AssignE, LocationE, Pred, state, location,
false);
3628 for (
const auto I : Tmp)
3629 evalBind(Dst, StoreE, I, location, Val,
false);
3634 const Expr *BoundEx,
3640 assert(!
isa<NonLoc>(location) &&
"location cannot be a NonLoc.");
3645 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location,
true);
3654 for (
const auto I : Tmp) {
3655 state = I->getState();
3661 V = state->getSVal(location.
castAs<
Loc>(), LoadTy);
3665 state->BindExpr(BoundEx, I->getStackFrame(),
V), tag,
3672 const Stmt *BoundEx,
3684 BldrTop.takeNodes(Pred);
3697 Bldr.generateNode(NodeEx, Pred, state, &tag);
3701 NodeEx, BoundEx, *
this);
3702 BldrTop.addNodes(Tmp);
3705std::pair<const ProgramPointTag *, const ProgramPointTag *>
3708 FalseTag(TagProviderName,
"Eagerly Assume False");
3710 return std::make_pair(&TrueTag, &FalseTag);
3734 State = State->set<LastEagerlyAssumeExprIfSuccessful>(
nullptr);
3737 if (SEV && SEV->isExpression()) {
3740 auto [StateTrue, StateFalse] = State->assume(*SEV);
3742 if (StateTrue && StateFalse) {
3743 StateTrue = StateTrue->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3744 StateFalse = StateFalse->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3750 StateTrue = StateTrue->BindExpr(Ex, Pred->
getStackFrame(), Val);
3757 StateFalse = StateFalse->BindExpr(Ex, Pred->
getStackFrame(), Val);
3765 const Expr *Ex)
const {
3766 return Ex && State->get<LastEagerlyAssumeExprIfSuccessful>() == Ex;
3785 if (std::optional<Loc> LV =
X.getAs<
Loc>())
3796 if (std::optional<Loc> LV =
X.getAs<
Loc>())
3827 for (
const auto &
Report : Class.getReports()) {
3828 const auto *PR = dyn_cast<PathSensitiveBugReport>(
Report.get());
3846 llvm::function_ref<
void(
const ExplodedNode *)> PreCallback,
3847 llvm::function_ref<
void(
const ExplodedNode *)> PostCallback,
3869 llvm::raw_string_ostream Out(Buf);
3871 const bool IsDot =
true;
3872 const unsigned int Space = 1;
3875 Out <<
"{ \"state_id\": " << State->getID()
3878 Indent(Out, Space, IsDot) <<
"\"program_points\": [\\l";
3884 Indent(Out, Space + 1, IsDot) <<
"{ ";
3886 Out <<
", \"tag\": ";
3888 Out <<
'\"' << Tag->getDebugTag() <<
'\"';
3891 Out <<
", \"node_id\": " << OtherNode->
getID() <<
3892 ", \"is_sink\": " << OtherNode->
isSink() <<
3900 Indent(Out, Space, IsDot) <<
"],\\l";
3913 llvm::DisplayGraph(Filename,
false, llvm::GraphProgram::DOT);
3917 std::string Filename =
DumpGraph(Nodes);
3918 llvm::DisplayGraph(Filename,
false, llvm::GraphProgram::DOT);
3923 std::vector<const ExplodedNode *> Src;
3926 for (
const auto &
Class : BR.equivalenceClasses()) {
3928 dyn_cast<PathSensitiveBugReport>(
Class.getReports()[0].get());
3931 const auto *N =
const_cast<ExplodedNode *
>(R->getErrorNode());
3938 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
3939 return llvm::WriteGraph(&G,
"ExprEngine",
false,
3941 std::string(Filename));
3945 StringRef Filename) {
3946 std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
3949 llvm::errs() <<
"warning: Trimmed ExplodedGraph is empty.\n";
3954 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
3955 return llvm::WriteGraph(TrimmedG.get(),
"TrimmedExprEngine",
3957 "Trimmed Exploded Graph",
3958 std::string(Filename));
3962 static int index = 0;
3966void ExprEngine::anchor() { }
3979 bool IsCompound = T->
isArrayType() || T->isRecordType() ||
3980 T->isAnyComplexType() || T->isVectorType();
3982 if (Args.size() > 1 || (E->
isPRValue() && IsCompound && !IsTransparent)) {
3984 for (
Expr *E : llvm::reverse(Args))
3988 S->BindExpr(E, SF, svalBuilder.makeCompoundVal(T, ArgList)));
3994 : S->getSVal(Args.front(), SF)));
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,...
static unsigned getNumSubExprs(AtomicOp Op)
Determine the number of arguments the specified atomic builtin should have.
const CFGBlock * getPreviousBlock() const
const CFGBlock * getBlock() const
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
const VarDecl * getVarDecl() const
const Stmt * getTriggerStmt() const
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.
const CXXDeleteExpr * getDeleteExpr() const
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.
void takeNodes(const ExplodedNodeSet &S)
ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred, bool MarkAsSink=false)
Generates a node in the ExplodedGraph.
void addNodes(const ExplodedNodeSet &S)
While alive, includes the current analysis stack in a crash trace.
Information about invalidation for a particular region/symbol.
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)