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));
1104enum class VisitKind {
1118 case Stmt::GNUNullExprClass:
1122 case Stmt::ObjCAtSynchronizedStmtClass:
1123 return K == VisitKind::Pre;
1126 case Expr::ConstantExprClass:
1127 case Stmt::ExprWithCleanupsClass:
1131 case Stmt::MSAsmStmtClass:
1135 case Stmt::BlockExprClass:
1136 return K == VisitKind::Post;
1142 case Stmt::LambdaExprClass:
1147 case Stmt::BinaryOperatorClass:
1152 case Stmt::CXXOperatorCallExprClass:
1153 case Stmt::CallExprClass:
1154 case Stmt::CXXMemberCallExprClass:
1155 case Stmt::UserDefinedLiteralClass:
1159 case Stmt::CXXCatchStmtClass:
1164 case Stmt::CXXTemporaryObjectExprClass:
1165 case Stmt::CXXConstructExprClass:
1170 case Stmt::CXXInheritedCtorInitExprClass:
1174 case Stmt::ChooseExprClass:
1179 case Stmt::CompoundAssignOperatorClass:
1183 case Stmt::CompoundLiteralExprClass:
1187 case Stmt::BinaryConditionalOperatorClass:
1188 case Stmt::ConditionalOperatorClass:
1192 case Stmt::CXXThisExprClass:
1196 case Stmt::DeclRefExprClass:
1200 case Stmt::DeclStmtClass:
1205 case Stmt::InitListExprClass:
1206 case Expr::CXXParenListInitExprClass:
1210 case Stmt::ObjCIvarRefExprClass:
1211 return K == VisitKind::Post;
1214 case Stmt::ObjCForCollectionStmtClass:
1215 return K == VisitKind::Post;
1218 case Stmt::ObjCMessageExprClass:
1222 case Stmt::ObjCAtThrowStmtClass:
1223 case Stmt::CXXThrowExprClass:
1227 case Stmt::ReturnStmtClass:
1228 return K == VisitKind::Pre;
1231 case Stmt::StmtExprClass:
1235 case Stmt::UnaryOperatorClass:
1239 case Stmt::PseudoObjectExprClass:
1243 case Expr::ObjCIndirectCopyRestoreExprClass:
1250 G.reclaimRecentlyAllocatedNodes();
1254 "Error evaluating statement");
1261 CleanedStates.
insert(Pred);
1268 PreVisited.
insert(CleanedStates);
1271 for (
const auto I : PreVisited) {
1273 Visit(currStmt, I, Tmp);
1282 PostVisited.
insert(Visited);
1285 Engine.enqueueStmtNodes(PostVisited,
getCurrBlock(), currStmtIdx);
1291 "Error evaluating end of the loop");
1294 if(AMgr.options.ShouldUnrollLoops)
1298 if (
ExplodedNode *N = Engine.makeNode(PP, NewState, Pred))
1299 Engine.enqueueStmtNode(N,
getCurrBlock(), currStmtIdx);
1306 "Error evaluating end of a lifetime");
1312 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1323 "Error evaluating initializer");
1329 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(
decl, SF));
1341 State = finishObjectConstruction(State, BMI, SF);
1343 Tmp.
insert(Engine.makeNode(PS, State, Pred));
1351 FieldLoc = State->getLValue(BMI->
getMember(), thisVal);
1355 if (Field->getType()->isArrayType()) {
1359 while ((ASE = dyn_cast<ArraySubscriptExpr>(
Init)))
1362 InitVal = State->getSVal(
Init, SF);
1371 InitVal = State->getSVal(BMI->
getInit(), SF);
1375 evalBind(Tmp,
Init, Pred, FieldLoc, InitVal,
true, &PP);
1383 SVal InitVal = State->getSVal(
Init, SF);
1384 evalBind(Tmp,
Init, Pred, BaseLoc, InitVal,
true);
1399 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1402std::pair<ProgramStateRef, uint64_t>
1403ExprEngine::prepareStateForArrayDestruction(
const ProgramStateRef State,
1407 SVal *ElementCountVal) {
1408 assert(Region !=
nullptr &&
"Not-null region expected");
1411 while (
const auto *NTy = dyn_cast<ArrayType>(Ty))
1412 Ty = NTy->getElementType().getDesugaredType(
getContext());
1416 if (ElementCountVal)
1417 *ElementCountVal = ElementCount;
1425 if (!ElementCount.isConstant())
1428 Idx = ElementCount.getAsInteger()->getLimitedValue();
1436 return {setPendingArrayDestruction(State, SF, Idx), Idx};
1459 llvm_unreachable(
"Unexpected dtor kind.");
1463 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1474 if (Opts.MayInlineCXXAllocator)
1482 Engine.enqueueStmtNodes(Dst,
getCurrBlock(), currStmtIdx);
1488 const auto *DtorDecl = Dtor.getDestructorDecl(
getContext());
1499 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
1514 std::tie(state, Idx) = prepareStateForArrayDestruction(
1515 state, Region, varType, SF, &ElementCount);
1517 if (ElementCount.isConstant()) {
1518 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1519 assert(ArrayLength &&
1520 "An automatic dtor for a 0 length array shouldn't be triggered!");
1525 "ExprEngine",
"Skipping automatic 0 length array destruction, "
1526 "which shouldn't be in the CFG.");
1529 Engine.makeNode(PP, Pred->
getState(), Pred,
true);
1541 "Prepare for object destruction");
1544 Pred = Engine.makeNode(PP, state, Pred);
1550 false, Pred, Dst, CallOpts);
1561 SVal ArgVal = State->getSVal(Arg, SF);
1565 if (State->isNull(ArgVal).isConstrainedTrue()) {
1575 auto getDtorDecl = [](
const QualType &DTy) {
1587 while (
const auto *AT =
getContext().getAsArrayType(DTy))
1588 DTy = AT->getElementType();
1592 std::tie(State, Idx) =
1593 prepareStateForArrayDestruction(State, ArgR, DTy, SF, &ElementCount);
1597 if (ElementCount.isConstant() &&
1598 ElementCount.getAsInteger()->getLimitedValue() == 0) {
1601 "ExprEngine",
"Skipping 0 length array delete destruction");
1608 ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
1614 "Prepare for object destruction");
1617 Pred = Engine.makeNode(PP, State, Pred);
1641 true, Pred, Dst, CallOpts);
1654 Loc ThisLoc = State->getSVal(ThisStorageLoc).
castAs<
Loc>();
1655 SVal FieldVal = State->getLValue(
Member, ThisLoc);
1660 std::tie(State, Idx) = prepareStateForArrayDestruction(
1661 State, FieldVal.getAsRegion(),
T, SF, &ElementCount);
1663 if (ElementCount.isConstant()) {
1664 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1665 assert(ArrayLength &&
1666 "A member dtor for a 0 length array shouldn't be triggered!");
1671 "ExprEngine",
"Skipping member 0 length array destruction, which "
1672 "shouldn't be in the CFG.");
1675 Engine.makeNode(PP, Pred->
getState(), Pred,
true);
1686 "Prepare for object destruction");
1689 Pred = Engine.makeNode(PP, State, Pred);
1695 false, Pred, Dst, CallOpts);
1710 State = finishObjectConstruction(State, BTE, SF);
1711 MR =
V->getAsRegion();
1716 if (isDestructorElided(State, BTE, SF)) {
1717 State = cleanupElidedDestructor(State, BTE, SF);
1720 Dst.
insert(Engine.makeNode(PP, State, Pred));
1724 ExplodedNode *CleanPred = Engine.makePostStmtNode(BTE, State, Pred);
1754 T = AT->getElementType();
1765 false, CleanPred, Dst, CallOpts);
1777 if (
const CFGBlock *DstBlock = Obj ? DstT : DstF) {
1779 Dst.
insert(Engine.makeNode(BE, State, Pred));
1802 State = addObjectUnderConstruction(State, BTE, SF,
UnknownVal());
1804 Dst.
insert(Engine.makePostStmtNode(BTE, State, Pred));
1811 class CollectReachableSymbolsCallback final :
public SymbolVisitor {
1816 : Symbols(Symbols) {}
1820 bool VisitSymbol(
SymbolRef Sym)
override {
1821 Symbols.insert(Sym);
1826 CollectReachableSymbolsCallback CallBack(Symbols);
1828 State->scanReachableSymbols(
V, CallBack);
1831 State, CallBack.getSymbols(),
Call, K,
nullptr);
1843 case Stmt::CXXDependentScopeMemberExprClass:
1844 case Stmt::CXXReflectExprClass:
1845 case Stmt::CXXTryStmtClass:
1846 case Stmt::CXXTypeidExprClass:
1847 case Stmt::CXXUuidofExprClass:
1848 case Stmt::CXXFoldExprClass:
1849 case Stmt::MSPropertyRefExprClass:
1850 case Stmt::MSPropertySubscriptExprClass:
1851 case Stmt::CXXUnresolvedConstructExprClass:
1852 case Stmt::DependentScopeDeclRefExprClass:
1853 case Stmt::ArrayTypeTraitExprClass:
1854 case Stmt::ExpressionTraitExprClass:
1855 case Stmt::UnresolvedLookupExprClass:
1856 case Stmt::UnresolvedMemberExprClass:
1857 case Stmt::DependentTemplateIdExprClass:
1858 case Stmt::RecoveryExprClass:
1859 case Stmt::CXXNoexceptExprClass:
1860 case Stmt::PackExpansionExprClass:
1861 case Stmt::PackIndexingExprClass:
1862 case Stmt::SubstNonTypeTemplateParmPackExprClass:
1863 case Stmt::FunctionParmPackExprClass:
1864 case Stmt::CoroutineBodyStmtClass:
1865 case Stmt::CoawaitExprClass:
1866 case Stmt::DependentCoawaitExprClass:
1867 case Stmt::CoreturnStmtClass:
1868 case Stmt::CoyieldExprClass:
1869 case Stmt::SEHTryStmtClass:
1870 case Stmt::SEHExceptStmtClass:
1871 case Stmt::SEHLeaveStmtClass:
1872 case Stmt::SEHFinallyStmtClass:
1873 case Stmt::CXXExpansionStmtPatternClass:
1874 case Stmt::CXXExpansionStmtInstantiationClass:
1875 case Stmt::CXXExpansionSelectExprClass:
1876 case Stmt::OMPCanonicalLoopClass:
1877 case Stmt::OMPParallelDirectiveClass:
1878 case Stmt::OMPSimdDirectiveClass:
1879 case Stmt::OMPForDirectiveClass:
1880 case Stmt::OMPForSimdDirectiveClass:
1881 case Stmt::OMPSectionsDirectiveClass:
1882 case Stmt::OMPSectionDirectiveClass:
1883 case Stmt::OMPScopeDirectiveClass:
1884 case Stmt::OMPSingleDirectiveClass:
1885 case Stmt::OMPMasterDirectiveClass:
1886 case Stmt::OMPCriticalDirectiveClass:
1887 case Stmt::OMPParallelForDirectiveClass:
1888 case Stmt::OMPParallelForSimdDirectiveClass:
1889 case Stmt::OMPParallelSectionsDirectiveClass:
1890 case Stmt::OMPParallelMasterDirectiveClass:
1891 case Stmt::OMPParallelMaskedDirectiveClass:
1892 case Stmt::OMPTaskDirectiveClass:
1893 case Stmt::OMPTaskyieldDirectiveClass:
1894 case Stmt::OMPBarrierDirectiveClass:
1895 case Stmt::OMPTaskwaitDirectiveClass:
1896 case Stmt::OMPErrorDirectiveClass:
1897 case Stmt::OMPTaskgroupDirectiveClass:
1898 case Stmt::OMPFlushDirectiveClass:
1899 case Stmt::OMPDepobjDirectiveClass:
1900 case Stmt::OMPScanDirectiveClass:
1901 case Stmt::OMPOrderedStandaloneDirectiveClass:
1902 case Stmt::OMPOrderedBlockAssocDirectiveClass:
1903 case Stmt::OMPAtomicDirectiveClass:
1904 case Stmt::OMPAssumeDirectiveClass:
1905 case Stmt::OMPTargetDirectiveClass:
1906 case Stmt::OMPTargetDataDirectiveClass:
1907 case Stmt::OMPTargetEnterDataDirectiveClass:
1908 case Stmt::OMPTargetExitDataDirectiveClass:
1909 case Stmt::OMPTargetParallelDirectiveClass:
1910 case Stmt::OMPTargetParallelForDirectiveClass:
1911 case Stmt::OMPTargetUpdateDirectiveClass:
1912 case Stmt::OMPTeamsDirectiveClass:
1913 case Stmt::OMPCancellationPointDirectiveClass:
1914 case Stmt::OMPCancelDirectiveClass:
1915 case Stmt::OMPTaskLoopDirectiveClass:
1916 case Stmt::OMPTaskLoopSimdDirectiveClass:
1917 case Stmt::OMPMasterTaskLoopDirectiveClass:
1918 case Stmt::OMPMaskedTaskLoopDirectiveClass:
1919 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1920 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1921 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1922 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1923 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1924 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1925 case Stmt::OMPDistributeDirectiveClass:
1926 case Stmt::OMPDistributeParallelForDirectiveClass:
1927 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1928 case Stmt::OMPDistributeSimdDirectiveClass:
1929 case Stmt::OMPTargetParallelForSimdDirectiveClass:
1930 case Stmt::OMPTargetSimdDirectiveClass:
1931 case Stmt::OMPTeamsDistributeDirectiveClass:
1932 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1933 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1934 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1935 case Stmt::OMPTargetTeamsDirectiveClass:
1936 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1937 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1938 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1939 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1940 case Stmt::OMPReverseDirectiveClass:
1941 case Stmt::OMPStripeDirectiveClass:
1942 case Stmt::OMPTileDirectiveClass:
1943 case Stmt::OMPInterchangeDirectiveClass:
1944 case Stmt::OMPFlattenDirectiveClass:
1945 case Stmt::OMPSplitDirectiveClass:
1946 case Stmt::OMPFuseDirectiveClass:
1947 case Stmt::OMPInteropDirectiveClass:
1948 case Stmt::OMPDispatchDirectiveClass:
1949 case Stmt::OMPMaskedDirectiveClass:
1950 case Stmt::OMPGenericLoopDirectiveClass:
1951 case Stmt::OMPTeamsGenericLoopDirectiveClass:
1952 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
1953 case Stmt::OMPParallelGenericLoopDirectiveClass:
1954 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1955 case Stmt::CapturedStmtClass:
1956 case Stmt::SYCLKernelCallStmtClass:
1957 case Stmt::UnresolvedSYCLKernelCallStmtClass:
1958 case Stmt::OpenACCComputeConstructClass:
1959 case Stmt::OpenACCLoopConstructClass:
1960 case Stmt::OpenACCCombinedConstructClass:
1961 case Stmt::OpenACCDataConstructClass:
1962 case Stmt::OpenACCEnterDataConstructClass:
1963 case Stmt::OpenACCExitDataConstructClass:
1964 case Stmt::OpenACCHostDataConstructClass:
1965 case Stmt::OpenACCWaitConstructClass:
1966 case Stmt::OpenACCCacheConstructClass:
1967 case Stmt::OpenACCInitConstructClass:
1968 case Stmt::OpenACCShutdownConstructClass:
1969 case Stmt::OpenACCSetConstructClass:
1970 case Stmt::OpenACCUpdateConstructClass:
1971 case Stmt::OpenACCAtomicConstructClass:
1972 case Stmt::OMPUnrollDirectiveClass:
1973 case Stmt::OMPMetaDirectiveClass:
1974 case Stmt::HLSLOutArgExprClass: {
1981 case Stmt::ParenExprClass:
1982 llvm_unreachable(
"ParenExprs already handled.");
1983 case Stmt::GenericSelectionExprClass:
1984 llvm_unreachable(
"GenericSelectionExprs already handled.");
1987 case Stmt::BreakStmtClass:
1988 case Stmt::CaseStmtClass:
1989 case Stmt::CompoundStmtClass:
1990 case Stmt::ContinueStmtClass:
1991 case Stmt::CXXForRangeStmtClass:
1992 case Stmt::DefaultStmtClass:
1993 case Stmt::DoStmtClass:
1994 case Stmt::ForStmtClass:
1995 case Stmt::GotoStmtClass:
1996 case Stmt::IfStmtClass:
1997 case Stmt::IndirectGotoStmtClass:
1998 case Stmt::LabelStmtClass:
2000 case Stmt::NullStmtClass:
2001 case Stmt::SwitchStmtClass:
2002 case Stmt::WhileStmtClass:
2003 case Stmt::DeferStmtClass:
2004 case Expr::MSDependentExistsStmtClass:
2005 llvm_unreachable(
"Stmt should not be in analyzer evaluation loop");
2006 case Stmt::ImplicitValueInitExprClass:
2010 llvm_unreachable(
"Should be pruned from CFG");
2012 case Stmt::ObjCSubscriptRefExprClass:
2013 case Stmt::ObjCPropertyRefExprClass:
2014 llvm_unreachable(
"These are handled by PseudoObjectExpr");
2016 case Stmt::GNUNullExprClass: {
2018 SVal Val = svalBuilder.makeIntValWithWidth(
getContext().VoidPtrTy, 0);
2023 case Stmt::ObjCAtSynchronizedStmtClass: {
2028 case Expr::ConstantExprClass:
2029 case Stmt::ExprWithCleanupsClass:
2034 case Stmt::CXXBindTemporaryExprClass:
2038 case Stmt::ArrayInitLoopExprClass:
2042 case Stmt::DesignatedInitExprClass:
2043 case Stmt::DesignatedInitUpdateExprClass:
2044 case Stmt::ArrayInitIndexExprClass:
2045 case Stmt::ExtVectorElementExprClass:
2046 case Stmt::MatrixElementExprClass:
2047 case Stmt::ImaginaryLiteralClass:
2048 case Stmt::ObjCAtCatchStmtClass:
2049 case Stmt::ObjCAtFinallyStmtClass:
2050 case Stmt::ObjCAtTryStmtClass:
2051 case Stmt::ObjCAutoreleasePoolStmtClass:
2052 case Stmt::ObjCEncodeExprClass:
2053 case Stmt::ObjCIsaExprClass:
2054 case Stmt::ObjCProtocolExprClass:
2055 case Stmt::ObjCSelectorExprClass:
2056 case Stmt::ParenListExprClass:
2057 case Stmt::ShuffleVectorExprClass:
2058 case Stmt::ConvertVectorExprClass:
2059 case Stmt::VAArgExprClass:
2060 case Stmt::CUDAKernelCallExprClass:
2061 case Stmt::OpaqueValueExprClass:
2062 case Stmt::AsTypeExprClass:
2063 case Stmt::ConceptSpecializationExprClass:
2064 case Stmt::CXXRewrittenBinaryOperatorClass:
2065 case Stmt::RequiresExprClass:
2066 case Stmt::EmbedExprClass:
2071 case Stmt::PredefinedExprClass:
2072 case Stmt::AddrLabelExprClass:
2073 case Stmt::IntegerLiteralClass:
2074 case Stmt::FixedPointLiteralClass:
2075 case Stmt::CharacterLiteralClass:
2076 case Stmt::CXXScalarValueInitExprClass:
2077 case Stmt::CXXBoolLiteralExprClass:
2078 case Stmt::ObjCBoolLiteralExprClass:
2079 case Stmt::ObjCAvailabilityCheckExprClass:
2080 case Stmt::FloatingLiteralClass:
2081 case Stmt::NoInitExprClass:
2082 case Stmt::SizeOfPackExprClass:
2083 case Stmt::StringLiteralClass:
2084 case Stmt::SourceLocExprClass:
2085 case Stmt::ObjCStringLiteralClass:
2086 case Stmt::CXXPseudoDestructorExprClass:
2087 case Stmt::SubstNonTypeTemplateParmExprClass:
2088 case Stmt::CXXNullPtrLiteralExprClass:
2089 case Stmt::ArraySectionExprClass:
2090 case Stmt::OMPArrayShapingExprClass:
2091 case Stmt::OMPIteratorExprClass:
2092 case Stmt::SYCLUniqueStableNameExprClass:
2093 case Stmt::OpenACCAsteriskSizeExprClass:
2094 case Stmt::TypeTraitExprClass: {
2099 case Stmt::AttributedStmtClass:
2103 case Stmt::CXXDefaultArgExprClass:
2104 case Stmt::CXXDefaultInitExprClass: {
2107 if (
const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
2108 ArgE = DefE->getExpr();
2109 else if (
const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
2110 ArgE = DefE->getExpr();
2112 llvm_unreachable(
"unknown constant wrapper kind");
2114 bool IsTemporary =
false;
2115 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
2116 ArgE = MTE->getSubExpr();
2120 std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
2126 State = State->BindExpr(
cast<Expr>(S), SF, *ConstantVal);
2128 State = createTemporaryRegionIfNeeded(State, SF,
cast<Expr>(S),
2130 Dst.
insert(Engine.makePostStmtNode(S, State, Pred));
2136 case Stmt::CXXStdInitializerListExprClass:
2137 case Expr::ObjCArrayLiteralClass:
2138 case Expr::ObjCDictionaryLiteralClass:
2139 case Expr::ObjCBoxedExprClass: {
2141 QualType resultType = Ex->getType();
2144 SVal result = svalBuilder.conjureSymbolVal(
2153 for (
auto Child : Ex->children()) {
2155 const auto *ChildExpr = dyn_cast<Expr>(Child);
2156 SVal Val = ChildExpr ? State->getSVal(ChildExpr, SF) :
UnknownVal();
2160 Dst.
insert(Engine.makePostStmtNode(S, State, Pred));
2164 case Stmt::ArraySubscriptExprClass:
2168 case Stmt::MatrixSingleSubscriptExprClass:
2170 "Support for MatrixSingleSubscriptExprClass is not implemented.");
2173 case Stmt::MatrixSubscriptExprClass:
2174 llvm_unreachable(
"Support for MatrixSubscriptExpr is not implemented.");
2177 case Stmt::GCCAsmStmtClass:
2181 case Stmt::MSAsmStmtClass:
2185 case Stmt::BlockExprClass:
2189 case Stmt::LambdaExprClass:
2193 case Stmt::BinaryOperatorClass: {
2195 if (B->isLogicalOp()) {
2198 }
else if (B->getOpcode() == BO_Comma) {
2201 Dst.
insert(Engine.makeNodeWithBinding(Pred, B, Val));
2205 if (AMgr.options.ShouldEagerlyAssume &&
2206 (B->isRelationalOp() || B->isEqualityOp())) {
2217 case Stmt::CXXOperatorCallExprClass:
2218 case Stmt::CallExprClass:
2219 case Stmt::CXXMemberCallExprClass:
2220 case Stmt::UserDefinedLiteralClass:
2224 case Stmt::CXXCatchStmtClass:
2228 case Stmt::CXXTemporaryObjectExprClass:
2229 case Stmt::CXXConstructExprClass:
2233 case Stmt::CXXInheritedCtorInitExprClass:
2238 case Stmt::CXXNewExprClass:
2242 case Stmt::CXXDeleteExprClass:
2248 case Stmt::ChooseExprClass: {
2254 case Stmt::CompoundAssignOperatorClass:
2258 case Stmt::CompoundLiteralExprClass:
2262 case Stmt::BinaryConditionalOperatorClass:
2263 case Stmt::ConditionalOperatorClass: {
2269 case Stmt::CXXThisExprClass:
2273 case Stmt::DeclRefExprClass: {
2279 case Stmt::DeclStmtClass:
2283 case Stmt::ImplicitCastExprClass:
2284 case Stmt::CStyleCastExprClass:
2285 case Stmt::CXXStaticCastExprClass:
2286 case Stmt::CXXDynamicCastExprClass:
2287 case Stmt::CXXReinterpretCastExprClass:
2288 case Stmt::CXXConstCastExprClass:
2289 case Stmt::CXXFunctionalCastExprClass:
2290 case Stmt::BuiltinBitCastExprClass:
2291 case Stmt::ObjCBridgedCastExprClass:
2292 case Stmt::CXXAddrspaceCastExprClass:
2296 case Expr::MaterializeTemporaryExprClass:
2301 case Stmt::InitListExprClass: {
2307 case Expr::CXXParenListInitExprClass:
2311 case Stmt::MemberExprClass:
2315 case Stmt::AtomicExprClass:
2319 case Stmt::ObjCIvarRefExprClass:
2323 case Stmt::ObjCForCollectionStmtClass:
2327 case Stmt::ObjCMessageExprClass:
2331 case Stmt::ObjCAtThrowStmtClass:
2332 case Stmt::CXXThrowExprClass:
2335 Engine.makePostStmtNode(S, Pred->
getState(), Pred,
true);
2338 case Stmt::ReturnStmtClass:
2342 case Stmt::OffsetOfExprClass:
2346 case Stmt::UnaryExprOrTypeTraitExprClass:
2351 case Stmt::StmtExprClass:
2355 case Stmt::UnaryOperatorClass: {
2357 if (AMgr.options.ShouldEagerlyAssume && (
U->getOpcode() == UO_LNot)) {
2367 case Stmt::PseudoObjectExprClass:
2371 case Expr::ObjCIndirectCopyRestoreExprClass:
2381 assert(CalleeSF && CallerSF);
2388 BeforeProcessingCall = N;
2403 if (SP->getStmt() == CE)
2408 if (!BeforeProcessingCall)
2447 NumTimesRetriedWithoutInlining++;
2457 unsigned MaxBlockVisit = AMgr.options.maxBlockVisitOnPath;
2461 if (AMgr.options.ShouldUnrollLoops) {
2463 State =
updateLoopStack(Term, AMgr.getASTContext(), Pred, MaxBlockVisit);
2466 return Engine.makeNode(BE, State, Pred);
2472 if (BlockCount == MaxBlockVisit - 1 && AMgr.options.ShouldWidenLoops) {
2473 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
2474 return Engine.makeNode(BE, State, Pred);
2484 return Engine.makeNode(BE, WidenedState, Pred);
2488 if (BlockCount < MaxBlockVisit)
2489 return Engine.makeNode(BE, State, Pred);
2494 Engine.makeNode(BE.
withTag(&Tag), State, Pred,
true);
2506 Engine.FunctionSummaries->markShouldNotInline(SF->
getDecl());
2512 if (!AMgr.options.NoRetryExhausted && replayWithoutInlining(Pred, SF))
2514 NumMaxBlockCountReachedInInlined++;
2516 NumMaxBlockCountReached++;
2519 Engine.blocksExhausted.push_back(std::make_pair(BE, Sink));
2527 llvm::PrettyStackTraceFormat CrashInfo(
2528 "Processing block entrance B%d -> B%d",
2546 const auto *Ex = dyn_cast<Expr>(
Condition);
2551 bool bitsInit =
false;
2553 while (
const auto *CE = dyn_cast<CastExpr>(Ex)) {
2556 if (!
T->isIntegralOrEnumerationType())
2560 if (!bitsInit || newBits < bits) {
2565 Ex = CE->getSubExpr();
2571 if (!bitsInit || !
T->isIntegralOrEnumerationType() ||
2575 return state->getSVal(Ex, SF);
2581 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2582 if (!BO || !BO->isLogicalOp()) {
2585 Condition = BO->getRHS()->IgnoreParens();
2607 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2610 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2611 if (!BO || !BO->isLogicalOp())
2615 "Other kinds of branches are handled separately!");
2626 std::optional<CFGStmt> CS = Elem.getAs<
CFGStmt>();
2629 const Stmt *LastStmt = CS->getStmt();
2633 llvm_unreachable(
"could not resolve condition");
2637 std::pair<const ObjCForCollectionStmt *, const StackFrame *>;
2643 bool HasMoreIteraton) {
2644 assert(!State->contains<ObjCForHasMoreIterations>({O, SF}));
2645 return State->set<ObjCForHasMoreIterations>({O, SF}, HasMoreIteraton);
2651 assert(State->contains<ObjCForHasMoreIterations>({O, SF}));
2652 return State->remove<ObjCForHasMoreIterations>({O, SF});
2658 assert(State->contains<ObjCForHasMoreIterations>({O, SF}));
2659 return *State->get<ObjCForHasMoreIterations>({O, SF});
2665static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
2668 if (
const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(ConditionStmt)) {
2669 bool HasMoreIteraton =
2676 if (HasMoreIteraton)
2677 return std::pair<ProgramStateRef, ProgramStateRef>{State,
nullptr};
2679 return std::pair<ProgramStateRef, ProgramStateRef>{
nullptr, State};
2682 const auto *ConditionExpr = dyn_cast<Expr>(ConditionStmt);
2683 assert(ConditionExpr &&
"The condition must be an Expr from here!");
2687 if (
X.isUnknownOrUndef()) {
2689 if (
const auto *Ex = dyn_cast<Expr>(ConditionExpr)) {
2690 if (Ex->getType()->isIntegralOrEnumerationType()) {
2697 N->
getState()->getStateManager().getContext());
2707 if (
X.isUnknownOrUndef())
2708 return std::nullopt;
2712 return State->assume(
V);
2718 std::optional<unsigned> IterationsCompletedInLoop) {
2720 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2736 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2742 "Error evaluating branch");
2748 if (CheckersOutSet.
empty())
2756 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2758 if (StTrue && StFalse)
2769 (StTrue && StFalse) ||
2788 bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;
2789 bool SkipTrueBranch = BothFeasible && CompletedTwoIterations;
2795 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops) {
2798 Dst.
insert(Engine.makeNode(BE, StTrue, PredN));
2800 }
else if (!AMgr.options.InlineFunctionsWithAmbiguousLoops) {
2817 Engine.FunctionSummaries->markShouldNotInline(SF->
getDecl());
2835 bool BeforeFirstIteration = IterationsCompletedInLoop == std::optional{0};
2836 bool SkipFalseBranch = BothFeasible && BeforeFirstIteration &&
2837 AMgr.options.ShouldAssumeAtLeastOneIteration;
2838 if (!SkipFalseBranch && DstF) {
2840 Dst.
insert(Engine.makeNode(BE, StFalse, PredN));
2849 llvm::ImmutableSet<const VarDecl *>)
2858 bool InitHasRun = State->contains<InitializedGlobalsSet>(VD);
2860 State = State->add<InitializedGlobalsSet>(VD);
2862 if (
const CFGBlock *DstBlock = InitHasRun ? DstT : DstF) {
2896 Dst.
insert(Engine.makeNode(BE, State, Pred));
2914 State = finishArgumentConstruction(
2929 while (SF != ToSF) {
2930 assert(SF &&
"ToSF must be a parent of FromSF!");
2931 for (
auto I : State->get<ObjectsUnderConstruction>())
2932 if (I.first.getStackFrame() == SF) {
2936 assert(I.first.getItem().getKind() ==
2938 I.first.getItem().getKind() ==
2940 State = State->remove<ObjectsUnderConstruction>(I.first);
2948 Pred = Engine.makeNode(Pred->
getLocation(), State, Pred);
2965 for (
const auto I : AfterRemovedDead)
2971 Engine.enqueueEndOfFunction(Dst, RS);
2985 assert(SwitchBlock->
succ_size() &&
"Switch must have at least one successor");
2991 llvm::iterator_range<CFGBlock::const_succ_reverse_iterator> CaseBlocks(
2998 Condition->IgnoreParens(), CheckersOutSet, Pred, *
this);
3008 std::optional<NonLoc> CondNL = CondV.
getAs<
NonLoc>();
3010 for (
const CFGBlock *CaseBlock : CaseBlocks) {
3019 assert(V1.getBitWidth() ==
3025 V2 = E->EvaluateKnownConstInt(ACtx);
3032 std::tie(StateMatching, State) =
3033 State->assumeInclusiveRange(*CondNL, V1, V2);
3037 StateMatching = State;
3040 if (StateMatching) {
3041 BlockEdge BE(SwitchBlock, CaseBlock, SF);
3042 Dst.
insert(Engine.makeNode(BE, StateMatching, Node));
3064 if (
Condition->IgnoreParenImpCasts()->getType()->isEnumeralType()) {
3065 if (
Switch->isAllEnumCasesCovered())
3069 BlockEdge BE(SwitchBlock, DefaultBlock, SF);
3070 Dst.
insert(Engine.makeNode(BE, State, Node));
3078std::optional<std::pair<SVal, QualType>>
3079ExprEngine::resolveAsLambdaCapturedVar(
const Expr *Ex,
const ValueDecl *VD,
3084 const auto *MD = dyn_cast<CXXMethodDecl>(SF->
getDecl());
3085 const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
3086 if (!AMgr.
options.ShouldInlineLambdas || !DeclRefEx ||
3087 !DeclRefEx->refersToEnclosingVariableOrCapture() || !MD ||
3088 !MD->getParent()->isLambda()) {
3089 return std::nullopt;
3093 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
3099 if (
const FieldDecl *FD = LambdaCaptureFields[VD]) {
3100 if (MD->isImplicitObjectMemberFunction()) {
3103 return {{State->getLValue(FD, CXXThisVal), FD->getType()}};
3105 const ParmVarDecl *PVD = MD->getParamDecl(0);
3107 const ParamVarRegion *PVR =
3108 MRMgr.getParamVarRegion(CallSite, 0, SF);
3118 State->bindLoc(loc::MemRegionVal(PVR),
3119 State->getSVal(SelfArgExpr, SF->
getParent()), SF);
3120 SVal ParamSVal = State->getSVal(loc::MemRegionVal(PVR));
3121 return {{State->getLValue(FD, ParamSVal), FD->getType()}};
3123 return {{State->getLValue(FD, loc::MemRegionVal(PVR)), FD->getType()}};
3126 return std::nullopt;
3135 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
3138 assert(Ex->
isGLValue() || VD->getType()->isVoidType());
3139 std::optional<std::pair<SVal, QualType>> VInfo =
3140 resolveAsLambdaCapturedVar(Ex, VD, Pred);
3143 VInfo = std::make_pair(state->getLValue(VD, SF), VD->getType());
3145 SVal V = VInfo->first;
3146 bool IsReference = VInfo->second->isReferenceType();
3152 V = state->getSVal(R);
3161 if (
const auto *ED = dyn_cast<EnumConstantDecl>(D)) {
3163 SVal V = svalBuilder.makeIntVal(ED->getInitVal());
3164 Dst.
insert(Engine.makeNodeWithBinding(Pred, Ex,
V));
3167 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
3168 SVal V = svalBuilder.getFunctionPointer(FD);
3179 if (
const auto *BD = dyn_cast<BindingDecl>(D)) {
3181 if (std::optional<std::pair<SVal, QualType>> VInfo =
3182 resolveAsLambdaCapturedVar(Ex, BD, Pred)) {
3183 auto [
V,
T] = VInfo.value();
3185 if (
T->isReferenceType()) {
3187 V = state->getSVal(R);
3192 Dst.
insert(Engine.makeNodeWithBinding(Pred, Ex,
V,
3199 SVal Base = state->getLValue(DD, SF);
3200 if (DD->getType()->isReferenceType()) {
3202 Base = state->getSVal(R);
3210 if (
const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
3212 V = state->getLValue(Field,
Base);
3215 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {
3216 SVal Idx = state->getSVal(ASE->getIdx(), SF);
3221 assert(Idx.
isConstant() &&
"BindingDecl array index is not a constant!");
3223 V = state->getLValue(BD->getType(), Idx,
Base);
3226 else if (
const auto *HV = BD->getHoldingVar()) {
3227 V = state->getLValue(HV, SF);
3229 if (HV->getType()->isReferenceType()) {
3231 V = state->getSVal(R);
3236 llvm_unreachable(
"An unknown case of structured binding encountered!");
3240 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3242 V = state->getSVal(R);
3252 if (
const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
3259 llvm_unreachable(
"Support for this Decl not implemented.");
3313 if (
const auto *ME = dyn_cast<MemberExpr>(Arr)) {
3314 Expr *MEBase = ME->getBase();
3317 if (
auto CXXSCE = dyn_cast<CXXStaticCastExpr>(MEBase)) {
3318 MEBase = CXXSCE->getSubExpr();
3339 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arr))
3344 Base = state->getSVal(R);
3348 Dst.
insert(Engine.makeNodeWithBinding(Pred, Ex,
Base));
3364 (A->
getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
3369 if (IsGLValueLike) {
3375 if (
T->isVoidType())
3379 state->getLValue(
T, state->getSVal(Idx, SF), state->getSVal(
Base, SF));
3382 }
else if (IsVectorType) {
3384 Dst.
insert(Engine.makePostStmtNode(A, state, Pred));
3386 llvm_unreachable(
"Array subscript should be an lValue when not \
3387a vector and not a forbidden lvalue type");
3408 if (
const auto *MD = dyn_cast<CXXMethodDecl>(
Member)) {
3409 if (MD->isImplicitObjectMemberFunction())
3410 state = createTemporaryRegionIfNeeded(state, SF, BaseExpr);
3412 SVal MDVal = svalBuilder.getFunctionPointer(MD);
3414 Dst.
insert(Engine.makeNodeWithBinding(Pred, M, MDVal, state));
3420 state = createTemporaryRegionIfNeeded(state, SF, BaseExpr,
3426 if (
const auto *SR =
3427 dyn_cast_or_null<SymbolicRegion>(baseExprVal.
getAsRegion())) {
3428 QualType T = SR->getPointeeStaticType();
3434 SVal L = state->getLValue(field, baseExprVal);
3443 const auto *PE = dyn_cast<ImplicitCastExpr>(
3445 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
3446 llvm_unreachable(
"should always be wrapped in ArrayToPointerDecay");
3450 if (field->getType()->isReferenceType()) {
3452 L = state->getSVal(R);
3457 Dst.
insert(Engine.makeNodeWithBinding(Pred, M, L, state,
3460 evalLoad(Dst, M, M, Pred, state, L);
3475 ValuesToInvalidate.push_back(SubExprVal);
3497 for (
const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
3499 const MemRegion *MR = LocAndVal.first.getAsRegion();
3502 Escaped.push_back(LocAndVal.second);
3507 if (
const auto *VR = dyn_cast<VarRegion>(MR->
getBaseRegion()))
3509 VR->getStackFrame()->inTopFrame())
3510 if (
const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3511 if (!RD->hasTrivialDestructor()) {
3512 Escaped.push_back(LocAndVal.second);
3521 SVal StoredVal = State->getSVal(MR);
3522 if (StoredVal != LocAndVal.second)
3525 Escaped.push_back(LocAndVal.second);
3528 if (Escaped.empty())
3537 std::pair<SVal, SVal> LocAndVal(
Loc, Val);
3548 if (!Invalidated || Invalidated->empty())
3561 for (
const auto I : ExplicitRegions) {
3563 SymbolsDirectlyInvalidated.insert(R->getSymbol());
3567 for (
const auto &sym : *Invalidated) {
3568 if (SymbolsDirectlyInvalidated.count(sym))
3570 SymbolsIndirectlyInvalidated.insert(sym);
3573 if (!SymbolsDirectlyInvalidated.empty())
3578 if (!SymbolsIndirectlyInvalidated.empty())
3592 assert(!
isa<NonLoc>(Location) &&
"evalBind location should not be NonLoc!");
3603 StoreE, AtDeclInit, *
this, *PP);
3611 if (
auto AsLoc = Location.getAs<
Loc>()) {
3615 State = State->bindLoc(*AsLoc, Val, SF, !AtDeclInit);
3618 PostStore PS(StoreE, SF, Location.getAsRegion(),
nullptr);
3632 const Expr *LocationE,
3638 const Expr *StoreE = AssignE ? AssignE : LocationE;
3642 evalLocation(Tmp, AssignE, LocationE, Pred, state, location,
false);
3650 for (
const auto I : Tmp)
3651 evalBind(Dst, StoreE, I, location, Val,
false);
3656 const Expr *BoundEx,
3662 assert(!
isa<NonLoc>(location) &&
"location cannot be a NonLoc.");
3667 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location,
true);
3677 for (
const auto I : Tmp) {
3678 state = I->getState();
3684 V = state->getSVal(location.
castAs<
Loc>(), LoadTy);
3687 const auto *SF = I->getStackFrame();
3689 Dst.
insert(Engine.makeNode(
Loc, state->BindExpr(BoundEx, SF,
V), I));
3721 ExplodedNodeSet Tmp;
3723 NodeEx, BoundEx, *
this);
3727std::pair<const ProgramPointTag *, const ProgramPointTag *>
3730 FalseTag(TagProviderName,
"Eagerly Assume False");
3732 return std::make_pair(&TrueTag, &FalseTag);
3756 State = State->set<LastEagerlyAssumeExprIfSuccessful>(
nullptr);
3757 SVal V = State->getSVal(Ex, SF);
3759 if (SEV && SEV->isExpression()) {
3762 auto [StateTrue, StateFalse] = State->assume(*SEV);
3764 if (StateTrue && StateFalse) {
3765 StateTrue = StateTrue->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3766 StateFalse = StateFalse->set<LastEagerlyAssumeExprIfSuccessful>(Ex);
3772 StateTrue = StateTrue->BindExpr(Ex, SF, Val);
3773 PostStmt PostStmtTrue(Ex, SF, TrueTag);
3780 StateFalse = StateFalse->BindExpr(Ex, SF, Val);
3781 PostStmt PostStmtFalse(Ex, SF, FalseTag);
3791 const Expr *Ex)
const {
3792 return Ex && State->get<LastEagerlyAssumeExprIfSuccessful>() == Ex;
3810 if (std::optional<Loc> LV =
X.getAs<
Loc>())
3821 if (std::optional<Loc> LV =
X.getAs<
Loc>())
3828 Dst.
insert(Engine.makePostStmtNode(A, state, Pred));
3851 for (
const auto &
Report : Class.getReports()) {
3852 const auto *PR = dyn_cast<PathSensitiveBugReport>(
Report.get());
3870 llvm::function_ref<
void(
const ExplodedNode *)> PreCallback,
3871 llvm::function_ref<
void(
const ExplodedNode *)> PostCallback,
3893 llvm::raw_string_ostream Out(Buf);
3895 const bool IsDot =
true;
3896 const unsigned int Space = 1;
3899 Out <<
"{ \"state_id\": " << State->getID()
3902 Indent(Out, Space, IsDot) <<
"\"program_points\": [\\l";
3908 Indent(Out, Space + 1, IsDot) <<
"{ ";
3910 Out <<
", \"tag\": ";
3912 Out <<
'\"' << Tag->getDebugTag() <<
'\"';
3915 Out <<
", \"node_id\": " << OtherNode->
getID() <<
3916 ", \"is_sink\": " << OtherNode->
isSink() <<
3924 Indent(Out, Space, IsDot) <<
"],\\l";
3937 llvm::DisplayGraph(Filename,
false, llvm::GraphProgram::DOT);
3941 std::string Filename =
DumpGraph(Nodes);
3942 llvm::DisplayGraph(Filename,
false, llvm::GraphProgram::DOT);
3947 std::vector<const ExplodedNode *> Src;
3950 for (
const auto &
Class : BR.equivalenceClasses()) {
3952 dyn_cast<PathSensitiveBugReport>(
Class.getReports()[0].get());
3955 const auto *N =
const_cast<ExplodedNode *
>(R->getErrorNode());
3962 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
3963 return llvm::WriteGraph(&G,
"ExprEngine",
false,
3965 std::string(Filename));
3969 StringRef Filename) {
3970 std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
3973 llvm::errs() <<
"warning: Trimmed ExplodedGraph is empty.\n";
3978 auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
3979 return llvm::WriteGraph(TrimmedG.get(),
"TrimmedExprEngine",
3981 "Trimmed Exploded Graph",
3982 std::string(Filename));
3986 static int index = 0;
3990void ExprEngine::anchor() { }
4002 bool IsCompound =
T->isArrayType() ||
T->isRecordType() ||
4003 T->isAnyComplexType() ||
T->isVectorType();
4006 if (Args.size() > 1 || (E->
isPRValue() && IsCompound && !IsTransparent)) {
4008 for (
Expr *E : llvm::reverse(Args))
4012 }
else if (Args.size() == 0) {
4015 Val = S->getSVal(Args.front(), SF);
4017 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 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)
static bool shouldJustCallCheckers(const Stmt *S, VisitKind K)
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 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
Stmt * getParentIgnoreParens(Stmt *) 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()
const ParentMap & getParentMap() const
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)
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 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 VisitObjCIndirectCopyRestoreExpr(const ObjCIndirectCopyRestoreExpr *OIE, 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.
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
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 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.
void VisitStmtExpr(const StmtExpr *SE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
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.
void VisitCXXParenListInitExpr(const CXXParenListInitExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
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 VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Create a C++ temporary object for an rvalue.
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 VisitCastExpr(const CastExpr *CastE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCastExpr - Transfer function logic for all casts (implicit and explicit).
void VisitAttributedStmt(const AttributedStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAttributedStmt - Transfer function logic for AttributedStmt.
void VisitPseudoObjectExpr(const PseudoObjectExpr *PE, ExplodedNode *Pred, 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)