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)
1141 if (
ExplodedNode *N = Engine.makeNode(PP, NewState, Pred))
1142 Engine.enqueueStmtNode(N,
getCurrBlock(), currStmtIdx);
1149 "Error evaluating end of a lifetime");
1155 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1166 "Error evaluating initializer");
1172 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(
decl, SF));
1184 State = finishObjectConstruction(State, BMI, SF);
1186 Tmp.
insert(Engine.makeNode(PS, State, Pred));
1194 FieldLoc = State->getLValue(BMI->
getMember(), thisVal);
1198 if (Field->getType()->isArrayType()) {
1202 while ((ASE = dyn_cast<ArraySubscriptExpr>(
Init)))
1205 InitVal = State->getSVal(
Init, SF);
1214 InitVal = State->getSVal(BMI->
getInit(), SF);
1218 evalBind(Tmp,
Init, Pred, FieldLoc, InitVal,
true, &PP);
1226 SVal InitVal = State->getSVal(
Init, SF);
1227 evalBind(Tmp,
Init, Pred, BaseLoc, InitVal,
true);
1242 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1245std::pair<ProgramStateRef, uint64_t>
1246ExprEngine::prepareStateForArrayDestruction(
const ProgramStateRef State,
1250 SVal *ElementCountVal) {
1251 assert(Region !=
nullptr &&
"Not-null region expected");
1254 while (
const auto *NTy = dyn_cast<ArrayType>(Ty))
1255 Ty = NTy->getElementType().getDesugaredType(
getContext());
1259 if (ElementCountVal)
1260 *ElementCountVal = ElementCount;
1268 if (!ElementCount.isConstant())
1271 Idx = ElementCount.getAsInteger()->getLimitedValue();
1279 return {setPendingArrayDestruction(State, SF, Idx), Idx};
1302 llvm_unreachable(
"Unexpected dtor kind.");
1306 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1317 if (Opts.MayInlineCXXAllocator)
1325 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1331 const auto *DtorDecl = Dtor.getDestructorDecl(
getContext());
1342 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
1357 std::tie(state, Idx) = prepareStateForArrayDestruction(
1358 state, Region, varType, SF, &ElementCount);
1360 if (ElementCount.isConstant()) {
1361 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1362 assert(ArrayLength &&
1363 "An automatic dtor for a 0 length array shouldn't be triggered!");
1368 "ExprEngine",
"Skipping automatic 0 length array destruction, "
1369 "which shouldn't be in the CFG.");
1372 Engine.makeNode(PP, Pred->
getState(), Pred,
true);
1384 "Prepare for object destruction");
1387 Pred = Engine.makeNode(PP, state, Pred);
1393 false, Pred, Dst, CallOpts);
1404 SVal ArgVal = State->getSVal(Arg, SF);
1408 if (State->isNull(ArgVal).isConstrainedTrue()) {
1418 auto getDtorDecl = [](
const QualType &DTy) {
1430 while (
const auto *AT =
getContext().getAsArrayType(DTy))
1431 DTy = AT->getElementType();
1435 std::tie(State, Idx) =
1436 prepareStateForArrayDestruction(State, ArgR, DTy, SF, &ElementCount);
1440 if (ElementCount.isConstant() &&
1441 ElementCount.getAsInteger()->getLimitedValue() == 0) {
1444 "ExprEngine",
"Skipping 0 length array delete destruction");
1451 ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
1457 "Prepare for object destruction");
1460 Pred = Engine.makeNode(PP, State, Pred);
1484 true, Pred, Dst, CallOpts);
1497 Loc ThisLoc = State->getSVal(ThisStorageLoc).
castAs<
Loc>();
1498 SVal FieldVal = State->getLValue(
Member, ThisLoc);
1503 std::tie(State, Idx) = prepareStateForArrayDestruction(
1504 State, FieldVal.getAsRegion(),
T, SF, &ElementCount);
1506 if (ElementCount.isConstant()) {
1507 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1508 assert(ArrayLength &&
1509 "A member dtor for a 0 length array shouldn't be triggered!");
1514 "ExprEngine",
"Skipping member 0 length array destruction, which "
1515 "shouldn't be in the CFG.");
1518 Engine.makeNode(PP, Pred->
getState(), Pred,
true);
1529 "Prepare for object destruction");
1532 Pred = Engine.makeNode(PP, State, Pred);
1538 false, Pred, Dst, CallOpts);
1553 State = finishObjectConstruction(State, BTE, SF);
1554 MR =
V->getAsRegion();
1559 if (isDestructorElided(State, BTE, SF)) {
1560 State = cleanupElidedDestructor(State, BTE, SF);
1563 Dst.
insert(Engine.makeNode(PP, State, Pred));
1567 ExplodedNode *CleanPred = Engine.makePostStmtNode(BTE, State, Pred);
1597 T = AT->getElementType();
1608 false, CleanPred, Dst, CallOpts);
1620 if (
const CFGBlock *DstBlock = Obj ? DstT : DstF) {
1622 Dst.
insert(Engine.makeNode(BE, State, Pred));
1640 const StackFrame *SF = Node->getStackFrame();
1646 State = addObjectUnderConstruction(State, BTE, SF,
UnknownVal());
1648 Dst.
insert(Engine.makePostStmtNode(BTE, State, Node));
1656 class CollectReachableSymbolsCallback final :
public SymbolVisitor {
1661 : Symbols(Symbols) {}
1665 bool VisitSymbol(
SymbolRef Sym)
override {
1666 Symbols.insert(Sym);
1671 CollectReachableSymbolsCallback CallBack(Symbols);
1673 State->scanReachableSymbols(
V, CallBack);
1676 State, CallBack.getSymbols(),
Call, K,
nullptr);
1688 case Stmt::CXXDependentScopeMemberExprClass:
1689 case Stmt::CXXReflectExprClass:
1690 case Stmt::CXXTryStmtClass:
1691 case Stmt::CXXTypeidExprClass:
1692 case Stmt::CXXUuidofExprClass:
1693 case Stmt::CXXFoldExprClass:
1694 case Stmt::MSPropertyRefExprClass:
1695 case Stmt::MSPropertySubscriptExprClass:
1696 case Stmt::CXXUnresolvedConstructExprClass:
1697 case Stmt::DependentScopeDeclRefExprClass:
1698 case Stmt::ArrayTypeTraitExprClass:
1699 case Stmt::ExpressionTraitExprClass:
1700 case Stmt::UnresolvedLookupExprClass:
1701 case Stmt::UnresolvedMemberExprClass:
1702 case Stmt::DependentTemplateIdExprClass:
1703 case Stmt::RecoveryExprClass:
1704 case Stmt::CXXNoexceptExprClass:
1705 case Stmt::PackExpansionExprClass:
1706 case Stmt::PackIndexingExprClass:
1707 case Stmt::SubstNonTypeTemplateParmPackExprClass:
1708 case Stmt::FunctionParmPackExprClass:
1709 case Stmt::CoroutineBodyStmtClass:
1710 case Stmt::CoawaitExprClass:
1711 case Stmt::DependentCoawaitExprClass:
1712 case Stmt::CoreturnStmtClass:
1713 case Stmt::CoyieldExprClass:
1714 case Stmt::SEHTryStmtClass:
1715 case Stmt::SEHExceptStmtClass:
1716 case Stmt::SEHLeaveStmtClass:
1717 case Stmt::SEHFinallyStmtClass:
1718 case Stmt::CXXExpansionStmtPatternClass:
1719 case Stmt::CXXExpansionStmtInstantiationClass:
1720 case Stmt::CXXExpansionSelectExprClass:
1721 case Stmt::OMPCanonicalLoopClass:
1722 case Stmt::OMPParallelDirectiveClass:
1723 case Stmt::OMPSimdDirectiveClass:
1724 case Stmt::OMPForDirectiveClass:
1725 case Stmt::OMPForSimdDirectiveClass:
1726 case Stmt::OMPSectionsDirectiveClass:
1727 case Stmt::OMPSectionDirectiveClass:
1728 case Stmt::OMPScopeDirectiveClass:
1729 case Stmt::OMPSingleDirectiveClass:
1730 case Stmt::OMPMasterDirectiveClass:
1731 case Stmt::OMPCriticalDirectiveClass:
1732 case Stmt::OMPParallelForDirectiveClass:
1733 case Stmt::OMPParallelForSimdDirectiveClass:
1734 case Stmt::OMPParallelSectionsDirectiveClass:
1735 case Stmt::OMPParallelMasterDirectiveClass:
1736 case Stmt::OMPParallelMaskedDirectiveClass:
1737 case Stmt::OMPTaskDirectiveClass:
1738 case Stmt::OMPTaskyieldDirectiveClass:
1739 case Stmt::OMPBarrierDirectiveClass:
1740 case Stmt::OMPTaskwaitDirectiveClass:
1741 case Stmt::OMPErrorDirectiveClass:
1742 case Stmt::OMPTaskgroupDirectiveClass:
1743 case Stmt::OMPFlushDirectiveClass:
1744 case Stmt::OMPDepobjDirectiveClass:
1745 case Stmt::OMPScanDirectiveClass:
1746 case Stmt::OMPOrderedStandaloneDirectiveClass:
1747 case Stmt::OMPOrderedBlockAssocDirectiveClass:
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: {
2137 for (
const auto i : PreVisit)
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)
2391 NumTimesRetriedWithoutInlining++;
2401 unsigned MaxBlockVisit = AMgr.options.maxBlockVisitOnPath;
2405 if (AMgr.options.ShouldUnrollLoops) {
2407 State =
updateLoopStack(Term, AMgr.getASTContext(), Pred, MaxBlockVisit);
2410 return Engine.makeNode(BE, State, Pred);
2416 if (BlockCount == MaxBlockVisit - 1 && AMgr.options.ShouldWidenLoops) {
2417 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
2418 return Engine.makeNode(BE, State, Pred);
2428 return Engine.makeNode(BE, WidenedState, Pred);
2432 if (BlockCount < MaxBlockVisit)
2433 return Engine.makeNode(BE, State, Pred);
2438 Engine.makeNode(BE.
withTag(&Tag), State, Pred,
true);
2450 Engine.FunctionSummaries->markShouldNotInline(SF->
getDecl());
2456 if (!AMgr.options.NoRetryExhausted && replayWithoutInlining(Pred, SF))
2458 NumMaxBlockCountReachedInInlined++;
2460 NumMaxBlockCountReached++;
2463 Engine.blocksExhausted.push_back(std::make_pair(BE, Sink));
2471 llvm::PrettyStackTraceFormat CrashInfo(
2472 "Processing block entrance B%d -> B%d",
2490 const auto *Ex = dyn_cast<Expr>(
Condition);
2495 bool bitsInit =
false;
2497 while (
const auto *CE = dyn_cast<CastExpr>(Ex)) {
2500 if (!
T->isIntegralOrEnumerationType())
2504 if (!bitsInit || newBits < bits) {
2509 Ex = CE->getSubExpr();
2515 if (!bitsInit || !
T->isIntegralOrEnumerationType() ||
2519 return state->getSVal(Ex, SF);
2525 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2526 if (!BO || !BO->isLogicalOp()) {
2529 Condition = BO->getRHS()->IgnoreParens();
2551 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2554 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2555 if (!BO || !BO->isLogicalOp())
2559 "Other kinds of branches are handled separately!");
2570 std::optional<CFGStmt> CS = Elem.getAs<
CFGStmt>();
2573 const Stmt *LastStmt = CS->getStmt();
2577 llvm_unreachable(
"could not resolve condition");
2581 std::pair<const ObjCForCollectionStmt *, const StackFrame *>;
2587 bool HasMoreIteraton) {
2588 assert(!State->contains<ObjCForHasMoreIterations>({O, SF}));
2589 return State->set<ObjCForHasMoreIterations>({O, SF}, HasMoreIteraton);
2595 assert(State->contains<ObjCForHasMoreIterations>({O, SF}));
2596 return State->remove<ObjCForHasMoreIterations>({O, SF});
2602 assert(State->contains<ObjCForHasMoreIterations>({O, SF}));
2603 return *State->get<ObjCForHasMoreIterations>({O, SF});
2609static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
2612 if (
const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(ConditionStmt)) {
2613 bool HasMoreIteraton =
2620 if (HasMoreIteraton)
2621 return std::pair<ProgramStateRef, ProgramStateRef>{State,
nullptr};
2623 return std::pair<ProgramStateRef, ProgramStateRef>{
nullptr, State};
2626 const auto *ConditionExpr = dyn_cast<Expr>(ConditionStmt);
2627 assert(ConditionExpr &&
"The condition must be an Expr from here!");
2631 if (
X.isUnknownOrUndef()) {
2633 if (
const auto *Ex = dyn_cast<Expr>(ConditionExpr)) {
2634 if (Ex->getType()->isIntegralOrEnumerationType()) {
2641 N->
getState()->getStateManager().getContext());
2651 if (
X.isUnknownOrUndef())
2652 return std::nullopt;
2656 return State->assume(
V);
2662 std::optional<unsigned> IterationsCompletedInLoop) {
2664 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2680 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2686 "Error evaluating branch");
2692 if (CheckersOutSet.
empty())
2700 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2702 if (StTrue && StFalse)
2713 (StTrue && StFalse) ||
2732 bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;
2733 bool SkipTrueBranch = BothFeasible && CompletedTwoIterations;
2739 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops) {
2742 Dst.
insert(Engine.makeNode(BE, StTrue, PredN));
2744 }
else if (!AMgr.options.InlineFunctionsWithAmbiguousLoops) {
2761 Engine.FunctionSummaries->markShouldNotInline(SF->
getDecl());
2779 bool BeforeFirstIteration = IterationsCompletedInLoop == std::optional{0};
2780 bool SkipFalseBranch = BothFeasible && BeforeFirstIteration &&
2781 AMgr.options.ShouldAssumeAtLeastOneIteration;
2782 if (!SkipFalseBranch && DstF) {
2784 Dst.
insert(Engine.makeNode(BE, StFalse, PredN));
2793 llvm::ImmutableSet<const VarDecl *>)
2802 bool InitHasRun = State->contains<InitializedGlobalsSet>(VD);
2804 State = State->add<InitializedGlobalsSet>(VD);
2806 if (
const CFGBlock *DstBlock = InitHasRun ? DstT : DstF) {
2840 Dst.
insert(Engine.makeNode(BE, State, Pred));
2858 State = finishArgumentConstruction(
2873 while (SF != ToSF) {
2874 assert(SF &&
"ToSF must be a parent of FromSF!");
2875 for (
auto I : State->get<ObjectsUnderConstruction>())
2876 if (I.first.getStackFrame() == SF) {
2880 assert(I.first.getItem().getKind() ==
2882 I.first.getItem().getKind() ==
2884 State = State->remove<ObjectsUnderConstruction>(I.first);
2892 Pred = Engine.makeNode(Pred->
getLocation(), State, Pred);
2909 for (
const auto I : AfterRemovedDead)
2915 Engine.enqueueEndOfFunction(Dst, RS);
2929 assert(SwitchBlock->
succ_size() &&
"Switch must have at least one successor");
2935 llvm::iterator_range<CFGBlock::const_succ_reverse_iterator> CaseBlocks(
2942 Condition->IgnoreParens(), CheckersOutSet, Pred, *
this);
2952 std::optional<NonLoc> CondNL = CondV.
getAs<
NonLoc>();
2954 for (
const CFGBlock *CaseBlock : CaseBlocks) {
2963 assert(V1.getBitWidth() ==
2969 V2 = E->EvaluateKnownConstInt(ACtx);
2976 std::tie(StateMatching, State) =
2977 State->assumeInclusiveRange(*CondNL, V1, V2);
2981 StateMatching = State;
2984 if (StateMatching) {
2985 BlockEdge BE(SwitchBlock, CaseBlock, SF);
2986 Dst.
insert(Engine.makeNode(BE, StateMatching, Node));
3008 if (
Condition->IgnoreParenImpCasts()->getType()->isEnumeralType()) {
3009 if (
Switch->isAllEnumCasesCovered())
3013 BlockEdge BE(SwitchBlock, DefaultBlock, SF);
3014 Dst.
insert(Engine.makeNode(BE, State, Node));
3028 auto resolveAsLambdaCapturedVar =
3029 [&](
const ValueDecl *VD) -> std::optional<std::pair<SVal, QualType>> {
3030 const auto *MD = dyn_cast<CXXMethodDecl>(SF->
getDecl());
3031 const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
3032 if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
3033 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
3034 MD->getParent()->isLambda()) {
3037 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
3043 if (
const FieldDecl *FD = LambdaCaptureFields[VD]) {
3044 Loc CXXThis = svalBuilder.getCXXThis(MD, SF);
3046 return std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
3050 return std::nullopt;
3053 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
3056 assert(Ex->
isGLValue() || VD->getType()->isVoidType());
3057 std::optional<std::pair<SVal, QualType>> VInfo =
3058 resolveAsLambdaCapturedVar(VD);
3061 VInfo = std::make_pair(state->getLValue(VD, SF), VD->getType());
3063 SVal V = VInfo->first;
3064 bool IsReference = VInfo->second->isReferenceType();
3070 V = state->getSVal(R);
3079 if (
const auto *ED = dyn_cast<EnumConstantDecl>(D)) {
3081 SVal V = svalBuilder.makeIntVal(ED->getInitVal());
3082 Dst.
insert(Engine.makeNodeWithBinding(Pred, Ex,
V));
3085 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
3086 SVal V = svalBuilder.getFunctionPointer(FD);
3097 if (
const auto *BD = dyn_cast<BindingDecl>(D)) {
3099 if (std::optional<std::pair<SVal, QualType>> VInfo =
3100 resolveAsLambdaCapturedVar(BD)) {
3101 auto [
V,
T] = VInfo.value();
3103 if (
T->isReferenceType()) {
3105 V = state->getSVal(R);
3110 Dst.
insert(Engine.makeNodeWithBinding(Pred, Ex,
V,
3117 SVal Base = state->getLValue(DD, SF);
3118 if (DD->getType()->isReferenceType()) {
3120 Base = state->getSVal(R);
3128 if (
const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
3130 V = state->getLValue(Field,
Base);
3133 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {
3134 SVal Idx = state->getSVal(ASE->getIdx(), SF);
3139 assert(Idx.
isConstant() &&
"BindingDecl array index is not a constant!");
3141 V = state->getLValue(BD->getType(), Idx,
Base);
3144 else if (
const auto *HV = BD->getHoldingVar()) {
3145 V = state->getLValue(HV, SF);
3147 if (HV->getType()->isReferenceType()) {
3149 V = state->getSVal(R);
3154 llvm_unreachable(
"An unknown case of structured binding encountered!");
3158 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3160 V = state->getSVal(R);
3170 if (
const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
3177 llvm_unreachable(
"Support for this Decl not implemented.");
3193 EvalSet.
insert(CheckerPreStmt);
3194 CheckerPreStmt.
clear();
3197 for (
auto *Node : CheckerPreStmt) {
3198 const StackFrame *SF = Node->getStackFrame();
3237 if (
const auto *ME = dyn_cast<MemberExpr>(Arr)) {
3238 Expr *MEBase = ME->getBase();
3241 if (
auto CXXSCE = dyn_cast<CXXStaticCastExpr>(MEBase)) {
3242 MEBase = CXXSCE->getSubExpr();
3263 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arr))
3268 Base = state->getSVal(R);
3272 EvalSet.
insert(Engine.makeNodeWithBinding(Node, Ex,
Base));
3296 (A->
getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
3298 for (
auto *Node : CheckerPreStmt) {
3299 const StackFrame *SF = Node->getStackFrame();
3302 if (IsGLValueLike) {
3308 if (
T->isVoidType())
3311 SVal V = state->getLValue(
T, state->getSVal(Idx, SF),
3312 state->getSVal(
Base, SF));
3315 }
else if (IsVectorType) {
3317 EvalSet.
insert(Engine.makePostStmtNode(A, state, Node));
3319 llvm_unreachable(
"Array subscript should be an lValue when not \
3320a vector and not a forbidden lvalue type");
3340 for (
const auto I : CheckedSet)
3344 for (
const auto I : CheckedSet) {
3350 if (
const auto *MD = dyn_cast<CXXMethodDecl>(
Member)) {
3351 if (MD->isImplicitObjectMemberFunction())
3352 state = createTemporaryRegionIfNeeded(state, SF, BaseExpr);
3354 SVal MDVal = svalBuilder.getFunctionPointer(MD);
3356 EvalSet.
insert(Engine.makeNodeWithBinding(I, M, MDVal, state));
3362 state = createTemporaryRegionIfNeeded(state, SF, BaseExpr,
3369 if (
const auto *SR =
3370 dyn_cast_or_null<SymbolicRegion>(baseExprVal.
getAsRegion())) {
3371 QualType T = SR->getPointeeStaticType();
3377 SVal L = state->getLValue(field, baseExprVal);
3387 dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
3388 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
3389 llvm_unreachable(
"should always be wrapped in ArrayToPointerDecay");
3393 if (field->getType()->isReferenceType()) {
3395 L = state->getSVal(R);
3400 EvalSet.
insert(Engine.makeNodeWithBinding(
3403 evalLoad(EvalSet, M, M, I, state, L);
3421 for (
const auto I : AfterPreSet) {
3428 ValuesToInvalidate.push_back(SubExprVal);
3436 AfterInvalidateSet.
insert(
3437 Engine.makeNodeWithBinding(I, AE,
UnknownVal(), State));
3454 for (
const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
3456 const MemRegion *MR = LocAndVal.first.getAsRegion();
3459 Escaped.push_back(LocAndVal.second);
3464 if (
const auto *VR = dyn_cast<VarRegion>(MR->
getBaseRegion()))
3466 VR->getStackFrame()->inTopFrame())
3467 if (
const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3468 if (!RD->hasTrivialDestructor()) {
3469 Escaped.push_back(LocAndVal.second);
3478 SVal StoredVal = State->getSVal(MR);
3479 if (StoredVal != LocAndVal.second)
3482 Escaped.push_back(LocAndVal.second);
3485 if (Escaped.empty())
3494 std::pair<SVal, SVal> LocAndVal(
Loc, Val);
3505 if (!Invalidated || Invalidated->empty())
3518 for (
const auto I : ExplicitRegions) {
3520 SymbolsDirectlyInvalidated.insert(R->getSymbol());
3524 for (
const auto &sym : *Invalidated) {
3525 if (SymbolsDirectlyInvalidated.count(sym))
3527 SymbolsIndirectlyInvalidated.insert(sym);
3530 if (!SymbolsDirectlyInvalidated.empty())
3535 if (!SymbolsIndirectlyInvalidated.empty())
3549 assert(!
isa<NonLoc>(Location) &&
"evalBind location should not be NonLoc!");
3560 StoreE, AtDeclInit, *
this, *PP);
3568 if (
auto AsLoc = Location.getAs<
Loc>()) {
3572 State = State->bindLoc(*AsLoc, Val, SF, !AtDeclInit);
3575 PostStore PS(StoreE, SF, Location.getAsRegion(),
nullptr);
3589 const Expr *LocationE,
3595 const Expr *StoreE = AssignE ? AssignE : LocationE;
3599 evalLocation(Tmp, AssignE, LocationE, Pred, state, location,
false);
3607 for (
const auto I : Tmp)
3608 evalBind(Dst, StoreE, I, location, Val,
false);
3613 const Expr *BoundEx,
3619 assert(!
isa<NonLoc>(location) &&
"location cannot be a NonLoc.");
3624 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location,
true);
3634 for (
const auto I : Tmp) {
3635 state = I->getState();
3641 V = state->getSVal(location.
castAs<
Loc>(), LoadTy);
3644 const auto *SF = I->getStackFrame();
3646 Dst.
insert(Engine.makeNode(
Loc, state->BindExpr(BoundEx, SF,
V), I));
3678 ExplodedNodeSet Tmp;
3680 NodeEx, BoundEx, *
this);
3684std::pair<const ProgramPointTag *, const ProgramPointTag *>
3687 FalseTag(TagProviderName,
"Eagerly Assume False");
3689 return std::make_pair(&TrueTag, &FalseTag);
3713 State = State->set<LastEagerlyAssumeExprIfSuccessful>(
nullptr);
3714 SVal V = State->getSVal(Ex, SF);
3716 if (SEV && SEV->isExpression()) {
3719 auto [StateTrue, StateFalse] = State->assume(*SEV);
3721 if (StateTrue && StateFalse) {
3722 StateTrue = StateTrue->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3723 StateFalse = StateFalse->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3729 StateTrue = StateTrue->BindExpr(Ex, SF, Val);
3730 PostStmt PostStmtTrue(Ex, SF, TrueTag);
3737 StateFalse = StateFalse->BindExpr(Ex, SF, Val);
3738 PostStmt PostStmtFalse(Ex, SF, FalseTag);
3748 const Expr *Ex)
const {
3749 return Ex && State->get<LastEagerlyAssumeExprIfSuccessful>() == Ex;
3767 if (std::optional<Loc> LV =
X.getAs<
Loc>())
3778 if (std::optional<Loc> LV =
X.getAs<
Loc>())
3785 Dst.
insert(Engine.makePostStmtNode(A, state, Pred));
3808 for (
const auto &
Report : Class.getReports()) {
3809 const auto *PR = dyn_cast<PathSensitiveBugReport>(
Report.get());
3827 llvm::function_ref<
void(
const ExplodedNode *)> PreCallback,
3828 llvm::function_ref<
void(
const ExplodedNode *)> PostCallback,
3850 llvm::raw_string_ostream Out(Buf);
3852 const bool IsDot =
true;
3853 const unsigned int Space = 1;
3856 Out <<
"{ \"state_id\": " << State->getID()
3859 Indent(Out, Space, IsDot) <<
"\"program_points\": [\\l";
3865 Indent(Out, Space + 1, IsDot) <<
"{ ";
3867 Out <<
", \"tag\": ";
3869 Out <<
'\"' << Tag->getDebugTag() <<
'\"';
3872 Out <<
", \"node_id\": " << OtherNode->
getID() <<
3873 ", \"is_sink\": " << OtherNode->
isSink() <<
3881 Indent(Out, Space, IsDot) <<
"],\\l";
3894 llvm::DisplayGraph(Filename,
false, llvm::GraphProgram::DOT);
3898 std::string Filename =
DumpGraph(Nodes);
3899 llvm::DisplayGraph(Filename,
false, llvm::GraphProgram::DOT);
3904 std::vector<const ExplodedNode *> Src;
3907 for (
const auto &
Class : BR.equivalenceClasses()) {
3909 dyn_cast<PathSensitiveBugReport>(
Class.getReports()[0].get());
3912 const auto *N =
const_cast<ExplodedNode *
>(R->getErrorNode());
3919 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
3920 return llvm::WriteGraph(&G,
"ExprEngine",
false,
3922 std::string(Filename));
3926 StringRef Filename) {
3927 std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
3930 llvm::errs() <<
"warning: Trimmed ExplodedGraph is empty.\n";
3935 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
3936 return llvm::WriteGraph(TrimmedG.get(),
"TrimmedExprEngine",
3938 "Trimmed Exploded Graph",
3939 std::string(Filename));
3943 static int index = 0;
3947void ExprEngine::anchor() { }
3959 bool IsCompound =
T->isArrayType() ||
T->isRecordType() ||
3960 T->isAnyComplexType() ||
T->isVectorType();
3963 if (Args.size() > 1 || (E->
isPRValue() && IsCompound && !IsTransparent)) {
3965 for (
Expr *E : llvm::reverse(Args))
3969 }
else if (Args.size() == 0) {
3972 Val = S->getSVal(Args.front(), SF);
3974 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.
ExplodedNode * processCFGBlockEntrance(const BlockEntrance &BE, ExplodedNode *Pred)
Called by CoreEngine when processing the entrance of a CFGBlock.
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 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...
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)
Top level wrappers for InstallAPI frontend operations.
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.
const FunctionProtoType * T
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)