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/SmallVector.h"
69#include "llvm/ADT/Statistic.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/SaveAndRestore.h"
76#include "llvm/Support/raw_ostream.h"
89#define DEBUG_TYPE "ExprEngine"
92 "The # of times RemoveDeadBindings is called");
94 "The # of aborted paths due to reaching the maximum block count in "
95 "a top level function");
97 "The # of aborted paths due to reaching the maximum block count in "
98 "an inlined function");
100 "The # of times we re-evaluated a call without inlining");
121class ConstructedObjectKey {
122 using ConstructedObjectKeyImpl =
123 std::pair<ConstructionContextItem, const LocationContext *>;
124 const ConstructedObjectKeyImpl Impl;
132 const LocationContext *getLocationContext()
const {
return Impl.second; }
135 return getLocationContext()->getDecl()->getASTContext();
138 void printJson(llvm::raw_ostream &Out,
PrinterHelper *Helper,
140 const Stmt *S = getItem().getStmtOrNull();
143 I = getItem().getCXXCtorInitializer();
146 Out <<
"\"stmt_id\": " << S->getID(getASTContext());
148 Out <<
"\"init_id\": " << I->
getID(getASTContext());
151 Out <<
", \"kind\": \"" << getItem().getKindAsString()
152 <<
"\", \"argument_index\": ";
155 Out << getItem().getIndex();
160 Out <<
", \"pretty\": ";
163 S->printJson(Out, Helper, PP,
true);
169 void Profile(llvm::FoldingSetNodeID &ID)
const {
171 ID.AddPointer(Impl.second);
174 bool operator==(
const ConstructedObjectKey &RHS)
const {
175 return Impl == RHS.Impl;
178 bool operator<(
const ConstructedObjectKey &RHS)
const {
179 return Impl < RHS.Impl;
184typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
195typedef llvm::ImmutableMap<
196 std::pair<const CXXConstructExpr *, const LocationContext *>,
unsigned>
197 IndexOfElementToConstructMap;
199 IndexOfElementToConstructMap)
204typedef llvm::ImmutableMap<
205 std::pair<const CXXConstructExpr *, const LocationContext *>,
unsigned>
209typedef llvm::ImmutableMap<const LocationContext *, unsigned>
218static const char* TagProviderName =
"ExprEngine";
223 : CTU(CTU), IsCTUEnabled(mgr.getAnalyzerOptions().IsNaiveCTUEnabled),
224 AMgr(mgr), AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
225 Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.getGraph()),
226 StateMgr(getContext(), mgr.getStoreManagerCreator(),
227 mgr.getConstraintManagerCreator(), G.getAllocator(), this),
228 SymMgr(StateMgr.getSymbolManager()), MRMgr(StateMgr.getRegionManager()),
229 svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
230 BR(mgr, *this), VisitedCallees(VisitedCalleesIn),
231 HowToInline(HowToInlineIn) {
232 unsigned TrimInterval = mgr.
options.GraphTrimInterval;
233 if (TrimInterval != 0) {
251 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
255 if (!II || !(II->
getName() ==
"main" && FD->getNumParams() > 0))
260 const auto *BT = dyn_cast<BuiltinType>(T);
261 if (!BT || !BT->isInteger())
264 const MemRegion *R = state->getRegion(PD, InitLoc);
273 std::optional<DefinedOrUnknownSVal> Constraint =
286 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
290 const MemRegion *R = state->getRegion(SelfD, InitLoc);
293 if (std::optional<Loc> LV =
V.getAs<
Loc>()) {
295 state = state->assume(*LV,
true);
296 assert(state &&
"'self' cannot be null");
300 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
301 if (!MD->isStatic()) {
308 SVal V = state->getSVal(L);
309 if (std::optional<Loc> LV =
V.getAs<
Loc>()) {
310 state = state->assume(*LV,
true);
311 assert(state &&
"'this' cannot be null");
323 const SubRegion **OutRegionWithAdjustments) {
329 SVal InitValWithAdjustments = State->getSVal(InitWithAdjustments, LC);
333 if (!isa<NonLoc>(InitValWithAdjustments)) {
334 if (OutRegionWithAdjustments)
335 *OutRegionWithAdjustments =
nullptr;
338 Result = InitWithAdjustments;
342 assert(!isa<Loc>(InitValWithAdjustments) ||
344 Result->getType()->isMemberPointerType());
376 CommaLHSs, Adjustments);
384 if (
const auto *MT = dyn_cast<MaterializeTemporaryExpr>(
Result)) {
386 State = finishObjectConstruction(State, MT, LC);
387 State = State->BindExpr(
Result, LC, *
V);
417 State = State->invalidateRegions(Reg, InitWithAdjustments,
419 nullptr,
nullptr,
nullptr);
432 SVal InitVal = State->getSVal(Init, LC);
436 State = State->bindLoc(BaseReg.
castAs<
Loc>(), InitVal, LC,
false);
440 if (InitValWithAdjustments.
isUnknown()) {
448 State->bindLoc(Reg.
castAs<
Loc>(), InitValWithAdjustments, LC,
false);
450 State = State->bindLoc(BaseReg.
castAs<
Loc>(), InitVal, LC,
false);
456 if (
Result->isGLValue()) {
457 State = State->BindExpr(
Result, LC, Reg);
459 State = State->BindExpr(
Result, LC, InitValWithAdjustments);
465 if (OutRegionWithAdjustments)
466 *OutRegionWithAdjustments = cast<SubRegion>(Reg.
getAsRegion());
475 assert(!State->contains<IndexOfElementToConstruct>(Key) || Idx > 0);
477 return State->set<IndexOfElementToConstruct>(Key, Idx);
480std::optional<unsigned>
483 const unsigned *
V = State->get<PendingInitLoop>({E, LCtx->
getStackFrame()});
484 return V ? std::make_optional(*
V) : std::nullopt;
492 assert(E && State->contains<PendingInitLoop>(Key));
493 return State->remove<PendingInitLoop>(Key);
502 assert(!State->contains<PendingInitLoop>(Key) && Size > 0);
504 return State->set<PendingInitLoop>(Key, Size);
507std::optional<unsigned>
512 State->get<IndexOfElementToConstruct>({E, LCtx->
getStackFrame()});
513 return V ? std::make_optional(*
V) : std::nullopt;
522 assert(E && State->contains<IndexOfElementToConstruct>(Key));
523 return State->remove<IndexOfElementToConstruct>(Key);
526std::optional<unsigned>
529 assert(LCtx &&
"LocationContext shouldn't be null!");
533 return V ? std::make_optional(*
V) : std::nullopt;
538 assert(LCtx &&
"LocationContext shouldn't be null!");
542 return State->set<PendingArrayDestruction>(Key, Idx);
548 assert(LCtx &&
"LocationContext shouldn't be null!");
552 assert(LCtx && State->contains<PendingArrayDestruction>(Key));
553 return State->remove<PendingArrayDestruction>(Key);
562 const Expr *Init =
nullptr;
564 if (
auto DS = dyn_cast_or_null<DeclStmt>(Item.
getStmtOrNull())) {
565 if (
auto VD = dyn_cast_or_null<VarDecl>(DS->getSingleDecl()))
566 Init = VD->getInit();
569 if (
auto LE = dyn_cast_or_null<LambdaExpr>(Item.
getStmtOrNull()))
570 Init = *(
LE->capture_init_begin() + Item.
getIndex());
578 if (
const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init))
587 assert((!State->get<ObjectsUnderConstruction>(Key) ||
588 Key.getItem().getKind() ==
590 State->contains<IndexOfElementToConstruct>(
591 {dyn_cast_or_null<CXXConstructExpr>(Init), LC})) &&
592 "The object is already marked as `UnderConstruction`, when it's not "
594 return State->set<ObjectsUnderConstruction>(Key,
V);
602 const SVal *
V = State->get<ObjectsUnderConstruction>(Key);
603 return V ? std::make_optional(*
V) : std::nullopt;
611 assert(State->contains<ObjectsUnderConstruction>(Key));
612 return State->remove<ObjectsUnderConstruction>(Key);
618 ConstructedObjectKey Key({BTE,
true}, LC);
621 return State->set<ObjectsUnderConstruction>(Key,
UnknownVal());
628 ConstructedObjectKey Key({BTE,
true}, LC);
629 assert(State->contains<ObjectsUnderConstruction>(Key));
630 return State->remove<ObjectsUnderConstruction>(Key);
636 ConstructedObjectKey Key({BTE,
true}, LC);
637 return State->contains<ObjectsUnderConstruction>(Key);
645 assert(LC &&
"ToLC must be a parent of FromLC!");
646 for (
auto I : State->get<ObjectsUnderConstruction>())
647 if (I.first.getLocationContext() == LC)
663 SVal cond,
bool assumption) {
682 unsigned int Space = 0,
bool IsDot =
false) {
687 bool HasItem =
false;
690 const ConstructedObjectKey *LastKey =
nullptr;
691 for (
const auto &I : State->get<ObjectsUnderConstruction>()) {
692 const ConstructedObjectKey &Key = I.first;
693 if (Key.getLocationContext() != LCtx)
704 for (
const auto &I : State->get<ObjectsUnderConstruction>()) {
705 const ConstructedObjectKey &Key = I.first;
707 if (Key.getLocationContext() != LCtx)
710 Indent(Out, Space, IsDot) <<
"{ ";
711 Key.printJson(Out,
nullptr, PP);
712 Out <<
", \"value\": \"" <<
Value <<
"\" }";
720 Indent(Out, --Space, IsDot) <<
']';
728 const LocationContext *LCtx,
unsigned int Space = 0,
bool IsDot =
false) {
729 using KeyT = std::pair<const Expr *, const LocationContext *>;
735 bool HasItem =
false;
739 for (
const auto &I : State->get<IndexOfElementToConstruct>()) {
740 const KeyT &Key = I.first;
741 if (Key.second != LCtx)
752 for (
const auto &I : State->get<IndexOfElementToConstruct>()) {
753 const KeyT &Key = I.first;
754 unsigned Value = I.second;
755 if (Key.second != LCtx)
758 Indent(Out, Space, IsDot) <<
"{ ";
761 const Expr *E = Key.first;
762 Out <<
"\"stmt_id\": " << E->
getID(Context);
765 Out <<
", \"kind\": null";
768 Out <<
", \"pretty\": ";
774 Out <<
", \"value\": \"Current index: " <<
Value - 1 <<
"\" }";
782 Indent(Out, --Space, IsDot) <<
']';
791 unsigned int Space = 0,
792 bool IsDot =
false) {
793 using KeyT = std::pair<const CXXConstructExpr *, const LocationContext *>;
799 bool HasItem =
false;
803 for (
const auto &I : State->get<PendingInitLoop>()) {
804 const KeyT &Key = I.first;
805 if (Key.second != LCtx)
816 for (
const auto &I : State->get<PendingInitLoop>()) {
817 const KeyT &Key = I.first;
818 unsigned Value = I.second;
819 if (Key.second != LCtx)
822 Indent(Out, Space, IsDot) <<
"{ ";
825 Out <<
"\"stmt_id\": " << E->
getID(Context);
827 Out <<
", \"kind\": null";
828 Out <<
", \"pretty\": ";
834 Out <<
", \"value\": \"Flattened size: " <<
Value <<
"\"}";
842 Indent(Out, --Space, IsDot) <<
']';
851 unsigned int Space = 0,
bool IsDot =
false) {
855 bool HasItem =
false;
858 KeyT LastKey =
nullptr;
859 for (
const auto &I : State->get<PendingArrayDestruction>()) {
860 const KeyT &Key = I.first;
872 for (
const auto &I : State->get<PendingArrayDestruction>()) {
873 const KeyT &Key = I.first;
877 Indent(Out, Space, IsDot) <<
"{ ";
879 Out <<
"\"stmt_id\": null";
880 Out <<
", \"kind\": null";
881 Out <<
", \"pretty\": \"Current index: \"";
882 Out <<
", \"value\": \"" << I.second <<
"\" }";
890 Indent(Out, --Space, IsDot) <<
']';
904template <
typename Trait,
typename Printer,
typename... Args>
907 const char *NL,
unsigned int Space,
bool IsDot,
908 const char *jsonPropertyName, Printer printer, Args &&...args) {
916 static_assert(std::is_function_v<std::remove_pointer_t<Printer>>,
917 "Printer is not a function!");
918 static_assert(std::is_convertible_v<Printer, RequiredType>,
919 "Printer doesn't have the required type!");
921 if (LCtx && !State->get<Trait>().isEmpty()) {
922 Indent(Out, Space, IsDot) <<
'\"' << jsonPropertyName <<
"\": ";
926 printer(Out, State, NL, LC, Space, IsDot, std::forward<Args>(args)...);
930 Indent(Out, Space, IsDot) <<
"]," << NL;
936 unsigned int Space,
bool IsDot)
const {
938 printStateTraitWithLocationContextJson<ObjectsUnderConstruction>(
939 Out, State, LCtx, NL, Space, IsDot,
"constructing_objects",
941 printStateTraitWithLocationContextJson<IndexOfElementToConstruct>(
942 Out, State, LCtx, NL, Space, IsDot,
"index_of_element",
944 printStateTraitWithLocationContextJson<PendingInitLoop>(
945 Out, State, LCtx, NL, Space, IsDot,
"pending_init_loops",
947 printStateTraitWithLocationContextJson<PendingArrayDestruction>(
948 Out, State, LCtx, NL, Space, IsDot,
"pending_destructors",
964 currStmtIdx = StmtIdx;
1024 const Stmt *ReferenceStmt,
1026 const Stmt *DiagnosticStmt,
1029 ReferenceStmt ==
nullptr || isa<ReturnStmt>(ReferenceStmt))
1030 &&
"PostStmt is not generally supported by the SymbolReaper yet");
1031 assert(LC &&
"Must pass the current (or expiring) LocationContext");
1033 if (!DiagnosticStmt) {
1034 DiagnosticStmt = ReferenceStmt;
1035 assert(DiagnosticStmt &&
"Required for clearing a LocationContext");
1038 NumRemoveDeadBindings++;
1044 if (!ReferenceStmt) {
1046 "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");
1053 for (
auto I : CleanedState->get<ObjectsUnderConstruction>()) {
1054 if (
SymbolRef Sym = I.second.getAsSymbol())
1056 if (
const MemRegion *MR = I.second.getAsRegion())
1066 CleanedState, SFC, SymReaper);
1075 DiagnosticStmt, *
this, K);
1081 for (
const auto I : CheckedSet) {
1089 "Checkers are not allowed to modify the Environment as a part of "
1090 "checkDeadSymbols processing.");
1092 "Checkers are not allowed to modify the Store as a part of "
1093 "checkDeadSymbols processing.");
1099 Bldr.
generateNode(DiagnosticStmt, I, CleanedCheckerSt, &cleanupTag, K);
1109 "Error evaluating statement");
1118 CleanedStates.
Add(Pred);
1122 for (
const auto I : CleanedStates) {
1125 Visit(currStmt, I, DstI);
1136 "Error evaluating end of the loop");
1142 if(AMgr.
options.ShouldUnrollLoops)
1159 "Error evaluating initializer");
1163 const auto *
decl = cast<CXXConstructorDecl>(stackFrame->getDecl());
1178 State = finishObjectConstruction(State, BMI, LC);
1180 PostStore PS(Init, LC,
nullptr,
nullptr);
1189 FieldLoc = State->getLValue(BMI->
getMember(), thisVal);
1193 if (Init->getType()->isArrayType()) {
1197 while ((ASE = dyn_cast<ArraySubscriptExpr>(Init)))
1200 SVal LValue = State->getSVal(Init, stackFrame);
1201 if (!Field->getType()->isReferenceType())
1202 if (std::optional<Loc> LValueLoc = LValue.
getAs<
Loc>())
1203 InitVal = State->getSVal(*LValueLoc);
1213 InitVal = State->getSVal(BMI->
getInit(), stackFrame);
1217 evalBind(Tmp, Init, Pred, FieldLoc, InitVal,
true, &PP);
1230 for (
const auto I : Tmp) {
1239std::pair<ProgramStateRef, uint64_t>
1240ExprEngine::prepareStateForArrayDestruction(
const ProgramStateRef State,
1244 SVal *ElementCountVal) {
1245 assert(Region !=
nullptr &&
"Not-null region expected");
1248 while (
const auto *NTy = dyn_cast<ArrayType>(Ty))
1249 Ty = NTy->getElementType().getDesugaredType(
getContext());
1253 if (ElementCountVal)
1254 *ElementCountVal = ElementCount;
1262 if (!ElementCount.isConstant())
1265 Idx = ElementCount.getAsInteger()->getLimitedValue();
1273 return {setPendingArrayDestruction(State, LCtx, Idx), Idx};
1296 llvm_unreachable(
"Unexpected dtor kind.");
1311 if (Opts.MayInlineCXXAllocator)
1337 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
1346 varType = cast<TypedValueRegion>(Region)->getValueType();
1350 if (isa<ArrayType>(varType)) {
1352 std::tie(state, Idx) = prepareStateForArrayDestruction(
1353 state, Region, varType, LCtx, &ElementCount);
1356 uint64_t ArrayLength = ElementCount.
getAsInteger()->getLimitedValue();
1357 assert(ArrayLength &&
1358 "An automatic dtor for a 0 length array shouldn't be triggered!");
1363 "ExprEngine",
"Skipping automatic 0 length array destruction, "
1364 "which shouldn't be in the CFG.");
1382 "Prepare for object destruction");
1392 false, Pred, Dst, CallOpts);
1403 SVal ArgVal = State->getSVal(Arg, LCtx);
1407 if (State->isNull(ArgVal).isConstrainedTrue()) {
1418 auto getDtorDecl = [](
const QualType &DTy) {
1431 DTy = AT->getElementType();
1435 std::tie(State, Idx) = prepareStateForArrayDestruction(
1436 State, ArgR, DTy, LCtx, &ElementCount);
1444 "ExprEngine",
"Skipping 0 length array delete destruction");
1452 ArgR = State->getLValue(DTy, svalBuilder.
makeArrayIndex(Idx), ArgVal)
1459 "Prepare for object destruction");
1475 const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->
getDecl());
1488 true, Pred, Dst, CallOpts);
1499 const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->
getDecl());
1500 Loc ThisStorageLoc =
1502 Loc ThisLoc = State->getSVal(ThisStorageLoc).castAs<
Loc>();
1503 SVal FieldVal = State->getLValue(
Member, ThisLoc);
1506 if (isa<ArrayType>(T)) {
1508 std::tie(State, Idx) = prepareStateForArrayDestruction(
1509 State, FieldVal.getAsRegion(), T, LCtx, &ElementCount);
1512 uint64_t ArrayLength = ElementCount.
getAsInteger()->getLimitedValue();
1513 assert(ArrayLength &&
1514 "A member dtor for a 0 length array shouldn't be triggered!");
1519 "ExprEngine",
"Skipping member 0 length array destruction, which "
1520 "shouldn't be in the CFG.");
1537 "Prepare for object destruction");
1547 false, Pred, Dst, CallOpts);
1565 MR =
V->getAsRegion();
1570 if (isDestructorElided(State, BTE, LC)) {
1571 State = cleanupElidedDestructor(State, BTE, LC);
1587 assert(CleanDtorState.
size() <= 1);
1589 CleanDtorState.
empty() ? Pred : *CleanDtorState.
begin();
1612 T = AT->getElementType();
1623 false, CleanPred, Dst, CallOpts);
1665 State = addObjectUnderConstruction(State, BTE, LC,
UnknownVal());
1675 class CollectReachableSymbolsCallback final :
public SymbolVisitor {
1680 : Symbols(Symbols) {}
1684 bool VisitSymbol(
SymbolRef Sym)
override {
1685 Symbols.insert(Sym);
1690 CollectReachableSymbolsCallback CallBack(Symbols);
1692 State->scanReachableSymbols(
V, CallBack);
1695 State, CallBack.getSymbols(), Call, K,
nullptr);
1701 S->getBeginLoc(),
"Error evaluating statement");
1705 assert(!isa<Expr>(S) || S == cast<Expr>(S)->IgnoreParens());
1707 switch (S->getStmtClass()) {
1709 case Stmt::CXXDependentScopeMemberExprClass:
1710 case Stmt::CXXTryStmtClass:
1711 case Stmt::CXXTypeidExprClass:
1712 case Stmt::CXXUuidofExprClass:
1713 case Stmt::CXXFoldExprClass:
1714 case Stmt::MSPropertyRefExprClass:
1715 case Stmt::MSPropertySubscriptExprClass:
1716 case Stmt::CXXUnresolvedConstructExprClass:
1717 case Stmt::DependentScopeDeclRefExprClass:
1718 case Stmt::ArrayTypeTraitExprClass:
1719 case Stmt::ExpressionTraitExprClass:
1720 case Stmt::UnresolvedLookupExprClass:
1721 case Stmt::UnresolvedMemberExprClass:
1722 case Stmt::TypoExprClass:
1723 case Stmt::RecoveryExprClass:
1724 case Stmt::CXXNoexceptExprClass:
1725 case Stmt::PackExpansionExprClass:
1726 case Stmt::SubstNonTypeTemplateParmPackExprClass:
1727 case Stmt::FunctionParmPackExprClass:
1728 case Stmt::CoroutineBodyStmtClass:
1729 case Stmt::CoawaitExprClass:
1730 case Stmt::DependentCoawaitExprClass:
1731 case Stmt::CoreturnStmtClass:
1732 case Stmt::CoyieldExprClass:
1733 case Stmt::SEHTryStmtClass:
1734 case Stmt::SEHExceptStmtClass:
1735 case Stmt::SEHLeaveStmtClass:
1736 case Stmt::SEHFinallyStmtClass:
1737 case Stmt::OMPCanonicalLoopClass:
1738 case Stmt::OMPParallelDirectiveClass:
1739 case Stmt::OMPSimdDirectiveClass:
1740 case Stmt::OMPForDirectiveClass:
1741 case Stmt::OMPForSimdDirectiveClass:
1742 case Stmt::OMPSectionsDirectiveClass:
1743 case Stmt::OMPSectionDirectiveClass:
1744 case Stmt::OMPSingleDirectiveClass:
1745 case Stmt::OMPMasterDirectiveClass:
1746 case Stmt::OMPCriticalDirectiveClass:
1747 case Stmt::OMPParallelForDirectiveClass:
1748 case Stmt::OMPParallelForSimdDirectiveClass:
1749 case Stmt::OMPParallelSectionsDirectiveClass:
1750 case Stmt::OMPParallelMasterDirectiveClass:
1751 case Stmt::OMPParallelMaskedDirectiveClass:
1752 case Stmt::OMPTaskDirectiveClass:
1753 case Stmt::OMPTaskyieldDirectiveClass:
1754 case Stmt::OMPBarrierDirectiveClass:
1755 case Stmt::OMPTaskwaitDirectiveClass:
1756 case Stmt::OMPErrorDirectiveClass:
1757 case Stmt::OMPTaskgroupDirectiveClass:
1758 case Stmt::OMPFlushDirectiveClass:
1759 case Stmt::OMPDepobjDirectiveClass:
1760 case Stmt::OMPScanDirectiveClass:
1761 case Stmt::OMPOrderedDirectiveClass:
1762 case Stmt::OMPAtomicDirectiveClass:
1763 case Stmt::OMPTargetDirectiveClass:
1764 case Stmt::OMPTargetDataDirectiveClass:
1765 case Stmt::OMPTargetEnterDataDirectiveClass:
1766 case Stmt::OMPTargetExitDataDirectiveClass:
1767 case Stmt::OMPTargetParallelDirectiveClass:
1768 case Stmt::OMPTargetParallelForDirectiveClass:
1769 case Stmt::OMPTargetUpdateDirectiveClass:
1770 case Stmt::OMPTeamsDirectiveClass:
1771 case Stmt::OMPCancellationPointDirectiveClass:
1772 case Stmt::OMPCancelDirectiveClass:
1773 case Stmt::OMPTaskLoopDirectiveClass:
1774 case Stmt::OMPTaskLoopSimdDirectiveClass:
1775 case Stmt::OMPMasterTaskLoopDirectiveClass:
1776 case Stmt::OMPMaskedTaskLoopDirectiveClass:
1777 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1778 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1779 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1780 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1781 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1782 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1783 case Stmt::OMPDistributeDirectiveClass:
1784 case Stmt::OMPDistributeParallelForDirectiveClass:
1785 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1786 case Stmt::OMPDistributeSimdDirectiveClass:
1787 case Stmt::OMPTargetParallelForSimdDirectiveClass:
1788 case Stmt::OMPTargetSimdDirectiveClass:
1789 case Stmt::OMPTeamsDistributeDirectiveClass:
1790 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1791 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1792 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1793 case Stmt::OMPTargetTeamsDirectiveClass:
1794 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1795 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1796 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1797 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1798 case Stmt::OMPTileDirectiveClass:
1799 case Stmt::OMPInteropDirectiveClass:
1800 case Stmt::OMPDispatchDirectiveClass:
1801 case Stmt::OMPMaskedDirectiveClass:
1802 case Stmt::OMPGenericLoopDirectiveClass:
1803 case Stmt::OMPTeamsGenericLoopDirectiveClass:
1804 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
1805 case Stmt::OMPParallelGenericLoopDirectiveClass:
1806 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1807 case Stmt::CapturedStmtClass:
1808 case Stmt::OMPUnrollDirectiveClass:
1809 case Stmt::OMPMetaDirectiveClass: {
1815 case Stmt::ParenExprClass:
1816 llvm_unreachable(
"ParenExprs already handled.");
1817 case Stmt::GenericSelectionExprClass:
1818 llvm_unreachable(
"GenericSelectionExprs already handled.");
1821 case Stmt::BreakStmtClass:
1822 case Stmt::CaseStmtClass:
1823 case Stmt::CompoundStmtClass:
1824 case Stmt::ContinueStmtClass:
1825 case Stmt::CXXForRangeStmtClass:
1826 case Stmt::DefaultStmtClass:
1827 case Stmt::DoStmtClass:
1828 case Stmt::ForStmtClass:
1829 case Stmt::GotoStmtClass:
1830 case Stmt::IfStmtClass:
1831 case Stmt::IndirectGotoStmtClass:
1832 case Stmt::LabelStmtClass:
1834 case Stmt::NullStmtClass:
1835 case Stmt::SwitchStmtClass:
1836 case Stmt::WhileStmtClass:
1837 case Expr::MSDependentExistsStmtClass:
1838 llvm_unreachable(
"Stmt should not be in analyzer evaluation loop");
1839 case Stmt::ImplicitValueInitExprClass:
1843 llvm_unreachable(
"Should be pruned from CFG");
1845 case Stmt::ObjCSubscriptRefExprClass:
1846 case Stmt::ObjCPropertyRefExprClass:
1847 llvm_unreachable(
"These are handled by PseudoObjectExpr");
1849 case Stmt::GNUNullExprClass: {
1852 state = state->BindExpr(
1859 case Stmt::ObjCAtSynchronizedStmtClass:
1865 case Expr::ConstantExprClass:
1866 case Stmt::ExprWithCleanupsClass:
1870 case Stmt::CXXBindTemporaryExprClass: {
1881 case Stmt::ArrayInitLoopExprClass:
1887 case Stmt::DesignatedInitExprClass:
1888 case Stmt::DesignatedInitUpdateExprClass:
1889 case Stmt::ArrayInitIndexExprClass:
1890 case Stmt::ExtVectorElementExprClass:
1891 case Stmt::ImaginaryLiteralClass:
1892 case Stmt::ObjCAtCatchStmtClass:
1893 case Stmt::ObjCAtFinallyStmtClass:
1894 case Stmt::ObjCAtTryStmtClass:
1895 case Stmt::ObjCAutoreleasePoolStmtClass:
1896 case Stmt::ObjCEncodeExprClass:
1897 case Stmt::ObjCIsaExprClass:
1898 case Stmt::ObjCProtocolExprClass:
1899 case Stmt::ObjCSelectorExprClass:
1900 case Stmt::ParenListExprClass:
1901 case Stmt::ShuffleVectorExprClass:
1902 case Stmt::ConvertVectorExprClass:
1903 case Stmt::VAArgExprClass:
1904 case Stmt::CUDAKernelCallExprClass:
1905 case Stmt::OpaqueValueExprClass:
1906 case Stmt::AsTypeExprClass:
1907 case Stmt::ConceptSpecializationExprClass:
1908 case Stmt::CXXRewrittenBinaryOperatorClass:
1909 case Stmt::RequiresExprClass:
1910 case Expr::CXXParenListInitExprClass:
1915 case Stmt::PredefinedExprClass:
1916 case Stmt::AddrLabelExprClass:
1917 case Stmt::AttributedStmtClass:
1918 case Stmt::IntegerLiteralClass:
1919 case Stmt::FixedPointLiteralClass:
1920 case Stmt::CharacterLiteralClass:
1921 case Stmt::CXXScalarValueInitExprClass:
1922 case Stmt::CXXBoolLiteralExprClass:
1923 case Stmt::ObjCBoolLiteralExprClass:
1924 case Stmt::ObjCAvailabilityCheckExprClass:
1925 case Stmt::FloatingLiteralClass:
1926 case Stmt::NoInitExprClass:
1927 case Stmt::SizeOfPackExprClass:
1928 case Stmt::StringLiteralClass:
1929 case Stmt::SourceLocExprClass:
1930 case Stmt::ObjCStringLiteralClass:
1931 case Stmt::CXXPseudoDestructorExprClass:
1932 case Stmt::SubstNonTypeTemplateParmExprClass:
1933 case Stmt::CXXNullPtrLiteralExprClass:
1934 case Stmt::OMPArraySectionExprClass:
1935 case Stmt::OMPArrayShapingExprClass:
1936 case Stmt::OMPIteratorExprClass:
1937 case Stmt::SYCLUniqueStableNameExprClass:
1938 case Stmt::TypeTraitExprClass: {
1947 case Stmt::CXXDefaultArgExprClass:
1948 case Stmt::CXXDefaultInitExprClass: {
1957 if (
const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
1958 ArgE = DefE->getExpr();
1959 else if (
const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
1960 ArgE = DefE->getExpr();
1962 llvm_unreachable(
"unknown constant wrapper kind");
1964 bool IsTemporary =
false;
1965 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
1966 ArgE = MTE->getSubExpr();
1970 std::optional<SVal> ConstantVal = svalBuilder.
getConstantVal(ArgE);
1975 for (
const auto I : PreVisit) {
1977 State = State->BindExpr(S, LCtx, *ConstantVal);
1979 State = createTemporaryRegionIfNeeded(State, LCtx,
1991 case Stmt::CXXStdInitializerListExprClass:
1992 case Expr::ObjCArrayLiteralClass:
1993 case Expr::ObjCDictionaryLiteralClass:
1994 case Expr::ObjCBoxedExprClass: {
2003 const auto *Ex = cast<Expr>(S);
2004 QualType resultType = Ex->getType();
2006 for (
const auto N : preVisit) {
2015 if (!(isa<ObjCBoxedExpr>(Ex) &&
2016 !cast<ObjCBoxedExpr>(Ex)->getSubExpr()
2018 for (
auto Child : Ex->children()) {
2020 SVal Val = State->getSVal(Child, LCtx);
2032 case Stmt::ArraySubscriptExprClass:
2038 case Stmt::MatrixSubscriptExprClass:
2039 llvm_unreachable(
"Support for MatrixSubscriptExpr is not implemented.");
2042 case Stmt::GCCAsmStmtClass:
2048 case Stmt::MSAsmStmtClass:
2054 case Stmt::BlockExprClass:
2060 case Stmt::LambdaExprClass:
2061 if (AMgr.
options.ShouldInlineLambdas) {
2071 case Stmt::BinaryOperatorClass: {
2072 const auto *B = cast<BinaryOperator>(S);
2073 if (B->isLogicalOp()) {
2079 else if (B->getOpcode() == BO_Comma) {
2083 state->getSVal(B->getRHS(),
2090 if (AMgr.
options.ShouldEagerlyAssume &&
2091 (B->isRelationalOp() || B->isEqualityOp())) {
2103 case Stmt::CXXOperatorCallExprClass: {
2104 const auto *OCE = cast<CXXOperatorCallExpr>(S);
2108 const Decl *Callee = OCE->getCalleeDecl();
2109 if (
const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
2110 if (MD->isInstance()) {
2114 createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
2115 if (NewState != State) {
2128 case Stmt::CallExprClass:
2129 case Stmt::CXXMemberCallExprClass:
2130 case Stmt::UserDefinedLiteralClass:
2136 case Stmt::CXXCatchStmtClass:
2142 case Stmt::CXXTemporaryObjectExprClass:
2143 case Stmt::CXXConstructExprClass:
2149 case Stmt::CXXInheritedCtorInitExprClass:
2156 case Stmt::CXXNewExprClass: {
2163 for (
const auto i : PreVisit)
2171 case Stmt::CXXDeleteExprClass: {
2174 const auto *CDE = cast<CXXDeleteExpr>(S);
2179 for (
const auto i : PostVisit)
2188 case Stmt::ChooseExprClass: {
2190 const auto *
C = cast<ChooseExpr>(S);
2196 case Stmt::CompoundAssignOperatorClass:
2202 case Stmt::CompoundLiteralExprClass:
2208 case Stmt::BinaryConditionalOperatorClass:
2209 case Stmt::ConditionalOperatorClass: {
2211 const auto *
C = cast<AbstractConditionalOperator>(S);
2217 case Stmt::CXXThisExprClass:
2223 case Stmt::DeclRefExprClass: {
2225 const auto *DE = cast<DeclRefExpr>(S);
2231 case Stmt::DeclStmtClass:
2237 case Stmt::ImplicitCastExprClass:
2238 case Stmt::CStyleCastExprClass:
2239 case Stmt::CXXStaticCastExprClass:
2240 case Stmt::CXXDynamicCastExprClass:
2241 case Stmt::CXXReinterpretCastExprClass:
2242 case Stmt::CXXConstCastExprClass:
2243 case Stmt::CXXFunctionalCastExprClass:
2244 case Stmt::BuiltinBitCastExprClass:
2245 case Stmt::ObjCBridgedCastExprClass:
2246 case Stmt::CXXAddrspaceCastExprClass: {
2248 const auto *
C = cast<CastExpr>(S);
2258 case Expr::MaterializeTemporaryExprClass: {
2260 const auto *MTE = cast<MaterializeTemporaryExpr>(S);
2264 for (
const auto i : dstPrevisit)
2271 case Stmt::InitListExprClass:
2277 case Stmt::MemberExprClass:
2283 case Stmt::AtomicExprClass:
2289 case Stmt::ObjCIvarRefExprClass:
2295 case Stmt::ObjCForCollectionStmtClass:
2301 case Stmt::ObjCMessageExprClass:
2307 case Stmt::ObjCAtThrowStmtClass:
2308 case Stmt::CXXThrowExprClass:
2314 case Stmt::ReturnStmtClass:
2320 case Stmt::OffsetOfExprClass: {
2326 for (
const auto Node : PreVisit)
2334 case Stmt::UnaryExprOrTypeTraitExprClass:
2341 case Stmt::StmtExprClass: {
2342 const auto *SE = cast<StmtExpr>(S);
2344 if (SE->getSubStmt()->body_empty()) {
2347 &&
"Empty statement expression must have void type.");
2351 if (
const auto *LastExpr =
2352 dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
2356 state->getSVal(LastExpr,
2362 case Stmt::UnaryOperatorClass: {
2364 const auto *
U = cast<UnaryOperator>(S);
2365 if (AMgr.
options.ShouldEagerlyAssume && (
U->getOpcode() == UO_LNot)) {
2376 case Stmt::PseudoObjectExprClass: {
2379 const auto *PE = cast<PseudoObjectExpr>(S);
2380 if (
const Expr *
Result = PE->getResultExpr()) {
2394 case Expr::ObjCIndirectCopyRestoreExprClass: {
2400 const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);
2401 const Expr *E = OIE->getSubExpr();
2415 assert(CalleeSF && CallerSF);
2422 BeforeProcessingCall = N;
2437 if (SP->getStmt() == CE)
2442 if (!BeforeProcessingCall)
2471 NumTimesRetriedWithoutInlining++;
2482 if(AMgr.
options.ShouldUnrollLoops) {
2487 Pred, maxBlockVisitOnPath);
2488 if (NewState != Pred->
getState()) {
2504 AMgr.
options.ShouldWidenLoops) {
2506 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt>(Term))
2527 (*G.
roots_begin())->getLocation().getLocationContext();
2536 replayWithoutInlining(Pred, CalleeLC)))
2538 NumMaxBlockCountReachedInInlined++;
2540 NumMaxBlockCountReached++;
2543 Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
2561 const auto *Ex = dyn_cast<Expr>(
Condition);
2566 bool bitsInit =
false;
2568 while (
const auto *CE = dyn_cast<CastExpr>(Ex)) {
2575 if (!bitsInit || newBits < bits) {
2580 Ex = CE->getSubExpr();
2590 return state->getSVal(Ex, LCtx);
2596 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2597 if (!BO || !BO->isLogicalOp()) {
2600 Condition = BO->getRHS()->IgnoreParens();
2622 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2625 const auto *BO = dyn_cast<BinaryOperator>(
Condition);
2626 if (!BO || !BO->isLogicalOp())
2630 "Other kinds of branches are handled separately!");
2641 for (; I != E; ++I) {
2646 const Stmt *LastStmt = CS->getStmt();
2650 llvm_unreachable(
"could not resolve condition");
2654 std::pair<const ObjCForCollectionStmt *, const LocationContext *>;
2661 assert(!State->contains<ObjCForHasMoreIterations>({O, LC}));
2662 return State->set<ObjCForHasMoreIterations>({O, LC}, HasMoreIteraton);
2669 assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
2670 return State->remove<ObjCForHasMoreIterations>({O, LC});
2676 assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
2677 return *State->get<ObjCForHasMoreIterations>({O, LC});
2683static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
2686 if (
const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(
Condition)) {
2687 bool HasMoreIteraton =
2694 if (HasMoreIteraton)
2695 return std::pair<ProgramStateRef, ProgramStateRef>{State,
nullptr};
2697 return std::pair<ProgramStateRef, ProgramStateRef>{
nullptr, State};
2701 if (
X.isUnknownOrUndef()) {
2703 if (
const auto *Ex = dyn_cast<Expr>(
Condition)) {
2704 if (Ex->getType()->isIntegralOrEnumerationType()) {
2711 N->
getState()->getStateManager().getContext());
2721 if (
X.isUnknownOrUndef())
2722 return std::nullopt;
2727 return State->assume(
V);
2737 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2740 currBldrCtx = &BldCtx;
2750 if (
const auto *Ex = dyn_cast<Expr>(
Condition))
2756 "Error evaluating branch");
2762 if (CheckersOutSet.
empty())
2767 if (PredN->isSink())
2774 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2776 assert(!isa<ObjCForCollectionStmt>(
Condition));
2781 if (StTrue && StFalse)
2782 assert(!isa<ObjCForCollectionStmt>(
Condition));
2800 currBldrCtx =
nullptr;
2806 llvm::ImmutableSet<const VarDecl *>)
2815 currBldrCtx = &BuilderCtx;
2819 bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
2823 state = state->add<InitializedGlobalsSet>(VD);
2826 builder.generateNode(state, initHasRun, Pred);
2827 builder.markInfeasible(!initHasRun);
2829 currBldrCtx =
nullptr;
2850 for (iterator I = builder.
begin(), E = builder.
end(); I != E; ++I) {
2851 if (I.getLabel() == L) {
2857 llvm_unreachable(
"No block with label.");
2860 if (isa<UndefinedVal, loc::ConcreteInt>(
V)) {
2871 for (iterator I = builder.
begin(), E = builder.
end(); I != E; ++I)
2891 State = finishArgumentConstruction(
2906 while (LC != ToLC) {
2907 assert(LC &&
"ToLC must be a parent of FromLC!");
2908 for (
auto I : State->get<ObjectsUnderConstruction>())
2909 if (I.first.getLocationContext() == LC) {
2913 assert(I.first.getItem().getKind() ==
2915 I.first.getItem().getKind() ==
2917 State = State->remove<ObjectsUnderConstruction>(I.first);
2935 assert(areAllObjectsFullyConstructed(Pred->
getState(),
2948 for (
const auto I : AfterRemovedDead)
2966 if (CondV_untested.
isUndef()) {
2977 iterator I = builder.
begin(), EI = builder.
end();
2978 bool defaultIsFeasible = I == EI;
2980 for ( ; I != EI; ++I) {
2985 const CaseStmt *Case = I.getCase();
2999 if (std::optional<NonLoc> NL = CondV.
getAs<
NonLoc>())
3000 std::tie(StateCase, DefaultSt) =
3001 DefaultSt->assumeInclusiveRange(*NL, V1, V2);
3003 StateCase = DefaultSt;
3011 defaultIsFeasible =
true;
3013 defaultIsFeasible =
false;
3018 if (!defaultIsFeasible)
3050 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
3053 assert(Ex->
isGLValue() || VD->getType()->isVoidType());
3056 const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D);
3057 const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
3058 std::optional<std::pair<SVal, QualType>> VInfo;
3060 if (AMgr.
options.ShouldInlineLambdas && DeclRefEx &&
3061 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
3062 MD->getParent()->isLambda()) {
3065 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
3071 if (
const FieldDecl *FD = LambdaCaptureFields[VD]) {
3074 SVal CXXThisVal = state->getSVal(CXXThis);
3075 VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
3080 VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());
3082 SVal V = VInfo->first;
3083 bool IsReference = VInfo->second->isReferenceType();
3089 V = state->getSVal(R);
3094 Bldr.
generateNode(Ex, Pred, state->BindExpr(Ex, LCtx,
V),
nullptr,
3098 if (
const auto *ED = dyn_cast<EnumConstantDecl>(D)) {
3104 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
3106 Bldr.
generateNode(Ex, Pred, state->BindExpr(Ex, LCtx,
V),
nullptr,
3110 if (isa<FieldDecl, IndirectFieldDecl>(D)) {
3115 if (
const auto *BD = dyn_cast<BindingDecl>(D)) {
3116 const auto *DD = cast<DecompositionDecl>(BD->getDecomposedDecl());
3118 SVal Base = state->getLValue(DD, LCtx);
3119 if (DD->getType()->isReferenceType()) {
3121 Base = state->getSVal(R);
3129 if (
const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
3130 const auto *Field = cast<FieldDecl>(ME->getMemberDecl());
3131 V = state->getLValue(Field,
Base);
3134 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {
3135 SVal Idx = state->getSVal(ASE->getIdx(), LCtx);
3140 assert(Idx.
isConstant() &&
"BindingDecl array index is not a constant!");
3142 V = state->getLValue(BD->getType(), Idx,
Base);
3145 else if (
const auto *HV = BD->getHoldingVar()) {
3146 V = state->getLValue(HV, LCtx);
3148 if (HV->getType()->isReferenceType()) {
3150 V = state->getSVal(R);
3155 llvm_unreachable(
"An unknown case of structured binding encountered!");
3159 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3161 V = state->getSVal(R);
3166 Bldr.
generateNode(Ex, Pred, state->BindExpr(Ex, LCtx,
V),
nullptr,
3172 if (
const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
3178 llvm_unreachable(
"Support for this Decl not implemented.");
3193 for (
auto *
Node : CheckerPreStmt) {
3238 if (
const auto *ME = dyn_cast<MemberExpr>(Arr)) {
3239 Expr *MEBase = ME->getBase();
3242 if (
auto CXXSCE = dyn_cast<CXXStaticCastExpr>(MEBase)) {
3243 MEBase = CXXSCE->getSubExpr();
3246 auto ObjDeclExpr = cast<DeclRefExpr>(MEBase);
3247 SVal Obj = state->getLValue(cast<VarDecl>(ObjDeclExpr->getDecl()), LCtx);
3249 Base = state->getLValue(cast<FieldDecl>(ME->getMemberDecl()), Obj);
3264 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arr))
3265 Base = state->getLValue(cast<VarDecl>(DRE->getDecl()), LCtx);
3269 Base = state->getSVal(R);
3300 for (
auto *
Node : CheckerPreStmt) {
3304 if (IsGLValueLike) {
3313 SVal V = state->getLValue(T,
3314 state->getSVal(Idx, LCtx),
3315 state->getSVal(
Base, LCtx));
3318 }
else if (IsVectorType) {
3322 llvm_unreachable(
"Array subscript should be an lValue when not \
3323a vector and not a forbidden lvalue type");
3342 if (isa<VarDecl, EnumConstantDecl>(
Member)) {
3343 for (
const auto I : CheckedSet)
3349 for (
const auto I : CheckedSet) {
3355 if (
const auto *MD = dyn_cast<CXXMethodDecl>(
Member)) {
3356 if (MD->isInstance())
3357 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
3360 state = state->BindExpr(M, LCtx, MDVal);
3368 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,
3375 if (
const auto *SR =
3376 dyn_cast_or_null<SymbolicRegion>(baseExprVal.
getAsRegion())) {
3377 QualType T = SR->getPointeeStaticType();
3382 const auto *field = cast<FieldDecl>(
Member);
3383 SVal L = state->getLValue(field, baseExprVal);
3393 dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
3394 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
3395 llvm_unreachable(
"should always be wrapped in ArrayToPointerDecay");
3399 if (field->getType()->isReferenceType()) {
3401 L = state->getSVal(R);
3406 Bldr.
generateNode(M, I, state->BindExpr(M, LCtx, L),
nullptr,
3430 for (
const auto I : AfterPreSet) {
3435 for (
unsigned SI = 0, Count = AE->
getNumSubExprs(); SI != Count; SI++) {
3437 SVal SubExprVal = State->getSVal(SubExpr, LCtx);
3438 ValuesToInvalidate.push_back(SubExprVal);
3441 State = State->invalidateRegions(ValuesToInvalidate, AE,
3448 State = State->BindExpr(AE, LCtx, ResultVal);
3468 for (
const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
3470 const MemRegion *MR = LocAndVal.first.getAsRegion();
3472 !isa<StackSpaceRegion, StaticGlobalSpaceRegion>(MR->
getMemorySpace())) {
3473 Escaped.push_back(LocAndVal.second);
3478 if (
const auto *VR = dyn_cast<VarRegion>(MR->
getBaseRegion()))
3479 if (VR->hasStackParametersStorage() && VR->getStackFrame()->inTopFrame())
3480 if (
const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3481 if (!RD->hasTrivialDestructor()) {
3482 Escaped.push_back(LocAndVal.second);
3491 SVal StoredVal = State->getSVal(MR);
3492 if (StoredVal != LocAndVal.second)
3495 Escaped.push_back(LocAndVal.second);
3498 if (Escaped.empty())
3501 return escapeValues(State, Escaped, Kind, Call);
3507 std::pair<SVal, SVal> LocAndVal(
Loc, Val);
3518 if (!Invalidated || Invalidated->empty())
3531 for (
const auto I : ExplicitRegions) {
3533 SymbolsDirectlyInvalidated.insert(R->getSymbol());
3537 for (
const auto &sym : *Invalidated) {
3538 if (SymbolsDirectlyInvalidated.count(sym))
3540 SymbolsIndirectlyInvalidated.insert(sym);
3543 if (!SymbolsDirectlyInvalidated.empty())
3548 if (!SymbolsIndirectlyInvalidated.empty())
3569 StoreE, *
this, *PP);
3575 if (!isa<Loc>(location)) {
3580 Bldr.generateNode(L, state, Pred);
3584 for (
const auto PredI : CheckedSet) {
3592 state = state->bindLoc(location.
castAs<
Loc>(),
3593 Val, LC, !atDeclInit);
3596 if (std::optional<loc::MemRegionVal> LocRegVal =
3598 LocReg = LocRegVal->getRegion();
3602 Bldr.generateNode(L, state, PredI);
3615 const Expr *LocationE,
3621 const Expr *StoreE = AssignE ? AssignE : LocationE;
3625 evalLocation(Tmp, AssignE, LocationE, Pred, state, location,
false);
3633 for (
const auto I : Tmp)
3634 evalBind(Dst, StoreE, I, location, Val,
false);
3639 const Expr *BoundEx,
3645 assert(!isa<NonLoc>(location) &&
"location cannot be a NonLoc.");
3650 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location,
true);
3659 for (
const auto I : Tmp) {
3660 state = I->getState();
3667 V = state->getSVal(location.
castAs<
Loc>(), LoadTy);
3670 Bldr.
generateNode(NodeEx, I, state->BindExpr(BoundEx, LCtx,
V), tag,
3677 const Stmt *BoundEx,
3689 BldrTop.takeNodes(Pred);
3702 Bldr.generateNode(NodeEx, Pred, state, &tag);
3706 NodeEx, BoundEx, *
this);
3707 BldrTop.addNodes(Tmp);
3710std::pair<const ProgramPointTag *, const ProgramPointTag*>
3713 eagerlyAssumeBinOpBifurcationTrue(TagProviderName,
3714 "Eagerly Assume True"),
3715 eagerlyAssumeBinOpBifurcationFalse(TagProviderName,
3716 "Eagerly Assume False");
3717 return std::make_pair(&eagerlyAssumeBinOpBifurcationTrue,
3718 &eagerlyAssumeBinOpBifurcationFalse);
3726 for (
const auto Pred : Src) {
3738 if (SEV && SEV->isExpression()) {
3739 const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags =
3743 std::tie(StateTrue, StateFalse) = state->assume(*SEV);
3776 assert(!isa<NonLoc>(
X));
3778 if (std::optional<Loc> LV =
X.getAs<
Loc>())
3803 N->
getState()->getStateManager().getOwningEngine()).getBugReporter();
3805 const auto EQClasses =
3808 for (
const auto &EQ : EQClasses) {
3809 for (
const auto &I : EQ.getReports()) {
3810 const auto *PR = dyn_cast<PathSensitiveBugReport>(I.get());
3828 llvm::function_ref<
void(
const ExplodedNode *)> PreCallback,
3829 llvm::function_ref<
void(
const ExplodedNode *)> PostCallback,
3851 llvm::raw_string_ostream Out(Buf);
3853 const bool IsDot =
true;
3854 const unsigned int Space = 1;
3857 Out <<
"{ \"state_id\": " << State->getID()
3860 Indent(Out, Space, IsDot) <<
"\"program_points\": [\\l";
3863 traverseHiddenNodes(
3866 Indent(Out, Space + 1, IsDot) <<
"{ ";
3868 Out <<
", \"tag\": ";
3870 Out <<
'\"' << Tag->getTagDescription() <<
'\"';
3873 Out <<
", \"node_id\": " << OtherNode->
getID() <<
3874 ", \"is_sink\": " << OtherNode->
isSink() <<
3875 ", \"has_report\": " << nodeHasBugReport(OtherNode) <<
" }";
3882 Indent(Out, Space, IsDot) <<
"],\\l";
3895 llvm::DisplayGraph(
Filename,
false, llvm::GraphProgram::DOT);
3900 llvm::DisplayGraph(
Filename,
false, llvm::GraphProgram::DOT);
3905 std::vector<const ExplodedNode *> Src;
3911 dyn_cast<PathSensitiveBugReport>(EI->getReports()[0].get());
3914 const auto *N =
const_cast<ExplodedNode *
>(R->getErrorNode());
3920 return llvm::WriteGraph(&G,
"ExprEngine",
false,
3927 std::unique_ptr<ExplodedGraph> TrimmedG(G.
trim(
Nodes));
3929 if (!TrimmedG.get()) {
3930 llvm::errs() <<
"warning: Trimmed ExplodedGraph is empty.\n";
3934 return llvm::WriteGraph(TrimmedG.get(),
"TrimmedExprEngine",
3936 "Trimmed Exploded Graph",
3941 static int index = 0;
3945void ExprEngine::anchor() { }
Defines the clang::ASTContext interface.
BoundNodesTreeBuilder Nodes
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static CompilationDatabasePluginRegistry::Add< FixedCompilationDatabasePlugin > X("fixed-compilation-database", "Reads plain-text flags file")
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
static const Stmt * getRightmostLeaf(const Stmt *Condition)
std::pair< const ObjCForCollectionStmt *, const LocationContext * > ObjCForLctxPair
static SVal RecoverCastedSymbol(ProgramStateRef state, const Stmt *Condition, const LocationContext *LCtx, ASTContext &Ctx)
RecoverCastedSymbol - A helper function for ProcessBranch that is used to try to recover some path-se...
static void printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
static void printIndicesOfElementsToConstructJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
static void printStateTraitWithLocationContextJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, 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 printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S, const ExplodedNode *Pred, const LocationContext *LC)
static const Stmt * ResolveCondition(const Stmt *Condition, const CFGBlock *B)
REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction, ObjectsUnderConstructionMap) typedef llvm REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct, IndexOfElementToConstructMap) typedef llvm typedef llvm::ImmutableMap< const LocationContext *, unsigned > PendingArrayDestructionMap
static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
llvm::ImmutableMap< ConstructedObjectKey, SVal > ObjectsUnderConstructionMap
static std::optional< std::pair< ProgramStateRef, ProgramStateRef > > assumeCondition(const Stmt *Condition, ExplodedNode *N)
Split the state on whether there are any more iterations left for this loop.
STATISTIC(NumRemoveDeadBindings, "The # of times RemoveDeadBindings is called")
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
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 the SourceManager interface.
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 ...
SourceManager & getSourceManager()
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
const clang::PrintingPolicy & getPrintingPolicy() const
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
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.
unsigned NoRetryExhausted
Do not re-analyze paths leading to exhausted nodes with a different strategy.
unsigned maxBlockVisitOnPath
The maximum number of times the analyzer visits a block.
AnalysisPurgeMode AnalysisPurgeOpt
Represents a loop initializing the elements of an array.
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Expr * getSubExpr() const
Get the initializer to use for each array element.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
static unsigned getNumSubExprs(AtomicOp Op)
Determine the number of arguments the specified atomic builtin should have.
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
const VarDecl * getVarDecl() const
const Stmt * getTriggerStmt() const
Represents C++ object destructor implicitly generated for base object in destructor.
const CXXBaseSpecifier * getBaseSpecifier() const
Represents a single basic block in a source-level CFG.
reverse_iterator rbegin()
CFGTerminator getTerminator() const
Stmt * getTerminatorStmt()
Represents C++ object destructor generated from a call to delete.
const CXXDeleteExpr * getDeleteExpr() const
Represents a top-level expression in a basic block.
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
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.
CXXCtorInitializer * getInitializer() 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
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
FieldDecl * getAnyMember() const
IndirectFieldDecl * getIndirectMember() const
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.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
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, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
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.
Represents the declaration of a label.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const LocationContext * getParent() const
It might return null.
const StackFrameContext * getStackFrame() const
virtual bool inTopFrame() const
void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const LocationContext *)> printMoreInfoPerContext=[](const LocationContext *) {}) const
Prints out the call stack in json format.
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.
void printJson(llvm::raw_ostream &Out, const char *NL="\n") const
@ PreStmtPurgeDeadSymbolsKind
@ PostStmtPurgeDeadSymbolsKind
const StackFrameContext * getStackFrame() const
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
const LocationContext * getLocationContext() const
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.
SplitQualType split() const
Divides a QualType into its unqualified type and a set of local qualifiers.
bool isCForbiddenLValueType() const
Determine whether expressions of the given type are forbidden from being lvalues in C.
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 (based on CallEvent).
unsigned getIndex() const
const Stmt * getCallSite() const
const CFGBlock * getCallSiteBlock() const
bool inTopFrame() const override
const Stmt * getStmt() const
Stmt - This represents one statement.
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.
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isReferenceType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isVectorType() const
const T * getAs() const
Member-template getAs<specific type>'.
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.
const LangOptions & getLangOpts() const
ASTContext & getASTContext() override
AnalyzerOptions & options
BranchNodeBuilder is responsible for constructing the nodes corresponding to the two branches of the ...
void markInfeasible(bool branch)
ExplodedNode * generateNode(ProgramStateRef State, bool branch, ExplodedNode *Pred)
bool isFeasible(bool branch)
BugReporter is a utility class for generating PathDiagnostics for analysis.
EQClasses_iterator EQClasses_begin()
EQClasses_iterator EQClasses_end()
llvm::FoldingSet< BugReportEquivClass >::iterator EQClasses_iterator
Iterator over the set of BugReports tracked by the BugReporter.
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.
void runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, ExprEngine &Eng, const ProgramPoint &PP)
Run checkers for binding of a value to a location.
void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, const ReturnStmt *RS)
Run checkers on end of function.
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 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.
ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call)
Run checkers for region changes.
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 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.
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 addAbortedBlock(const ExplodedNode *node, const CFGBlock *block)
Inform the CoreEngine that a basic block was aborted because it could not be completely analyzed.
void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx)
Enqueue a single node created as a result of statement processing.
void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS)
enqueue the nodes corresponding to the end of function onto the end of path / work list.
void enqueue(ExplodedNodeSet &Set)
Enqueue the given set of nodes onto the work list.
std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy * > Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const
Creates a trimmed version of the graph that only contains paths leading to the given nodes.
void enableNodeReclamation(unsigned Interval)
Enable tracking of recently allocated nodes for potential reclamation when calling reclaimRecentlyAll...
void reclaimRecentlyAllocatedNodes()
Reclaim "uninteresting" nodes created since the last time this method was called.
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 ...
roots_iterator roots_begin()
void insert(const ExplodedNodeSet &S)
void Add(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 StackFrameContext * getStackFrame() const
const LocationContext * getLocationContext() const
unsigned succ_size() const
void processEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, const ReturnStmt *RS=nullptr)
Called by CoreEngine.
void VisitBinaryOperator(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBinaryOperator - Transfer function logic for binary operators.
ProgramStateManager & getStateManager()
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 VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGuardedExpr - Transfer function logic for ?, __builtin_choose.
void processBeginOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L)
Called by CoreEngine.
void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCast - Transfer function logic for all casts (implicit and explicit).
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const LocationContext *LC, const Stmt *DiagnosticStmt=nullptr, ProgramPoint::Kind K=ProgramPoint::PreStmtPurgeDeadSymbolsKind)
Run the analyzer's garbage collection - remove dead symbols and bindings from the state.
void VisitLogicalExpr(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitLogicalExpr - Transfer function logic for '&&', '||'.
void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst, EvalCallOptions &Options)
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)
ProgramStateRef processRegionChange(ProgramStateRef state, const MemRegion *MR, const LocationContext *LCtx)
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.
ProgramStateRef getInitialState(const LocationContext *InitLoc)
getInitialState - Return the initial state used for the root vertex in the ExplodedGraph.
void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for computing the lvalue of an Objective-C ivar.
static bool hasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
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.
static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const LocationContext *LC)
By looking at a certain item that may be potentially part of an object's ConstructionContext,...
std::string DumpGraph(bool trim=false, StringRef Filename="")
Dump graph to the specified filename.
void printJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, const char *NL, unsigned int Space, bool IsDot) const
printJson - Called by ProgramStateManager to print checker-specific data.
InliningModes
The modes of inlining, which override the default analysis-wide settings.
ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, ArrayRef< std::pair< SVal, SVal > > LocAndVals, const LocationContext *LCtx, PointerEscapeKind Kind, const CallEvent *Call)
Call PointerEscape callback when a value escapes as a result of bind.
const LocationContext * getRootLocationContext() const
static ProgramStateRef removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
ProgramStateRef processAssume(ProgramStateRef state, SVal cond, bool assumption)
evalAssume - Callback function invoked by the ConstraintManager when making assumptions about state v...
static std::optional< unsigned > getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives which element is being constructed in a non-POD type array.
void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBlockExpr - Transfer function logic for BlockExprs.
void ProcessBaseDtor(const CFGBaseDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCall - Transfer function for function calls.
ASTContext & getContext() const
getContext - Return the ASTContext associated with this analysis.
StoreManager & getStoreManager()
void 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.
CFGBlock::ConstCFGElementRef getCFGElementRef() const
void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGCCAsmStmt - Transfer function logic for inline asm.
void processCFGBlockEntrance(const BlockEdge &L, NodeBuilderWithSinks &nodeBuilder, ExplodedNode *Pred)
Called by CoreEngine when processing the entrance of a CFGBlock.
void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void processBranch(const Stmt *Condition, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
ProcessBranch - Called by CoreEngine.
ProgramStateRef processRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call)
processRegionChanges - Called by ProgramStateManager whenever a change is made to the store.
void ProcessStmt(const Stmt *S, ExplodedNode *Pred)
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.
static std::optional< unsigned > getPendingArrayDestruction(ProgramStateRef State, const LocationContext *LCtx)
Retreives which element is being destructed in a non-POD type array.
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.
void processCFGElement(const CFGElement E, ExplodedNode *Pred, unsigned StmtIdx, NodeBuilderContext *Ctx)
processCFGElement - Called by CoreEngine.
void processStaticInitializer(const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
void ProcessLoopExit(const Stmt *S, ExplodedNode *Pred)
void processSwitch(SwitchNodeBuilder &builder)
ProcessSwitch - Called by CoreEngine.
void processEndWorklist()
Called by CoreEngine when the analysis worklist has terminated.
CheckerManager & getCheckerManager() const
void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAtomicExpr - Transfer function for builtin atomic expressions.
void ProcessMemberDtor(const CFGMemberDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitMemberExpr - Transfer function for member expressions.
void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
ConstraintManager & getConstraintManager()
void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, NodeBuilderContext &BldCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex)
evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic expressions of ...
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 removeDeadOnEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Remove dead bindings/symbols before exiting a function.
static std::pair< const ProgramPointTag *, const ProgramPointTag * > geteagerlyAssumeBinOpBifurcationTags()
void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Visit - Transfer function logic for all statements.
AnalysisManager & getAnalysisManager()
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 VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, ExplodedNodeSet &PreVisit, ExplodedNodeSet &Dst)
void processIndirectGoto(IndirectGotoNodeBuilder &builder)
processIndirectGoto - Called by CoreEngine.
const NodeBuilderContext & getBuilderContext()
static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives the size of the array in the pending ArrayInitLoopExpr.
void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred)
void markReachedMaxBlockCount(const Decl *D)
const Expr * getTarget() const
const LocationContext * getLocationContext() const
ProgramStateRef getState() const
ExplodedNode * generateNode(const iterator &I, ProgramStateRef State, bool isSink=false)
static bool isLocType(QualType T)
const CXXTempObjectRegion * getCXXStaticTempObjectRegion(const Expr *Ex)
Create a CXXTempObjectRegion for temporaries which are lifetime-extended by static references.
const CXXTempObjectRegion * getCXXTempObjectRegion(Expr const *Ex, LocationContext const *LC)
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
This node builder keeps track of the generated sink nodes.
ExplodedNode * generateNode(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
This is the simplest builder which generates nodes in the ExplodedGraph.
ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)
Generates a node in the ExplodedGraph.
void takeNodes(const ExplodedNodeSet &S)
ExplodedNode * generateSink(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)
Generates a sink in the ExplodedGraph.
void addNodes(const ExplodedNodeSet &S)
const NodeBuilderContext & getContext()
While alive, includes the current analysis stack in a crash trace.
ProgramStateRef removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, const StackFrameContext *LCtx, SymbolReaper &SymReaper)
bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) const
bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) const
ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState)
MemRegionManager & getRegionManager()
ProgramStateRef getInitialState(const LocationContext *InitLoc)
StoreManager & getStoreManager()
Information about invalidation for a particular region/symbol.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
DefinedSVal getFunctionPointer(const FunctionDecl *func)
NonLoc makeIntValWithWidth(QualType ptrType, uint64_t integer)
NonLoc makeArrayIndex(uint64_t idx)
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
QualType getConditionType() const
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the 'this' object reference.
std::optional< SVal > getConstantVal(const Expr *E)
Returns the value of E, if it can be determined in a non-path-sensitive manner.
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 llvm::APSInt * getAsInteger() const
If this SVal is loc::ConcreteInt or nonloc::ConcreteInt, return a pointer to APSInt which is held in ...
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
This builder class is useful for generating nodes that resulted from visiting a statement.
ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
ExplodedNode * generateSink(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
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.
ProgramStateRef getState() const
const Expr * getCondition() const
ExplodedNode * generateDefaultCaseNode(ProgramStateRef State, bool isSink=false)
ExplodedNode * generateCaseStmtNode(const iterator &I, ProgramStateRef State)
const LocationContext * getLocationContext() const
const SwitchStmt * getSwitch() const
A class responsible for cleaning up unused symbols.
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
SymbolicRegion - A special, "non-concrete" region.
TypedValueRegion - An abstract class representing regions having a typed value.
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)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State)
Updates the given ProgramState.
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, const LocationContext *LCtx, unsigned BlockCount, const Stmt *LoopStmt)
Get the states that result from widening the loop.
bool isUnrolledState(ProgramStateRef State)
Returns if the given State indicates that is inside a completely unrolled loop.
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)
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ C
Languages that the frontend can parse and compile.
StorageDuration
The storage duration for an object (per C++ [basic.stc]).
@ SD_Thread
Thread storage duration.
@ SD_Static
Static storage duration.
@ Result
The result type of a method or function.
Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)
YAML serialization mapping.
Describes how types, statements, expressions, and declarations should be printed.
An adjustment to be made to the temporary created when emitting a reference binding,...
@ DerivedToBaseAdjustment
@ MemberPointerAdjustment
Hints for figuring out of 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...
const CFGBlock * getBlock() const
Return the CFGBlock associated with this builder.
unsigned blockCount() const
Returns the number of times the current basic block has been visited on the exploded graph path.
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)