clang: lib/StaticAnalyzer/Core/ExprEngine.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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/TimeProfiler.h"
76#include "llvm/Support/raw_ostream.h"
77#include
78#include
79#include
80#include
81#include
82#include
83#include
84#include
85
86using namespace clang;
87using namespace ento;
88
89#define DEBUG_TYPE "ExprEngine"
90
92 "The # of times RemoveDeadBindings is called");
94 NumMaxBlockCountReached,
95 "The # of aborted paths due to reaching the maximum block count in "
96 "a top level function");
98 NumMaxBlockCountReachedInInlined,
99 "The # of aborted paths due to reaching the maximum block count in "
100 "an inlined function");
102 "The # of times we re-evaluated a call without inlining");
103
104
105
106
107
108namespace {
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123class ConstructedObjectKey {
124 using ConstructedObjectKeyImpl =
125 std::pair<ConstructionContextItem, const LocationContext *>;
126 const ConstructedObjectKeyImpl Impl;
127
128public:
131 : Impl(Item, LC) {}
132
133 const ConstructionContextItem &getItem() const { return Impl.first; }
134 const LocationContext *getLocationContext() const { return Impl.second; }
135
136 ASTContext &getASTContext() const {
137 return getLocationContext()->getDecl()->getASTContext();
138 }
139
140 void printJson(llvm::raw_ostream &Out, PrinterHelper *Helper,
141 PrintingPolicy &PP) const {
142 const Stmt *S = getItem().getStmtOrNull();
143 const CXXCtorInitializer *I = nullptr;
144 if (!S)
145 I = getItem().getCXXCtorInitializer();
146
147 if (S)
148 Out << "\"stmt_id\": " << S->getID(getASTContext());
149 else
150 Out << "\"init_id\": " << I->getID(getASTContext());
151
152
153 Out << ", \"kind\": \"" << getItem().getKindAsString()
154 << "\", \"argument_index\": ";
155
157 Out << getItem().getIndex();
158 else
159 Out << "null";
160
161
162 Out << ", \"pretty\": ";
163
164 if (S) {
165 S->printJson(Out, Helper, PP, true);
166 } else {
168 }
169 }
170
171 void Profile(llvm::FoldingSetNodeID &ID) const {
172 ID.Add(Impl.first);
173 ID.AddPointer(Impl.second);
174 }
175
176 bool operator==(const ConstructedObjectKey &RHS) const {
177 return Impl == RHS.Impl;
178 }
179
180 bool operator<(const ConstructedObjectKey &RHS) const {
181 return Impl < RHS.Impl;
182 }
183};
184}
185
186typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
190
191
192
193
194
195
196
197typedef llvm::ImmutableMap<
198 std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>
199 IndexOfElementToConstructMap;
201 IndexOfElementToConstructMap)
202
203
204
205
206typedef llvm::ImmutableMap<
207 std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>
208 PendingInitLoopMap;
210
211typedef llvm::ImmutableMap<const LocationContext *, unsigned>
215
216
217
218
219
220static const char* TagProviderName = "ExprEngine";
221
225 : CTU(CTU), IsCTUEnabled(mgr.getAnalyzerOptions().IsNaiveCTUEnabled),
227 Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.getGraph()),
228 StateMgr(getContext(), mgr.getStoreManagerCreator(),
229 mgr.getConstraintManagerCreator(), G.getAllocator(), this),
231 svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
232 BR(mgr, *this), VisitedCallees(VisitedCalleesIn),
233 HowToInline(HowToInlineIn) {
234 unsigned TrimInterval = mgr.options.GraphTrimInterval;
235 if (TrimInterval != 0) {
236
237 G.enableNodeReclamation(TrimInterval);
238 }
239}
240
241
242
243
244
246 ProgramStateRef state = StateMgr.getInitialState(InitLoc);
248
249
250
251
252 do {
253 if (const auto *FD = dyn_cast(D)) {
254
255
257 if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))
258 break;
259
260 const ParmVarDecl *PD = FD->getParamDecl(0);
262 const auto *BT = dyn_cast(T);
263 if (!BT || !BT->isInteger())
264 break;
265
266 const MemRegion *R = state->getRegion(PD, InitLoc);
267 if (!R)
268 break;
269
271 SVal Constraint_untested = evalBinOp(state, BO_GT, V,
272 svalBuilder.makeZeroVal(T),
273 svalBuilder.getConditionType());
274
275 std::optional Constraint =
277
278 if (!Constraint)
279 break;
280
281 if (ProgramStateRef newState = state->assume(*Constraint, true))
282 state = newState;
283 }
284 break;
285 }
286 while (false);
287
288 if (const auto *MD = dyn_cast(D)) {
289
290
292 const MemRegion *R = state->getRegion(SelfD, InitLoc);
294
295 if (std::optional LV = V.getAs<Loc>()) {
296
297 state = state->assume(*LV, true);
298 assert(state && "'self' cannot be null");
299 }
300 }
301
302 if (const auto *MD = dyn_cast(D)) {
303 if (MD->isImplicitObjectMemberFunction()) {
304
305
306
308 if (SFC->getParent() == nullptr) {
310 SVal V = state->getSVal(L);
311 if (std::optional LV = V.getAs<Loc>()) {
312 state = state->assume(*LV, true);
313 assert(state && "'this' cannot be null");
314 }
315 }
316 }
317 }
318
319 return state;
320}
321
322ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
325 const SubRegion **OutRegionWithAdjustments) {
326
327
328
329
330
331 SVal InitValWithAdjustments = State->getSVal(InitWithAdjustments, LC);
333
334
335 if ((InitValWithAdjustments)) {
336 if (OutRegionWithAdjustments)
337 *OutRegionWithAdjustments = nullptr;
338 return State;
339 }
340 Result = InitWithAdjustments;
341 } else {
342
343
344 assert((InitValWithAdjustments) ||
346 Result->getType()->isMemberPointerType());
347 }
348
349 ProgramStateManager &StateMgr = State->getStateManager();
350 MemRegionManager &MRMgr = StateMgr.getRegionManager();
351 StoreManager &StoreMgr = StateMgr.getStoreManager();
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374 SmallVector<const Expr *, 2> CommaLHSs;
375 SmallVector<SubobjectAdjustment, 2> Adjustments;
376
378 CommaLHSs, Adjustments);
379
380
381
382
383
384
385 const TypedValueRegion *TR = nullptr;
386 if (const auto *MT = dyn_cast(Result)) {
388 State = finishObjectConstruction(State, MT, LC);
389 State = State->BindExpr(Result, LC, *V);
390 return State;
391 } else if (const ValueDecl *VD = MT->getExtendingDecl()) {
394
395
397 TR = MRMgr.getCXXStaticLifetimeExtendedObjectRegion(Init, VD);
398 } else {
399 TR = MRMgr.getCXXLifetimeExtendedObjectRegion(Init, VD, LC);
400 }
401 } else {
403 TR = MRMgr.getCXXTempObjectRegion(Init, LC);
404 }
405 } else {
406 TR = MRMgr.getCXXTempObjectRegion(Init, LC);
407 }
408
409 SVal Reg = loc::MemRegionVal(TR);
410 SVal BaseReg = Reg;
411
412
413 for (const SubobjectAdjustment &Adj : llvm::reverse(Adjustments)) {
414 switch (Adj.Kind) {
416 Reg = StoreMgr.evalDerivedToBase(Reg, Adj.DerivedToBase.BasePath);
417 break;
420 break;
422
424 currBldrCtx->blockCount(), LC, true,
425 nullptr, nullptr, nullptr);
426 return State;
427 }
428 }
429
430
431
432
433
434
435
436
437
438 SVal InitVal = State->getSVal(Init, LC);
442 State = State->bindLoc(BaseReg.castAs(), InitVal, LC, false);
443
444
445
446 if (InitValWithAdjustments.isUnknown()) {
447
448
451 currBldrCtx->blockCount());
452 }
453 State =
454 State->bindLoc(Reg.castAs(), InitValWithAdjustments, LC, false);
455 } else {
456 State = State->bindLoc(BaseReg.castAs(), InitVal, LC, false);
457 }
458
459
460
461
462 if (Result->isGLValue()) {
463 State = State->BindExpr(Result, LC, Reg);
464 } else {
465 State = State->BindExpr(Result, LC, InitValWithAdjustments);
466 }
467
468
470
471 if (OutRegionWithAdjustments)
473 return State;
474}
475
478 const LocationContext *LCtx, unsigned Idx) {
479 auto Key = std::make_pair(E, LCtx->getStackFrame());
480
481 assert(!State->contains(Key) || Idx > 0);
482
483 return State->set(Key, Idx);
484}
485
486std::optional
489 const unsigned *V = State->get({E, LCtx->getStackFrame()});
490 return V ? std::make_optional(*V) : std::nullopt;
491}
492
496 auto Key = std::make_pair(E, LCtx->getStackFrame());
497
498 assert(E && State->contains(Key));
499 return State->remove(Key);
500}
501
505 unsigned Size) {
506 auto Key = std::make_pair(E, LCtx->getStackFrame());
507
508 assert(!State->contains(Key) && Size > 0);
509
510 return State->set(Key, Size);
511}
512
513std::optional
517 const unsigned *V =
518 State->get({E, LCtx->getStackFrame()});
519 return V ? std::make_optional(*V) : std::nullopt;
520}
521
523ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State,
526 auto Key = std::make_pair(E, LCtx->getStackFrame());
527
528 assert(E && State->contains(Key));
529 return State->remove(Key);
530}
531
532std::optional
535 assert(LCtx && "LocationContext shouldn't be null!");
536
537 const unsigned *V =
538 State->get(LCtx->getStackFrame());
539 return V ? std::make_optional(*V) : std::nullopt;
540}
541
544 assert(LCtx && "LocationContext shouldn't be null!");
545
547
548 return State->set(Key, Idx);
549}
550
552ExprEngine::removePendingArrayDestruction(ProgramStateRef State,
554 assert(LCtx && "LocationContext shouldn't be null!");
555
557
558 assert(LCtx && State->contains(Key));
559 return State->remove(Key);
560}
561
563ExprEngine::addObjectUnderConstruction(ProgramStateRef State,
566 ConstructedObjectKey Key(Item, LC->getStackFrame());
567
569
570 if (auto DS = dyn_cast_or_null(Item.getStmtOrNull())) {
571 if (auto VD = dyn_cast_or_null(DS->getSingleDecl()))
572 Init = VD->getInit();
573 }
574
575 if (auto LE = dyn_cast_or_null(Item.getStmtOrNull()))
576 Init = *(LE->capture_init_begin() + Item.getIndex());
577
580
581
582
583
584 if (const auto *AILE = dyn_cast_or_null(Init))
586
587
588
589
590
591
592
593 assert((!State->get(Key) ||
594 Key.getItem().getKind() ==
596 State->contains(
597 {dyn_cast_or_null(Init), LC})) &&
598 "The object is already marked as `UnderConstruction`, when it's not "
599 "supposed to!");
600 return State->set(Key, V);
601}
602
603std::optional
607 ConstructedObjectKey Key(Item, LC->getStackFrame());
608 const SVal *V = State->get(Key);
609 return V ? std::make_optional(*V) : std::nullopt;
610}
611
613ExprEngine::finishObjectConstruction(ProgramStateRef State,
616 ConstructedObjectKey Key(Item, LC->getStackFrame());
617 assert(State->contains(Key));
618 return State->remove(Key);
619}
620
624 ConstructedObjectKey Key({BTE, true}, LC);
625
626
627 return State->set(Key, UnknownVal());
628}
629
631ExprEngine::cleanupElidedDestructor(ProgramStateRef State,
632 const CXXBindTemporaryExpr *BTE,
633 const LocationContext *LC) {
634 ConstructedObjectKey Key({BTE, true}, LC);
635 assert(State->contains(Key));
636 return State->remove(Key);
637}
638
639bool ExprEngine::isDestructorElided(ProgramStateRef State,
640 const CXXBindTemporaryExpr *BTE,
641 const LocationContext *LC) {
642 ConstructedObjectKey Key({BTE, true}, LC);
643 return State->contains(Key);
644}
645
646bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
647 const LocationContext *FromLC,
648 const LocationContext *ToLC) {
649 const LocationContext *LC = FromLC;
650 while (LC != ToLC) {
651 assert(LC && "ToLC must be a parent of FromLC!");
652 for (auto I : State->get())
653 if (I.first.getLocationContext() == LC)
654 return false;
655
657 }
658 return true;
659}
660
661
662
663
664
665
666
667
669 SVal cond, bool assumption) {
671}
672
681 Explicits, Regions,
683}
684
685static void
688 unsigned int Space = 0, bool IsDot = false) {
691
692 ++Space;
693 bool HasItem = false;
694
695
696 const ConstructedObjectKey *LastKey = nullptr;
697 for (const auto &I : State->get()) {
698 const ConstructedObjectKey &Key = I.first;
699 if (Key.getLocationContext() != LCtx)
700 continue;
701
702 if (!HasItem) {
703 Out << '[' << NL;
704 HasItem = true;
705 }
706
707 LastKey = &Key;
708 }
709
710 for (const auto &I : State->get()) {
711 const ConstructedObjectKey &Key = I.first;
713 if (Key.getLocationContext() != LCtx)
714 continue;
715
716 Indent(Out, Space, IsDot) << "{ ";
717 Key.printJson(Out, nullptr, PP);
718 Out << ", \"value\": \"" << Value << "\" }";
719
720 if (&Key != LastKey)
721 Out << ',';
722 Out << NL;
723 }
724
725 if (HasItem)
726 Indent(Out, --Space, IsDot) << ']';
727 else {
728 Out << "null ";
729 }
730}
731
734 const LocationContext *LCtx, unsigned int Space = 0, bool IsDot = false) {
735 using KeyT = std::pair<const Expr *, const LocationContext *>;
736
739
740 ++Space;
741 bool HasItem = false;
742
743
744 KeyT LastKey;
745 for (const auto &I : State->get()) {
746 const KeyT &Key = I.first;
747 if (Key.second != LCtx)
748 continue;
749
750 if (!HasItem) {
751 Out << '[' << NL;
752 HasItem = true;
753 }
754
755 LastKey = Key;
756 }
757
758 for (const auto &I : State->get()) {
759 const KeyT &Key = I.first;
760 unsigned Value = I.second;
761 if (Key.second != LCtx)
762 continue;
763
764 Indent(Out, Space, IsDot) << "{ ";
765
766
767 const Expr *E = Key.first;
768 Out << "\"stmt_id\": " << E->getID(Context);
769
770
771 Out << ", \"kind\": null";
772
773
774 Out << ", \"pretty\": ";
778 Out << "'\"";
779
780 Out << ", \"value\": \"Current index: " << Value - 1 << "\" }";
781
782 if (Key != LastKey)
783 Out << ',';
784 Out << NL;
785 }
786
787 if (HasItem)
788 Indent(Out, --Space, IsDot) << ']';
789 else {
790 Out << "null ";
791 }
792}
793
795 const char *NL,
797 unsigned int Space = 0,
798 bool IsDot = false) {
799 using KeyT = std::pair<const CXXConstructExpr *, const LocationContext *>;
800
803
804 ++Space;
805 bool HasItem = false;
806
807
808 KeyT LastKey;
809 for (const auto &I : State->get()) {
810 const KeyT &Key = I.first;
811 if (Key.second != LCtx)
812 continue;
813
814 if (!HasItem) {
815 Out << '[' << NL;
816 HasItem = true;
817 }
818
819 LastKey = Key;
820 }
821
822 for (const auto &I : State->get()) {
823 const KeyT &Key = I.first;
824 unsigned Value = I.second;
825 if (Key.second != LCtx)
826 continue;
827
828 Indent(Out, Space, IsDot) << "{ ";
829
831 Out << "\"stmt_id\": " << E->getID(Context);
832
833 Out << ", \"kind\": null";
834 Out << ", \"pretty\": ";
838 Out << "'\"";
839
840 Out << ", \"value\": \"Flattened size: " << Value << "\"}";
841
842 if (Key != LastKey)
843 Out << ',';
844 Out << NL;
845 }
846
847 if (HasItem)
848 Indent(Out, --Space, IsDot) << ']';
849 else {
850 Out << "null ";
851 }
852}
853
854static void
857 unsigned int Space = 0, bool IsDot = false) {
859
860 ++Space;
861 bool HasItem = false;
862
863
864 KeyT LastKey = nullptr;
865 for (const auto &I : State->get()) {
866 const KeyT &Key = I.first;
867 if (Key != LCtx)
868 continue;
869
870 if (!HasItem) {
871 Out << '[' << NL;
872 HasItem = true;
873 }
874
875 LastKey = Key;
876 }
877
878 for (const auto &I : State->get()) {
879 const KeyT &Key = I.first;
880 if (Key != LCtx)
881 continue;
882
883 Indent(Out, Space, IsDot) << "{ ";
884
885 Out << "\"stmt_id\": null";
886 Out << ", \"kind\": null";
887 Out << ", \"pretty\": \"Current index: \"";
888 Out << ", \"value\": \"" << I.second << "\" }";
889
890 if (Key != LastKey)
891 Out << ',';
892 Out << NL;
893 }
894
895 if (HasItem)
896 Indent(Out, --Space, IsDot) << ']';
897 else {
898 Out << "null ";
899 }
900}
901
902
903
904
905
906
907
908
909
910template <typename Trait, typename Printer, typename... Args>
913 const char *NL, unsigned int Space, bool IsDot,
914 const char *jsonPropertyName, Printer printer, Args &&...args) {
915
916 using RequiredType =
919
920
921
922 static_assert(std::is_function_v<std::remove_pointer_t>,
923 "Printer is not a function!");
924 static_assert(std::is_convertible_v<Printer, RequiredType>,
925 "Printer doesn't have the required type!");
926
927 if (LCtx && !State->get().isEmpty()) {
928 Indent(Out, Space, IsDot) << '\"' << jsonPropertyName << "\": ";
929 ++Space;
930 Out << '[' << NL;
932 printer(Out, State, NL, LC, Space, IsDot, std::forward(args)...);
933 });
934
935 --Space;
936 Indent(Out, Space, IsDot) << "]," << NL;
937 }
938}
939
942 unsigned int Space, bool IsDot) const {
943
945 Out, State, LCtx, NL, Space, IsDot, "constructing_objects",
948 Out, State, LCtx, NL, Space, IsDot, "index_of_element",
951 Out, State, LCtx, NL, Space, IsDot, "pending_init_loops",
954 Out, State, LCtx, NL, Space, IsDot, "pending_destructors",
956
958 IsDot);
959}
960
966
969 currStmtIdx = StmtIdx;
970 currBldrCtx = Ctx;
971
977 return;
980 return;
983 Pred);
984 return;
991 return;
994 return;
999 return;
1000 }
1001}
1002
1004 const Stmt *S,
1007
1009 return false;
1010
1011
1013 return true;
1014
1015
1017 return true;
1018
1019
1021 return true;
1022
1023
1024
1027}
1028
1030 const Stmt *ReferenceStmt,
1032 const Stmt *DiagnosticStmt,
1034 llvm::TimeTraceScope TimeScope("ExprEngine::removeDead");
1036 ReferenceStmt == nullptr || isa(ReferenceStmt))
1037 && "PostStmt is not generally supported by the SymbolReaper yet");
1038 assert(LC && "Must pass the current (or expiring) LocationContext");
1039
1040 if (!DiagnosticStmt) {
1041 DiagnosticStmt = ReferenceStmt;
1042 assert(DiagnosticStmt && "Required for clearing a LocationContext");
1043 }
1044
1045 NumRemoveDeadBindings++;
1047
1048
1049
1050
1051 if (!ReferenceStmt) {
1053 "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");
1055 }
1056
1059
1060 for (auto I : CleanedState->get()) {
1061 if (SymbolRef Sym = I.second.getAsSymbol())
1063 if (const MemRegion *MR = I.second.getAsRegion())
1065 }
1066
1068
1069
1070
1071
1072 CleanedState = StateMgr.removeDeadBindingsFromEnvironmentAndStore(
1073 CleanedState, SFC, SymReaper);
1074
1075
1076
1077
1080 DiagnosticStmt, *this, K);
1081
1082
1083
1084
1086
1087
1088
1089
1091 for (const auto I : CheckedSet) {
1093
1094
1095 CheckerState =
1097
1098 assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&
1099 "Checkers are not allowed to modify the Environment as a part of "
1100 "checkDeadSymbols processing.");
1101 assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&
1102 "Checkers are not allowed to modify the Store as a part of "
1103 "checkDeadSymbols processing.");
1104
1105
1106
1108 StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
1110 }
1111}
1112
1115 return &cleanupTag;
1116}
1117
1119
1120 G.reclaimRecentlyAllocatedNodes();
1121
1124 "Error evaluating statement");
1125
1126
1130 removeDead(Pred, CleanedStates, currStmt,
1132 } else
1133 CleanedStates.Add(Pred);
1134
1135
1137 for (const auto I : CleanedStates) {
1139
1140 Visit(currStmt, I, DstI);
1142 }
1143
1144
1145 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1146}
1147
1151 "Error evaluating end of the loop");
1153 Dst.Add(Pred);
1154 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1156
1157 if(AMgr.options.ShouldUnrollLoops)
1159
1162
1163 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1164}
1165
1171
1174 "Error evaluating initializer");
1175
1176
1179
1181 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));
1182
1184 SVal FieldLoc;
1185
1186
1188
1189
1191
1192
1193 State = finishObjectConstruction(State, BMI, LC);
1194 NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
1195 PostStore PS(Init, LC, nullptr, nullptr);
1197 } else {
1202 } else {
1204 FieldLoc = State->getLValue(BMI->getMember(), thisVal);
1205 }
1206
1207 SVal InitVal;
1208 if (Init->getType()->isArrayType()) {
1209
1210
1212 while ((ASE = dyn_cast(Init)))
1214
1215 InitVal = State->getSVal(Init, stackFrame);
1216
1217
1220 InitVal =
1222 Field->getType(), currBldrCtx->blockCount());
1223 }
1224 } else {
1225 InitVal = State->getSVal(BMI->getInit(), stackFrame);
1226 }
1227
1229 evalBind(Tmp, Init, Pred, FieldLoc, InitVal, true, &PP);
1230 }
1232
1233
1234
1237 SVal InitVal = State->getSVal(Init, stackFrame);
1238 evalBind(Tmp, Init, Pred, BaseLoc, InitVal, true);
1239 } else {
1242
1243 }
1244
1245
1246
1249 NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
1250 for (const auto I : Tmp) {
1253 }
1254
1255
1256 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1257}
1258
1259std::pair<ProgramStateRef, uint64_t>
1260ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,
1264 SVal *ElementCountVal) {
1265 assert(Region != nullptr && "Not-null region expected");
1266
1268 while (const auto *NTy = dyn_cast(Ty))
1269 Ty = NTy->getElementType().getDesugaredType(getContext());
1270
1272
1273 if (ElementCountVal)
1274 *ElementCountVal = ElementCount;
1275
1276
1277 unsigned Idx = 0;
1279 Idx = *OptionalIdx;
1280 } else {
1281
1282 if (!ElementCount.isConstant())
1283 return {State, 0};
1284
1285 Idx = ElementCount.getAsInteger()->getLimitedValue();
1286 }
1287
1288 if (Idx == 0)
1289 return {State, 0};
1290
1291 --Idx;
1292
1293 return {setPendingArrayDestruction(State, LCtx, Idx), Idx};
1294}
1295
1302 break;
1305 break;
1308 break;
1311 break;
1314 break;
1315 default:
1316 llvm_unreachable("Unexpected dtor kind.");
1317 }
1318
1319
1320 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1321}
1322
1328
1329
1330
1331 if (Opts.MayInlineCXXAllocator)
1333 else {
1334 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1336 PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx,
1339 }
1340 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1341}
1342
1349
1352
1353 SVal dest = state->getLValue(varDecl, LCtx);
1355
1357 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
1358 if (!ValueRegion) {
1359
1360
1361
1362
1363 return;
1364 }
1367 }
1368
1369 unsigned Idx = 0;
1371 SVal ElementCount;
1372 std::tie(state, Idx) = prepareStateForArrayDestruction(
1373 state, Region, varType, LCtx, &ElementCount);
1374
1375 if (ElementCount.isConstant()) {
1376 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1377 assert(ArrayLength &&
1378 "An automatic dtor for a 0 length array shouldn't be triggered!");
1379
1380
1381 if (!ArrayLength) {
1383 "ExprEngine", "Skipping automatic 0 length array destruction, "
1384 "which shouldn't be in the CFG.");
1387 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1389 return;
1390 }
1391 }
1392 }
1393
1395 Region = makeElementRegion(state, loc::MemRegionVal(Region), varType,
1397 .getAsRegion();
1398
1400
1402 "Prepare for object destruction");
1404 &PT);
1406
1407 if (!Pred)
1408 return;
1410
1412 false, Pred, Dst, CallOpts);
1413}
1414
1423 SVal ArgVal = State->getSVal(Arg, LCtx);
1424
1425
1426
1427 if (State->isNull(ArgVal).isConstrainedTrue()) {
1431
1433 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1435 return;
1436 }
1437
1438 auto getDtorDecl = [](const QualType &DTy) {
1441 };
1442
1443 unsigned Idx = 0;
1446
1449
1450 while (const auto *AT = getContext().getAsArrayType(DTy))
1451 DTy = AT->getElementType();
1452
1453 if (ArgR) {
1454 SVal ElementCount;
1455 std::tie(State, Idx) = prepareStateForArrayDestruction(
1456 State, ArgR, DTy, LCtx, &ElementCount);
1457
1458
1459
1460 if (ElementCount.isConstant() &&
1461 ElementCount.getAsInteger()->getLimitedValue() == 0) {
1462
1464 "ExprEngine", "Skipping 0 length array delete destruction");
1467 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1469 return;
1470 }
1471
1472 ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
1473 .getAsRegion();
1474 }
1475 }
1476
1479 "Prepare for object destruction");
1483
1484 if (!Pred)
1485 return;
1487
1488 VisitCXXDestructor(DTy, ArgR, DE, false, Pred, Dst, CallOpts);
1489}
1490
1494
1498 SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
1499
1500
1504 Base->isVirtual());
1505
1508 true, Pred, Dst, CallOpts);
1509}
1510
1518
1520 Loc ThisStorageLoc =
1522 Loc ThisLoc = State->getSVal(ThisStorageLoc).castAs<Loc>();
1523 SVal FieldVal = State->getLValue(Member, ThisLoc);
1524
1525 unsigned Idx = 0;
1527 SVal ElementCount;
1528 std::tie(State, Idx) = prepareStateForArrayDestruction(
1529 State, FieldVal.getAsRegion(), T, LCtx, &ElementCount);
1530
1531 if (ElementCount.isConstant()) {
1532 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1533 assert(ArrayLength &&
1534 "A member dtor for a 0 length array shouldn't be triggered!");
1535
1536
1537 if (!ArrayLength) {
1539 "ExprEngine", "Skipping member 0 length array destruction, which "
1540 "shouldn't be in the CFG.");
1543 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1545 return;
1546 }
1547 }
1548 }
1549
1551 FieldVal =
1552 makeElementRegion(State, FieldVal, T, CallOpts.IsArrayCtorOrDtor, Idx);
1553
1555
1557 "Prepare for object destruction");
1559 &PT);
1561
1562 if (!Pred)
1563 return;
1565
1567 false, Pred, Dst, CallOpts);
1568}
1569
1577
1580
1581
1582
1585 MR = V->getAsRegion();
1586 }
1587
1588
1589
1590 if (isDestructorElided(State, BTE, LC)) {
1591 State = cleanupElidedDestructor(State, BTE, LC);
1592 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1597 return;
1598 }
1599
1601 StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);
1603
1605
1606
1607 assert(CleanDtorState.size() <= 1);
1609 CleanDtorState.empty() ? Pred : *CleanDtorState.begin();
1610
1613 if (!MR) {
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1632 T = AT->getElementType();
1633
1634
1635
1636 }
1637 } else {
1638
1639
1640
1641 }
1643 false, CleanPred, Dst, CallOpts);
1644}
1645
1652 BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);
1656 TempDtorBuilder.generateNode(State, true, Pred);
1657 } else {
1658 TempDtorBuilder.generateNode(State, false, Pred);
1659 }
1660}
1661
1665
1666
1667
1669
1670
1671 Dst = PreVisit;
1672 return;
1673 }
1679
1680
1681
1682
1683 State = addObjectUnderConstruction(State, BTE, LC, UnknownVal());
1684 }
1686 }
1687}
1688
1693 class CollectReachableSymbolsCallback final : public SymbolVisitor {
1695
1696 public:
1697 explicit CollectReachableSymbolsCallback(InvalidatedSymbols &Symbols)
1698 : Symbols(Symbols) {}
1699
1701
1702 bool VisitSymbol(SymbolRef Sym) override {
1703 Symbols.insert(Sym);
1704 return true;
1705 }
1706 };
1708 CollectReachableSymbolsCallback CallBack(Symbols);
1710 State->scanReachableSymbols(V, CallBack);
1711
1713 State, CallBack.getSymbols(), Call, K, nullptr);
1714}
1715
1719 S->getBeginLoc(), "Error evaluating statement");
1722
1724
1726
1727 case Stmt::CXXDependentScopeMemberExprClass:
1728 case Stmt::CXXTryStmtClass:
1729 case Stmt::CXXTypeidExprClass:
1730 case Stmt::CXXUuidofExprClass:
1731 case Stmt::CXXFoldExprClass:
1732 case Stmt::MSPropertyRefExprClass:
1733 case Stmt::MSPropertySubscriptExprClass:
1734 case Stmt::CXXUnresolvedConstructExprClass:
1735 case Stmt::DependentScopeDeclRefExprClass:
1736 case Stmt::ArrayTypeTraitExprClass:
1737 case Stmt::ExpressionTraitExprClass:
1738 case Stmt::UnresolvedLookupExprClass:
1739 case Stmt::UnresolvedMemberExprClass:
1740 case Stmt::RecoveryExprClass:
1741 case Stmt::CXXNoexceptExprClass:
1742 case Stmt::PackExpansionExprClass:
1743 case Stmt::PackIndexingExprClass:
1744 case Stmt::SubstNonTypeTemplateParmPackExprClass:
1745 case Stmt::FunctionParmPackExprClass:
1746 case Stmt::CoroutineBodyStmtClass:
1747 case Stmt::CoawaitExprClass:
1748 case Stmt::DependentCoawaitExprClass:
1749 case Stmt::CoreturnStmtClass:
1750 case Stmt::CoyieldExprClass:
1751 case Stmt::SEHTryStmtClass:
1752 case Stmt::SEHExceptStmtClass:
1753 case Stmt::SEHLeaveStmtClass:
1754 case Stmt::SEHFinallyStmtClass:
1755 case Stmt::OMPCanonicalLoopClass:
1756 case Stmt::OMPParallelDirectiveClass:
1757 case Stmt::OMPSimdDirectiveClass:
1758 case Stmt::OMPForDirectiveClass:
1759 case Stmt::OMPForSimdDirectiveClass:
1760 case Stmt::OMPSectionsDirectiveClass:
1761 case Stmt::OMPSectionDirectiveClass:
1762 case Stmt::OMPScopeDirectiveClass:
1763 case Stmt::OMPSingleDirectiveClass:
1764 case Stmt::OMPMasterDirectiveClass:
1765 case Stmt::OMPCriticalDirectiveClass:
1766 case Stmt::OMPParallelForDirectiveClass:
1767 case Stmt::OMPParallelForSimdDirectiveClass:
1768 case Stmt::OMPParallelSectionsDirectiveClass:
1769 case Stmt::OMPParallelMasterDirectiveClass:
1770 case Stmt::OMPParallelMaskedDirectiveClass:
1771 case Stmt::OMPTaskDirectiveClass:
1772 case Stmt::OMPTaskyieldDirectiveClass:
1773 case Stmt::OMPBarrierDirectiveClass:
1774 case Stmt::OMPTaskwaitDirectiveClass:
1775 case Stmt::OMPErrorDirectiveClass:
1776 case Stmt::OMPTaskgroupDirectiveClass:
1777 case Stmt::OMPFlushDirectiveClass:
1778 case Stmt::OMPDepobjDirectiveClass:
1779 case Stmt::OMPScanDirectiveClass:
1780 case Stmt::OMPOrderedDirectiveClass:
1781 case Stmt::OMPAtomicDirectiveClass:
1782 case Stmt::OMPAssumeDirectiveClass:
1783 case Stmt::OMPTargetDirectiveClass:
1784 case Stmt::OMPTargetDataDirectiveClass:
1785 case Stmt::OMPTargetEnterDataDirectiveClass:
1786 case Stmt::OMPTargetExitDataDirectiveClass:
1787 case Stmt::OMPTargetParallelDirectiveClass:
1788 case Stmt::OMPTargetParallelForDirectiveClass:
1789 case Stmt::OMPTargetUpdateDirectiveClass:
1790 case Stmt::OMPTeamsDirectiveClass:
1791 case Stmt::OMPCancellationPointDirectiveClass:
1792 case Stmt::OMPCancelDirectiveClass:
1793 case Stmt::OMPTaskLoopDirectiveClass:
1794 case Stmt::OMPTaskLoopSimdDirectiveClass:
1795 case Stmt::OMPMasterTaskLoopDirectiveClass:
1796 case Stmt::OMPMaskedTaskLoopDirectiveClass:
1797 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1798 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1799 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1800 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1801 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1802 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1803 case Stmt::OMPDistributeDirectiveClass:
1804 case Stmt::OMPDistributeParallelForDirectiveClass:
1805 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1806 case Stmt::OMPDistributeSimdDirectiveClass:
1807 case Stmt::OMPTargetParallelForSimdDirectiveClass:
1808 case Stmt::OMPTargetSimdDirectiveClass:
1809 case Stmt::OMPTeamsDistributeDirectiveClass:
1810 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1811 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1812 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1813 case Stmt::OMPTargetTeamsDirectiveClass:
1814 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1815 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1816 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1817 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1818 case Stmt::OMPReverseDirectiveClass:
1819 case Stmt::OMPStripeDirectiveClass:
1820 case Stmt::OMPTileDirectiveClass:
1821 case Stmt::OMPInterchangeDirectiveClass:
1822 case Stmt::OMPFuseDirectiveClass:
1823 case Stmt::OMPInteropDirectiveClass:
1824 case Stmt::OMPDispatchDirectiveClass:
1825 case Stmt::OMPMaskedDirectiveClass:
1826 case Stmt::OMPGenericLoopDirectiveClass:
1827 case Stmt::OMPTeamsGenericLoopDirectiveClass:
1828 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
1829 case Stmt::OMPParallelGenericLoopDirectiveClass:
1830 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1831 case Stmt::CapturedStmtClass:
1832 case Stmt::SYCLKernelCallStmtClass:
1833 case Stmt::OpenACCComputeConstructClass:
1834 case Stmt::OpenACCLoopConstructClass:
1835 case Stmt::OpenACCCombinedConstructClass:
1836 case Stmt::OpenACCDataConstructClass:
1837 case Stmt::OpenACCEnterDataConstructClass:
1838 case Stmt::OpenACCExitDataConstructClass:
1839 case Stmt::OpenACCHostDataConstructClass:
1840 case Stmt::OpenACCWaitConstructClass:
1841 case Stmt::OpenACCCacheConstructClass:
1842 case Stmt::OpenACCInitConstructClass:
1843 case Stmt::OpenACCShutdownConstructClass:
1844 case Stmt::OpenACCSetConstructClass:
1845 case Stmt::OpenACCUpdateConstructClass:
1846 case Stmt::OpenACCAtomicConstructClass:
1847 case Stmt::OMPUnrollDirectiveClass:
1848 case Stmt::OMPMetaDirectiveClass:
1849 case Stmt::HLSLOutArgExprClass: {
1851 Engine.addAbortedBlock(node, currBldrCtx->getBlock());
1852 break;
1853 }
1854
1855 case Stmt::ParenExprClass:
1856 llvm_unreachable("ParenExprs already handled.");
1857 case Stmt::GenericSelectionExprClass:
1858 llvm_unreachable("GenericSelectionExprs already handled.");
1859
1860
1861 case Stmt::BreakStmtClass:
1862 case Stmt::CaseStmtClass:
1863 case Stmt::CompoundStmtClass:
1864 case Stmt::ContinueStmtClass:
1865 case Stmt::CXXForRangeStmtClass:
1866 case Stmt::DefaultStmtClass:
1867 case Stmt::DoStmtClass:
1868 case Stmt::ForStmtClass:
1869 case Stmt::GotoStmtClass:
1870 case Stmt::IfStmtClass:
1871 case Stmt::IndirectGotoStmtClass:
1872 case Stmt::LabelStmtClass:
1874 case Stmt::NullStmtClass:
1875 case Stmt::SwitchStmtClass:
1876 case Stmt::WhileStmtClass:
1877 case Stmt::DeferStmtClass:
1878 case Expr::MSDependentExistsStmtClass:
1879 llvm_unreachable("Stmt should not be in analyzer evaluation loop");
1880 case Stmt::ImplicitValueInitExprClass:
1881
1882
1883
1884 llvm_unreachable("Should be pruned from CFG");
1885
1886 case Stmt::ObjCSubscriptRefExprClass:
1887 case Stmt::ObjCPropertyRefExprClass:
1888 llvm_unreachable("These are handled by PseudoObjectExpr");
1889
1890 case Stmt::GNUNullExprClass: {
1891
1893 state = state->BindExpr(
1895 svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));
1897 break;
1898 }
1899
1900 case Stmt::ObjCAtSynchronizedStmtClass:
1904 break;
1905
1906 case Expr::ConstantExprClass:
1907 case Stmt::ExprWithCleanupsClass:
1908
1909 break;
1910
1911 case Stmt::CXXBindTemporaryExprClass: {
1919 break;
1920 }
1921
1922 case Stmt::ArrayInitLoopExprClass:
1926 break;
1927
1928 case Stmt::DesignatedInitExprClass:
1929 case Stmt::DesignatedInitUpdateExprClass:
1930 case Stmt::ArrayInitIndexExprClass:
1931 case Stmt::ExtVectorElementExprClass:
1932 case Stmt::ImaginaryLiteralClass:
1933 case Stmt::ObjCAtCatchStmtClass:
1934 case Stmt::ObjCAtFinallyStmtClass:
1935 case Stmt::ObjCAtTryStmtClass:
1936 case Stmt::ObjCAutoreleasePoolStmtClass:
1937 case Stmt::ObjCEncodeExprClass:
1938 case Stmt::ObjCIsaExprClass:
1939 case Stmt::ObjCProtocolExprClass:
1940 case Stmt::ObjCSelectorExprClass:
1941 case Stmt::ParenListExprClass:
1942 case Stmt::ShuffleVectorExprClass:
1943 case Stmt::ConvertVectorExprClass:
1944 case Stmt::VAArgExprClass:
1945 case Stmt::CUDAKernelCallExprClass:
1946 case Stmt::OpaqueValueExprClass:
1947 case Stmt::AsTypeExprClass:
1948 case Stmt::ConceptSpecializationExprClass:
1949 case Stmt::CXXRewrittenBinaryOperatorClass:
1950 case Stmt::RequiresExprClass:
1951 case Stmt::EmbedExprClass:
1952
1953
1954
1955
1956 case Stmt::PredefinedExprClass:
1957 case Stmt::AddrLabelExprClass:
1958 case Stmt::IntegerLiteralClass:
1959 case Stmt::FixedPointLiteralClass:
1960 case Stmt::CharacterLiteralClass:
1961 case Stmt::CXXScalarValueInitExprClass:
1962 case Stmt::CXXBoolLiteralExprClass:
1963 case Stmt::ObjCBoolLiteralExprClass:
1964 case Stmt::ObjCAvailabilityCheckExprClass:
1965 case Stmt::FloatingLiteralClass:
1966 case Stmt::NoInitExprClass:
1967 case Stmt::SizeOfPackExprClass:
1968 case Stmt::StringLiteralClass:
1969 case Stmt::SourceLocExprClass:
1970 case Stmt::ObjCStringLiteralClass:
1971 case Stmt::CXXPseudoDestructorExprClass:
1972 case Stmt::SubstNonTypeTemplateParmExprClass:
1973 case Stmt::CXXNullPtrLiteralExprClass:
1974 case Stmt::ArraySectionExprClass:
1975 case Stmt::OMPArrayShapingExprClass:
1976 case Stmt::OMPIteratorExprClass:
1977 case Stmt::SYCLUniqueStableNameExprClass:
1978 case Stmt::OpenACCAsteriskSizeExprClass:
1979 case Stmt::TypeTraitExprClass: {
1985 break;
1986 }
1987
1988 case Stmt::AttributedStmtClass: {
1992 break;
1993 }
1994
1995 case Stmt::CXXDefaultArgExprClass:
1996 case Stmt::CXXDefaultInitExprClass: {
2000
2003
2004 const Expr *ArgE;
2005 if (const auto *DefE = dyn_cast(S))
2006 ArgE = DefE->getExpr();
2007 else if (const auto *DefE = dyn_cast(S))
2008 ArgE = DefE->getExpr();
2009 else
2010 llvm_unreachable("unknown constant wrapper kind");
2011
2012 bool IsTemporary = false;
2013 if (const auto *MTE = dyn_cast(ArgE)) {
2014 ArgE = MTE->getSubExpr();
2015 IsTemporary = true;
2016 }
2017
2018 std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);
2019 if (!ConstantVal)
2021
2023 for (const auto I : PreVisit) {
2025 State = State->BindExpr(S, LCtx, *ConstantVal);
2026 if (IsTemporary)
2027 State = createTemporaryRegionIfNeeded(State, LCtx,
2031 }
2032
2035 break;
2036 }
2037
2038
2039 case Stmt::CXXStdInitializerListExprClass:
2040 case Expr::ObjCArrayLiteralClass:
2041 case Expr::ObjCDictionaryLiteralClass:
2042 case Expr::ObjCBoxedExprClass: {
2044
2047
2050
2052 QualType resultType = Ex->getType();
2053
2054 for (const auto N : preVisit) {
2056 SVal result = svalBuilder.conjureSymbolVal(
2057 nullptr, getCFGElementRef(), LCtx, resultType,
2058 currBldrCtx->blockCount());
2059 ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
2060
2061
2062
2066 for (auto Child : Ex->children()) {
2067 assert(Child);
2068 SVal Val = State->getSVal(Child, LCtx);
2070 }
2071
2073 }
2074
2077 break;
2078 }
2079
2080 case Stmt::ArraySubscriptExprClass:
2084 break;
2085
2086 case Stmt::MatrixSubscriptExprClass:
2087 llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
2088 break;
2089
2090 case Stmt::GCCAsmStmtClass: {
2099 break;
2100 }
2101
2102 case Stmt::MSAsmStmtClass:
2106 break;
2107
2108 case Stmt::BlockExprClass:
2112 break;
2113
2114 case Stmt::LambdaExprClass:
2115 if (AMgr.options.ShouldInlineLambdas) {
2119 } else {
2121 Engine.addAbortedBlock(node, currBldrCtx->getBlock());
2122 }
2123 break;
2124
2125 case Stmt::BinaryOperatorClass: {
2127 if (B->isLogicalOp()) {
2131 break;
2132 }
2133 else if (B->getOpcode() == BO_Comma) {
2137 state->getSVal(B->getRHS(),
2139 break;
2140 }
2141
2143
2144 if (AMgr.options.ShouldEagerlyAssume &&
2145 (B->isRelationalOp() || B->isEqualityOp())) {
2149 }
2150 else
2152
2154 break;
2155 }
2156
2157 case Stmt::CXXOperatorCallExprClass: {
2159
2160
2161
2162 const Decl *Callee = OCE->getCalleeDecl();
2163 if (const auto *MD = dyn_cast_or_null(Callee)) {
2164 if (MD->isImplicitObjectMemberFunction()) {
2168 createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
2169 if (NewState != State) {
2170 Pred = Bldr.generateNode(OCE, Pred, NewState, nullptr,
2172
2173 if (!Pred)
2174 break;
2175 }
2176 }
2177 }
2178 [[fallthrough]];
2179 }
2180
2181 case Stmt::CallExprClass:
2182 case Stmt::CXXMemberCallExprClass:
2183 case Stmt::UserDefinedLiteralClass:
2187 break;
2188
2189 case Stmt::CXXCatchStmtClass:
2193 break;
2194
2195 case Stmt::CXXTemporaryObjectExprClass:
2196 case Stmt::CXXConstructExprClass:
2200 break;
2201
2202 case Stmt::CXXInheritedCtorInitExprClass:
2205 Dst);
2207 break;
2208
2209 case Stmt::CXXNewExprClass: {
2211
2214
2216 for (const auto i : PreVisit)
2218
2221 break;
2222 }
2223
2224 case Stmt::CXXDeleteExprClass: {
2231
2232 for (const auto i : PostVisit)
2234
2236 break;
2237 }
2238
2239
2240
2241 case Stmt::ChooseExprClass: {
2246 break;
2247 }
2248
2249 case Stmt::CompoundAssignOperatorClass:
2253 break;
2254
2255 case Stmt::CompoundLiteralExprClass:
2259 break;
2260
2261 case Stmt::BinaryConditionalOperatorClass:
2262 case Stmt::ConditionalOperatorClass: {
2267 break;
2268 }
2269
2270 case Stmt::CXXThisExprClass:
2274 break;
2275
2276 case Stmt::DeclRefExprClass: {
2281 break;
2282 }
2283
2284 case Stmt::DeclStmtClass:
2288 break;
2289
2290 case Stmt::ImplicitCastExprClass:
2291 case Stmt::CStyleCastExprClass:
2292 case Stmt::CXXStaticCastExprClass:
2293 case Stmt::CXXDynamicCastExprClass:
2294 case Stmt::CXXReinterpretCastExprClass:
2295 case Stmt::CXXConstCastExprClass:
2296 case Stmt::CXXFunctionalCastExprClass:
2297 case Stmt::BuiltinBitCastExprClass:
2298 case Stmt::ObjCBridgedCastExprClass:
2299 case Stmt::CXXAddrspaceCastExprClass: {
2303 VisitCast(C, C->getSubExpr(), Pred, dstExpr);
2304
2305
2308 break;
2309 }
2310
2311 case Expr::MaterializeTemporaryExprClass: {
2317 for (const auto i : dstPrevisit)
2321 break;
2322 }
2323
2324 case Stmt::InitListExprClass: {
2329 break;
2330 }
2331
2332 case Expr::CXXParenListInitExprClass: {
2336 Dst);
2338 break;
2339 }
2340
2341 case Stmt::MemberExprClass:
2345 break;
2346
2347 case Stmt::AtomicExprClass:
2351 break;
2352
2353 case Stmt::ObjCIvarRefExprClass:
2357 break;
2358
2359 case Stmt::ObjCForCollectionStmtClass:
2363 break;
2364
2365 case Stmt::ObjCMessageExprClass:
2369 break;
2370
2371 case Stmt::ObjCAtThrowStmtClass:
2372 case Stmt::CXXThrowExprClass:
2373
2374
2376 break;
2377
2378 case Stmt::ReturnStmtClass:
2382 break;
2383
2384 case Stmt::OffsetOfExprClass: {
2388
2390 for (const auto Node : PreVisit)
2392
2395 break;
2396 }
2397
2398 case Stmt::UnaryExprOrTypeTraitExprClass:
2401 Pred, Dst);
2403 break;
2404
2405 case Stmt::StmtExprClass: {
2407
2408 if (SE->getSubStmt()->body_empty()) {
2409
2410 assert(SE->getType() == getContext().VoidTy
2411 && "Empty statement expression must have void type.");
2412 break;
2413 }
2414
2415 if (const auto *LastExpr =
2416 dyn_cast(*SE->getSubStmt()->body_rbegin())) {
2420 state->getSVal(LastExpr,
2422 }
2423 break;
2424 }
2425
2426 case Stmt::UnaryOperatorClass: {
2429 if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
2433 }
2434 else
2437 break;
2438 }
2439
2440 case Stmt::PseudoObjectExprClass: {
2444 if (const Expr *Result = PE->getResultExpr()) {
2448 }
2449 else
2453
2455 break;
2456 }
2457
2458 case Expr::ObjCIndirectCopyRestoreExprClass: {
2459
2460
2461
2465 const Expr *E = OIE->getSubExpr();
2470 break;
2471 }
2472 }
2473}
2474
2475bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
2479 assert(CalleeSF && CallerSF);
2480 ExplodedNode *BeforeProcessingCall = nullptr;
2482
2483
2484 while (N) {
2486 BeforeProcessingCall = N;
2488
2489
2491 continue;
2492
2493
2495 continue;
2497 continue;
2499 continue;
2500 if (std::optional SP = L.getAs<StmtPoint>())
2501 if (SP->getStmt() == CE)
2502 continue;
2503 break;
2504 }
2505
2506 if (!BeforeProcessingCall)
2507 return false;
2508
2509
2510
2511
2512
2516
2517
2519 NewNodeState =
2521
2522
2523 bool IsNew = false;
2524 ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew);
2525
2526
2527 if (!IsNew)
2528 return true;
2529
2531
2532
2535 NumTimesRetriedWithoutInlining++;
2536 return true;
2537}
2538
2539
2540
2546
2548 return nullptr;
2549
2550 return CalleeLC;
2551}
2552
2553
2557
2558
2559 if(AMgr.options.ShouldUnrollLoops) {
2560 unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
2562 if (Term) {
2564 Pred, maxBlockVisitOnPath);
2565 if (NewState != Pred->getState()) {
2567 if (!UpdatedNode)
2568 return;
2569 Pred = UpdatedNode;
2570 }
2571 }
2572
2574 return;
2575 }
2576
2577
2578
2580 if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
2581 AMgr.options.ShouldWidenLoops) {
2583 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
2584 return;
2585
2586
2588
2589
2590
2591
2592
2593
2594
2598 nodeBuilder.generateNode(WidenedState, Pred);
2599 return;
2600 }
2601
2602
2603 if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
2607
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618 Engine.FunctionSummaries->markShouldNotInline(
2620
2621
2622
2623
2624
2625 if ((!AMgr.options.NoRetryExhausted && replayWithoutInlining(Pred, LC)))
2626 return;
2627 NumMaxBlockCountReachedInInlined++;
2628 } else
2629 NumMaxBlockCountReached++;
2630
2631
2632 Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
2633 }
2634}
2635
2640 llvm::PrettyStackTraceFormat CrashInfo(
2641 "Processing block entrance B%d -> B%d",
2644 currBldrCtx = &BldCtx;
2646 currBldrCtx = nullptr;
2647}
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2662
2663 const auto *Ex = dyn_cast(Condition);
2664 if (!Ex)
2666
2667 uint64_t bits = 0;
2668 bool bitsInit = false;
2669
2670 while (const auto *CE = dyn_cast(Ex)) {
2672
2673 if (->isIntegralOrEnumerationType())
2675
2677 if (!bitsInit || newBits < bits) {
2678 bitsInit = true;
2679 bits = newBits;
2680 }
2681
2682 Ex = CE->getSubExpr();
2683 }
2684
2685
2687
2688 if (!bitsInit || ->isIntegralOrEnumerationType() ||
2691
2692 return state->getSVal(Ex, LCtx);
2693}
2694
2695#ifndef NDEBUG
2698 const auto *BO = dyn_cast(Condition);
2699 if (!BO || !BO->isLogicalOp()) {
2701 }
2702 Condition = BO->getRHS()->IgnoreParens();
2703 }
2704 return nullptr;
2705}
2706#endif
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2724 if (const auto *Ex = dyn_cast(Condition))
2726
2727 const auto *BO = dyn_cast(Condition);
2728 if (!BO || !BO->isLogicalOp())
2730
2732 "Other kinds of branches are handled separately!");
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742 for (CFGElement Elem : llvm::reverse(*B)) {
2743 std::optional CS = Elem.getAs<CFGStmt>();
2744 if (!CS)
2745 continue;
2746 const Stmt *LastStmt = CS->getStmt();
2748 return LastStmt;
2749 }
2750 llvm_unreachable("could not resolve condition");
2751}
2752
2754 std::pair<const ObjCForCollectionStmt *, const LocationContext *>;
2755
2757
2761 assert(!State->contains({O, LC}));
2762 return State->set({O, LC}, HasMoreIteraton);
2763}
2764
2769 assert(State->contains({O, LC}));
2770 return State->remove({O, LC});
2771}
2772
2776 assert(State->contains({O, LC}));
2777 return *State->get({O, LC});
2778}
2779
2780
2781
2782
2783static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
2786 if (const auto *ObjCFor = dyn_cast(Condition)) {
2787 bool HasMoreIteraton =
2789
2790
2791
2794 if (HasMoreIteraton)
2795 return std::pair<ProgramStateRef, ProgramStateRef>{State, nullptr};
2796 else
2797 return std::pair<ProgramStateRef, ProgramStateRef>{nullptr, State};
2798 }
2800
2801 if (X.isUnknownOrUndef()) {
2802
2803 if (const auto *Ex = dyn_cast(Condition)) {
2804 if (Ex->getType()->isIntegralOrEnumerationType()) {
2805
2806
2807
2808
2809 SVal recovered =
2811 N->getState()->getStateManager().getContext());
2812
2814 X = recovered;
2815 }
2816 }
2817 }
2818 }
2819
2820
2821 if (X.isUnknownOrUndef())
2822 return std::nullopt;
2823
2825
2827 return State->assume(V);
2828}
2829
2833 std::optional IterationsCompletedInLoop) {
2835 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2836 currBldrCtx = &BldCtx;
2837
2838
2842 return;
2843 }
2844
2845 if (const auto *Ex = dyn_cast(Condition))
2847
2851 "Error evaluating branch");
2852
2855 Pred, *this);
2856
2857 if (CheckersOutSet.empty())
2858 return;
2859
2860 BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
2861 for (ExplodedNode *PredN : CheckersOutSet) {
2862 if (PredN->isSink())
2863 continue;
2864
2866
2867 ProgramStateRef StTrue = PrevState, StFalse = PrevState;
2869 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2870
2871 if (StTrue && StFalse)
2873
2874
2875
2876
2877
2878
2879
2880
2881 bool BothFeasible =
2882 (StTrue && StFalse) ||
2884
2885 if (StTrue) {
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901 bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;
2902 bool SkipTrueBranch = BothFeasible && CompletedTwoIterations;
2903
2904
2905
2906
2907
2908 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops) {
2909 Builder.generateNode(StTrue, true, PredN);
2910 } else if (!AMgr.options.InlineFunctionsWithAmbiguousLoops) {
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2927 Engine.FunctionSummaries->markShouldNotInline(
2929 }
2930 }
2931 }
2932
2933 if (StFalse) {
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946 bool BeforeFirstIteration = IterationsCompletedInLoop == std::optional{0};
2947 bool SkipFalseBranch = BothFeasible && BeforeFirstIteration &&
2948 AMgr.options.ShouldAssumeAtLeastOneIteration;
2949 if (!SkipFalseBranch)
2950 Builder.generateNode(StFalse, false, PredN);
2951 }
2952 }
2953 currBldrCtx = nullptr;
2954}
2955
2956
2957
2959 llvm::ImmutableSet<const VarDecl *>)
2960
2964 currBldrCtx = &BuilderCtx;
2965
2968 bool initHasRun = state->contains(VD);
2970
2971 if (!initHasRun) {
2972 state = state->add(VD);
2973 }
2974
2975 Builder.generateNode(state, initHasRun, Pred);
2976
2977 currBldrCtx = nullptr;
2978}
2979
2980
2981
2985
2986
2987
2988
2989
2990
2991
2992
2994
2995 if (std::optionalloc::GotoLabel LV = V.getAs<loc::GotoLabel>()) {
2996 const LabelDecl *L = LV->getLabel();
2997
2998 for (iterator Succ : builder) {
2999 if (Succ.getLabel() == L) {
3000 builder.generateNode(Succ, state);
3001 return;
3002 }
3003 }
3004
3005 llvm_unreachable("No block with label.");
3006 }
3007
3009
3010
3011
3012
3013 return;
3014 }
3015
3016
3017
3018
3019 for (iterator Succ : builder)
3021}
3022
3030
3031
3032
3037
3039 State = finishArgumentConstruction(
3040 State, *getStateManager().getCallEventManager().getCaller(
3042
3043
3044
3045
3046
3047
3048
3049
3050 {
3054 while (LC != ToLC) {
3055 assert(LC && "ToLC must be a parent of FromLC!");
3056 for (auto I : State->get())
3057 if (I.first.getLocationContext() == LC) {
3058
3059
3060
3061 assert(I.first.getItem().getKind() ==
3063 I.first.getItem().getKind() ==
3065 State = State->remove(I.first);
3066 }
3068 }
3069 }
3070
3071
3072 if (State != Pred->getState()) {
3074 NodeBuilder Bldr(Pred, PostCleanup, BC);
3076 if (!Pred) {
3077
3078
3079 return;
3080 }
3081 }
3082
3083 assert(areAllObjectsFullyConstructed(Pred->getState(),
3088
3091
3092
3093 for (const auto I : AfterRemovedDead)
3095 } else {
3097 }
3098
3099 Engine.enqueueEndOfFunction(Dst, RS);
3100}
3101
3102
3103
3106
3110
3111 if (CondV_untested.isUndef()) {
3112
3113
3114
3115
3116 return;
3117 }
3119
3121
3123 bool defaultIsFeasible = I == EI;
3124
3125 for ( ; I != EI; ++I) {
3126
3127 if (!I.getBlock())
3128 continue;
3129
3130 const CaseStmt *Case = I.getCase();
3131
3132
3134 assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType()));
3135
3136
3137 llvm::APSInt V2;
3139 V2 = E->EvaluateKnownConstInt(getContext());
3140 else
3141 V2 = V1;
3142
3144 if (std::optional NL = CondV.getAs<NonLoc>())
3145 std::tie(StateCase, DefaultSt) =
3146 DefaultSt->assumeInclusiveRange(*NL, V1, V2);
3147 else
3148 StateCase = DefaultSt;
3149
3150 if (StateCase)
3152
3153
3154
3155 if (DefaultSt)
3156 defaultIsFeasible = true;
3157 else {
3158 defaultIsFeasible = false;
3159 break;
3160 }
3161 }
3162
3163 if (!defaultIsFeasible)
3164 return;
3165
3166
3167
3168
3169
3170
3171
3172
3177 return;
3178 }
3179
3181}
3182
3183
3184
3185
3186
3191
3194
3195 auto resolveAsLambdaCapturedVar =
3196 [&](const ValueDecl *VD) -> std::optional<std::pair<SVal, QualType>> {
3197 const auto *MD = dyn_cast(LCtx->getDecl());
3198 const auto *DeclRefEx = dyn_cast(Ex);
3199 if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
3200 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
3201 MD->getParent()->isLambda()) {
3202
3204 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
3205 FieldDecl *LambdaThisCaptureField;
3206 CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
3207
3208
3209
3210 if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
3212 SVal CXXThisVal = state->getSVal(CXXThis);
3213 return std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
3214 }
3215 }
3216
3217 return std::nullopt;
3218 };
3219
3220 if (const auto *VD = dyn_cast(D)) {
3221
3222
3223 assert(Ex->isGLValue() || VD->getType()->isVoidType());
3225 std::optional<std::pair<SVal, QualType>> VInfo =
3226 resolveAsLambdaCapturedVar(VD);
3227
3228 if (!VInfo)
3229 VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());
3230
3232 bool IsReference = VInfo->second->isReferenceType();
3233
3234
3235
3236 if (IsReference) {
3237 if (const MemRegion *R = V.getAsRegion())
3238 V = state->getSVal(R);
3239 else
3241 }
3242
3243 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3245 return;
3246 }
3247 if (const auto *ED = dyn_cast(D)) {
3249 SVal V = svalBuilder.makeIntVal(ED->getInitVal());
3250 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
3251 return;
3252 }
3253 if (const auto *FD = dyn_cast(D)) {
3254 SVal V = svalBuilder.getFunctionPointer(FD);
3255 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3257 return;
3258 }
3260
3261
3262 return;
3263 }
3264 if (const auto *BD = dyn_cast(D)) {
3265
3266 if (std::optional<std::pair<SVal, QualType>> VInfo =
3267 resolveAsLambdaCapturedVar(BD)) {
3268 auto [V, T] = VInfo.value();
3269
3270 if (T->isReferenceType()) {
3271 if (const MemRegion *R = V.getAsRegion())
3272 V = state->getSVal(R);
3273 else
3275 }
3276
3277 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3279 return;
3280 }
3281
3283
3284 SVal Base = state->getLValue(DD, LCtx);
3285 if (DD->getType()->isReferenceType()) {
3287 Base = state->getSVal(R);
3288 else
3290 }
3291
3293
3294
3295 if (const auto *ME = dyn_cast(BD->getBinding())) {
3296 const auto *Field = cast(ME->getMemberDecl());
3297 V = state->getLValue(Field, Base);
3298 }
3299
3300 else if (const auto *ASE = dyn_cast(BD->getBinding())) {
3301 SVal Idx = state->getSVal(ASE->getIdx(), LCtx);
3302
3303
3304
3305
3306 assert(Idx.isConstant() && "BindingDecl array index is not a constant!");
3307
3308 V = state->getLValue(BD->getType(), Idx, Base);
3309 }
3310
3311 else if (const auto *HV = BD->getHoldingVar()) {
3312 V = state->getLValue(HV, LCtx);
3313
3314 if (HV->getType()->isReferenceType()) {
3315 if (const MemRegion *R = V.getAsRegion())
3316 V = state->getSVal(R);
3317 else
3319 }
3320 } else
3321 llvm_unreachable("An unknown case of structured binding encountered!");
3322
3323
3324
3325 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3326 if (const MemRegion *R = V.getAsRegion())
3327 V = state->getSVal(R);
3328 else
3330 }
3331
3332 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3334
3335 return;
3336 }
3337
3338 if (const auto *TPO = dyn_cast(D)) {
3339
3340 (void)TPO;
3341 return;
3342 }
3343
3344 llvm_unreachable("Support for this Decl not implemented.");
3345}
3346
3347
3353
3355 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
3356
3358
3359 for (auto *Node : CheckerPreStmt) {
3360
3361
3363 break;
3364
3365 const LocationContext *LCtx = Node->getLocationContext();
3367
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404 if (const auto *ME = dyn_cast(Arr)) {
3405 Expr *MEBase = ME->getBase();
3406
3407
3408 if (auto CXXSCE = dyn_cast(MEBase)) {
3409 MEBase = CXXSCE->getSubExpr();
3410 }
3411
3413 SVal Obj = state->getLValue(cast(ObjDeclExpr->getDecl()), LCtx);
3414
3416 }
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430 if (const DeclRefExpr *DRE = dyn_cast(Arr))
3432
3433
3435 Base = state->getSVal(R);
3436 else
3438
3439 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, Base));
3440 }
3441
3443}
3444
3445
3451
3454
3456 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
3457
3459
3460
3461
3462
3463 bool IsGLValueLike = A->isGLValue() ||
3464 (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
3465
3466 for (auto *Node : CheckerPreStmt) {
3467 const LocationContext *LCtx = Node->getLocationContext();
3469
3470 if (IsGLValueLike) {
3472
3473
3474
3475
3476 if (T->isVoidType())
3478
3479 SVal V = state->getLValue(T,
3480 state->getSVal(Idx, LCtx),
3481 state->getSVal(Base, LCtx));
3482 Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
3484 } else if (IsVectorType) {
3485
3487 } else {
3488 llvm_unreachable("Array subscript should be an lValue when not \
3489a vector and not a forbidden lvalue type");
3490 }
3491 }
3492
3494}
3495
3496
3499
3502
3505
3506
3507
3509 for (const auto I : CheckedSet)
3511 } else {
3512 StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
3514
3515 for (const auto I : CheckedSet) {
3519
3520
3521 if (const auto *MD = dyn_cast(Member)) {
3522 if (MD->isImplicitObjectMemberFunction())
3523 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
3524
3525 SVal MDVal = svalBuilder.getFunctionPointer(MD);
3526 state = state->BindExpr(M, LCtx, MDVal);
3527
3529 continue;
3530 }
3531
3532
3534 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,
3535 nullptr,
3536 &MR);
3537 SVal baseExprVal =
3539
3540
3541 if (const auto *SR =
3542 dyn_cast_or_null(baseExprVal.getAsRegion())) {
3543 QualType T = SR->getPointeeStaticType();
3544 baseExprVal =
3546 }
3547
3549 SVal L = state->getLValue(field, baseExprVal);
3550
3552
3553
3554
3555
3558 const auto *PE =
3559 dyn_cast(I->getParentMap().getParentIgnoreParens(M));
3560 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
3561 llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
3562 }
3563 }
3564
3565 if (field->getType()->isReferenceType()) {
3567 L = state->getSVal(R);
3568 else
3570 }
3571
3572 Bldr.generateNode(M, I, state->BindExpr(M, LCtx, L), nullptr,
3574 } else {
3576 evalLoad(Tmp, M, M, I, state, L);
3578 }
3579 }
3580 }
3581
3583}
3584
3589
3590
3591
3592
3594 StmtNodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx);
3595
3596 for (const auto I : AfterPreSet) {
3599
3601 for (unsigned SI = 0, Count = AE->getNumSubExprs(); SI != Count; SI++) {
3603 SVal SubExprVal = State->getSVal(SubExpr, LCtx);
3604 ValuesToInvalidate.push_back(SubExprVal);
3605 }
3606
3607 State = State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
3608 currBldrCtx->blockCount(), LCtx,
3609 true,
3610 nullptr);
3611
3613 State = State->BindExpr(AE, LCtx, ResultVal);
3616 }
3617
3619}
3620
3621
3622
3623
3624
3625
3626
3627
3633 for (const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
3634
3635 const MemRegion *MR = LocAndVal.first.getAsRegion();
3638 Escaped.push_back(LocAndVal.second);
3639 continue;
3640 }
3641
3642
3643 if (const auto *VR = dyn_cast(MR->getBaseRegion()))
3645 VR->getStackFrame()->inTopFrame())
3646 if (const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3647 if (!RD->hasTrivialDestructor()) {
3648 Escaped.push_back(LocAndVal.second);
3649 continue;
3650 }
3651
3652
3653
3654
3655
3656
3657 SVal StoredVal = State->getSVal(MR);
3658 if (StoredVal != LocAndVal.second)
3659 if (State ==
3660 (State->bindLoc(loc::MemRegionVal(MR), LocAndVal.second, LCtx)))
3661 Escaped.push_back(LocAndVal.second);
3662 }
3663
3664 if (Escaped.empty())
3665 return State;
3666
3668}
3669
3673 std::pair<SVal, SVal> LocAndVal(Loc, Val);
3675 nullptr);
3676}
3677
3684 if (!Invalidated || Invalidated->empty())
3685 return State;
3686
3689 *Invalidated,
3690 nullptr,
3692 &ITraits);
3693
3694
3695
3697 for (const auto I : ExplicitRegions) {
3699 SymbolsDirectlyInvalidated.insert(R->getSymbol());
3700 }
3701
3703 for (const auto &sym : *Invalidated) {
3704 if (SymbolsDirectlyInvalidated.count(sym))
3705 continue;
3706 SymbolsIndirectlyInvalidated.insert(sym);
3707 }
3708
3709 if (!SymbolsDirectlyInvalidated.empty())
3712
3713
3714 if (!SymbolsIndirectlyInvalidated.empty())
3717
3718 return State;
3719}
3720
3721
3722
3728 if (!PP)
3729 PP = &PS;
3730
3731
3734 StoreE, AtDeclInit, *this, *PP);
3735
3737
3738
3739
3742 nullptr);
3745 Bldr.generateNode(L, state, Pred);
3746 return;
3747 }
3748
3749 for (const auto PredI : CheckedSet) {
3751
3753
3754
3755
3756
3757 state = state->bindLoc(location.castAs<Loc>(), Val, LC,
3758 !AtDeclInit);
3759
3760 const MemRegion *LocReg = nullptr;
3761 if (std::optionalloc::MemRegionVal LocRegVal =
3763 LocReg = LocRegVal->getRegion();
3764 }
3765
3767 Bldr.generateNode(L, state, PredI);
3768 }
3769}
3770
3771
3772
3773
3774
3775
3776
3777
3778
3780 const Expr *LocationE,
3784
3785
3786 const Expr *StoreE = AssignE ? AssignE : LocationE;
3787
3788
3790 evalLocation(Tmp, AssignE, LocationE, Pred, state, location, false);
3791
3792 if (Tmp.empty())
3793 return;
3794
3796 return;
3797
3798 for (const auto I : Tmp)
3799 evalBind(Dst, StoreE, I, location, Val, false);
3800}
3801
3803 const Expr *NodeEx,
3804 const Expr *BoundEx,
3807 SVal location,
3810 assert((location) && "location cannot be a NonLoc.");
3811 assert(NodeEx);
3812 assert(BoundEx);
3813
3815 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, true);
3816 if (Tmp.empty())
3817 return;
3818
3821 return;
3822
3823
3824 for (const auto I : Tmp) {
3825 state = I->getState();
3827
3829 if (location.isValid()) {
3830 if (LoadTy.isNull())
3831 LoadTy = BoundEx->getType();
3832 V = state->getSVal(location.castAs<Loc>(), LoadTy);
3833 }
3834
3835 Bldr.generateNode(NodeEx, I, state->BindExpr(BoundEx, LCtx, V), tag,
3837 }
3838}
3839
3841 const Stmt *NodeEx,
3842 const Stmt *BoundEx,
3845 SVal location,
3846 bool isLoad) {
3848
3850 return;
3851 }
3852
3854 BldrTop.takeNodes(Pred);
3856 if (Pred->getState() != state) {
3857
3858
3859
3860
3861
3862
3863
3864
3865
3867 Bldr.generateNode(NodeEx, Pred, state, &tag);
3868 }
3871 NodeEx, BoundEx, *this);
3872 BldrTop.addNodes(Tmp);
3873}
3874
3875std::pair<const ProgramPointTag *, const ProgramPointTag *>
3878 FalseTag(TagProviderName, "Eagerly Assume False");
3879
3880 return std::make_pair(&TrueTag, &FalseTag);
3881}
3882
3883
3884
3885
3887 const Expr *)
3888
3891 const Expr *Ex) {
3893
3895
3896
3897
3900 continue;
3901 }
3902
3904 State = State->set(nullptr);
3906 std::optionalnonloc::SymbolVal SEV = V.getAs<nonloc::SymbolVal>();
3907 if (SEV && SEV->isExpression()) {
3909
3910 auto [StateTrue, StateFalse] = State->assume(*SEV);
3911
3912 if (StateTrue && StateFalse) {
3913 StateTrue = StateTrue->set(Ex);
3914 StateFalse = StateFalse->set(Ex);
3915 }
3916
3917
3918 if (StateTrue) {
3920 StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
3921 Bldr.generateNode(Ex, Pred, StateTrue, TrueTag);
3922 }
3923
3924
3925 if (StateFalse) {
3927 StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
3928 Bldr.generateNode(Ex, Pred, StateFalse, FalseTag);
3929 }
3930 }
3931 }
3932}
3933
3935 const Expr *Ex) const {
3936 return Ex && State->get() == Ex;
3937}
3938
3942
3943
3944
3945
3946
3947
3948
3950
3953 assert((X));
3954
3955 if (std::optional LV = X.getAs<Loc>())
3957 currBldrCtx->blockCount(),
3959 true);
3960 }
3961
3962
3965
3966 if (std::optional LV = X.getAs<Loc>())
3968 currBldrCtx->blockCount(),
3970 true);
3971 }
3972
3974}
3975
3981
3982
3983
3984
3985
3986namespace llvm {
3987
3988template<>
3991
3995
3997 for (const auto &Report : Class.getReports()) {
3998 const auto *PR = dyn_cast(Report.get());
3999 if (!PR)
4000 continue;
4001 const ExplodedNode *EN = PR->getErrorNode();
4004 return true;
4005 }
4006 }
4007 return false;
4008 }
4009
4010
4011
4012
4013
4016 llvm::function_ref<void(const ExplodedNode *)> PreCallback,
4017 llvm::function_ref<void(const ExplodedNode *)> PostCallback,
4018 llvm::function_ref<bool(const ExplodedNode *)> Stop) {
4019 while (true) {
4020 PreCallback(N);
4021 if (Stop(N))
4022 return true;
4023
4025 break;
4026 PostCallback(N);
4027
4029 }
4030 return false;
4031 }
4032
4036
4038 std::string Buf;
4039 llvm::raw_string_ostream Out(Buf);
4040
4041 const bool IsDot = true;
4042 const unsigned int Space = 1;
4044
4045 Out << "{ \"state_id\": " << State->getID()
4046 << ",\\l";
4047
4048 Indent(Out, Space, IsDot) << "\"program_points\": [\\l";
4049
4050
4052 N,
4054 Indent(Out, Space + 1, IsDot) << "{ ";
4056 Out << ", \"tag\": ";
4058 Out << '\"' << Tag->getDebugTag() << '\"';
4059 else
4060 Out << "null";
4061 Out << ", \"node_id\": " << OtherNode->getID() <<
4062 ", \"is_sink\": " << OtherNode->isSink() <<
4063 ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
4064 },
4065
4066 [&](const ExplodedNode *) { Out << ",\\l"; },
4067 [&](const ExplodedNode *) { return false; });
4068
4069 Out << "\\l";
4070 Indent(Out, Space, IsDot) << "],\\l";
4071
4073
4074 Out << "\\l}\\l";
4075 return Buf;
4076 }
4077};
4078
4079}
4080
4082 std::string Filename = DumpGraph(trim);
4083 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
4084}
4085
4087 std::string Filename = DumpGraph(Nodes);
4088 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
4089}
4090
4092 if (trim) {
4093 std::vector<const ExplodedNode *> Src;
4094
4095
4096 for (const auto &Class : BR.equivalenceClasses()) {
4097 const auto *R =
4098 dyn_cast(Class.getReports()[0].get());
4099 if (!R)
4100 continue;
4101 const auto *N = const_cast<ExplodedNode *>(R->getErrorNode());
4102 Src.push_back(N);
4103 }
4104 return DumpGraph(Src, Filename);
4105 }
4106
4107 return llvm::WriteGraph(&G, "ExprEngine", false,
4108 "Exploded Graph",
4109 std::string(Filename));
4110}
4111
4113 StringRef Filename) {
4114 std::unique_ptr TrimmedG(G.trim(Nodes));
4115
4116 if (!TrimmedG) {
4117 llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
4118 return "";
4119 }
4120
4121 return llvm::WriteGraph(TrimmedG.get(), "TrimmedExprEngine",
4122 false,
4123 "Trimmed Exploded Graph",
4124 std::string(Filename));
4125}
4126
4128 static int index = 0;
4130}
4131
4132void ExprEngine::anchor() { }
4133
4138
4140
4144
4145 bool IsCompound = T->isArrayType() || T->isRecordType() ||
4146 T->isAnyComplexType() || T->isVectorType();
4147
4148 if (Args.size() > 1 || (E->isPRValue() && IsCompound && !IsTransparent)) {
4150 for (Expr *E : llvm::reverse(Args))
4152
4154 S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, ArgList)));
4155 } else {
4157 S->BindExpr(E, LC,
4158 Args.size() == 0
4160 : S->getSVal(Args.front(), LC)));
4161 }
4162}
Defines the clang::ASTContext interface.
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
#define STAT_COUNTER(VARNAME, DESC)
Defines the clang::Expr interface and subclasses for C++ expressions.
static const Stmt * getRightmostLeaf(const Stmt *Condition)
Definition ExprEngine.cpp:2696
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...
Definition ExprEngine.cpp:2658
static void printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition ExprEngine.cpp:686
static void printIndicesOfElementsToConstructJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition ExprEngine.cpp:732
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.
Definition ExprEngine.cpp:911
static void printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition ExprEngine.cpp:855
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S, const ExplodedNode *Pred, const LocationContext *LC)
Definition ExprEngine.cpp:1003
static const Stmt * ResolveCondition(const Stmt *Condition, const CFGBlock *B)
Definition ExprEngine.cpp:2722
REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction, ObjectsUnderConstructionMap) typedef llvm REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct, IndexOfElementToConstructMap) typedef llvm typedef llvm::ImmutableMap< const LocationContext *, unsigned > PendingArrayDestructionMap
Definition ExprEngine.cpp:200
static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
Definition ExprEngine.cpp:794
llvm::ImmutableMap< ConstructedObjectKey, SVal > ObjectsUnderConstructionMap
Definition ExprEngine.cpp:187
static const LocationContext * getInlinedLocationContext(ExplodedNode *Node, ExplodedGraph &G)
Return the innermost location context which is inlined at Node, unless it's the top-level (entry poin...
Definition ExprEngine.cpp:2541
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.
Definition ExprEngine.cpp:2784
std::pair< const ObjCForCollectionStmt *, const LocationContext * > ObjCForLctxPair
Definition ExprEngine.cpp:2753
TokenType getType() const
Returns the token's type, e.g.
FormatToken * Next
The next token in the unwrapped line.
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 various enumerations that describe declaration and type specifiers.
Defines the Objective-C statement AST node classes.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
const clang::PrintingPolicy & getPrintingPolicy() const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
ParentMap & getParentMap()
ASTContext & getASTContext() const
Stores options for the analyzer from the command line.
AnalysisPurgeMode AnalysisPurgeOpt
Represents a loop initializing the elements of an array.
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Expr * getSubExpr() const
Get the initializer to use for each array element.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
static unsigned getNumSubExprs(AtomicOp Op)
Determine the number of arguments the specified atomic builtin should have.
const CFGBlock * getPreviousBlock() const
const CFGBlock * getBlock() const
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
const VarDecl * getVarDecl() const
const Stmt * getTriggerStmt() const
Represents C++ object destructor implicitly generated for base object in destructor.
const CXXBaseSpecifier * getBaseSpecifier() const
Represents a single basic block in a source-level CFG.
CFGTerminator getTerminator() const
Stmt * getTerminatorStmt()
unsigned getBlockID() const
Represents C++ object destructor generated from a call to delete.
const CXXDeleteExpr * getDeleteExpr() const
Represents a top-level expression in a basic block.
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
Represents C++ object destructor implicitly generated by compiler on various occasions.
const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const
Represents C++ base or member initializer from constructor's initialization list.
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
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
FieldDecl * getAnyMember() const
IndirectFieldDecl * getIndirectMember() const
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Represents a delete expression for memory deallocation and destructor calls, e.g.
SourceLocation getBeginLoc() const
QualType getDestroyedType() const
Retrieve the type being destroyed.
Represents a C++ destructor within a class.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Represents a list-initialization with parenthesis.
MutableArrayRef< Expr * > getInitExprs()
Represents a C++ struct/union/class.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Represents a point when we begin processing an inlined call.
CaseStmt - Represent a case statement.
Represents a single point (AST node) in the program that requires attention during construction of an...
unsigned getIndex() const
If a single trigger statement triggers multiple constructors, they are usually being enumerated.
const CXXCtorInitializer * getCXXCtorInitializer() const
The construction site is not necessarily a statement.
@ TemporaryDestructorKind
const Stmt * getStmtOrNull() const
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
const Decl * getSingleDecl() const
Decl - This represents one declaration (or definition), e.g.
This is a meta program point, which should be skipped by all the diagnostic reasoning etc.
This represents one expression.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * 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.
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()
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.
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type.
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.
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 (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.
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.
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 isEnumeralType() 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)
BranchNodeBuilder is responsible for constructing the nodes corresponding to the two branches of the ...
ExplodedNode * generateNode(ProgramStateRef State, bool branch, ExplodedNode *Pred)
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.
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 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.
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 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.
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 * 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...
ExplodedNode * getRoot() const
Get the root node of the graph.
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.
Definition ExprEngine.cpp:3033
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.
Definition ExprEngine.cpp:3446
void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
Definition ExprEngine.cpp:3187
void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred)
Definition ExprEngine.cpp:1166
void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void ProcessTemporaryDtor(const CFGTemporaryDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Definition ExprEngine.cpp:1570
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.
Definition ExprEngine.cpp:3023
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.
Definition ExprEngine.cpp:1029
BasicValueFactory & getBasicVals()
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 evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex)
evalEagerlyAssumeBifurcation - Given the nodes in 'Src', eagerly assume concrete boolean values for '...
void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for ObjCAtSynchronizedStmts.
void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitReturnStmt - Transfer function logic for return statements.
SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, SVal LHS, SVal RHS, QualType T)
void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
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)
Definition ExprEngine.cpp:1296
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.
Definition ExprEngine.cpp:245
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)
Definition ExprEngine.cpp:2773
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.
Definition ExprEngine.cpp:3976
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,...
Definition ExprEngine.cpp:604
std::string DumpGraph(bool trim=false, StringRef Filename="")
Dump graph to the specified filename.
Definition ExprEngine.cpp:4091
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.
Definition ExprEngine.cpp:940
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.
Definition ExprEngine.cpp:3628
const LocationContext * getRootLocationContext() const
static ProgramStateRef removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
Definition ExprEngine.cpp:2766
ProgramStateRef processAssume(ProgramStateRef state, SVal cond, bool assumption)
evalAssume - Callback function invoked by the ConstraintManager when making assumptions about state v...
Definition ExprEngine.cpp:668
AnalysisDeclContextManager & getAnalysisDeclContextManager()
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.
Definition ExprEngine.cpp:514
void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBlockExpr - Transfer function logic for BlockExprs.
void ProcessBaseDtor(const CFGBaseDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Definition ExprEngine.cpp:1491
static std::pair< const ProgramPointTag *, const ProgramPointTag * > getEagerlyAssumeBifurcationTags()
Definition ExprEngine.cpp:3876
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.
void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGCCAsmStmt - Transfer function logic for inline asm.
Definition ExprEngine.cpp:3939
BugReporter & getBugReporter()
void processCFGBlockEntrance(const BlockEdge &L, NodeBuilderWithSinks &nodeBuilder, ExplodedNode *Pred)
Called by CoreEngine when processing the entrance of a CFGBlock.
Definition ExprEngine.cpp:2554
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.
Definition ExprEngine.cpp:674
void ProcessStmt(const Stmt *S, ExplodedNode *Pred)
Definition ExprEngine.cpp:1118
ConstCFGElementRef getCFGElementRef() const
ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS, InliningModes HowToInlineIn)
Definition ExprEngine.cpp:222
void ViewGraph(bool trim=false)
Visualize the ExplodedGraph created by executing the simulation.
Definition ExprEngine.cpp:4081
static std::optional< unsigned > getPendingArrayDestruction(ProgramStateRef State, const LocationContext *LCtx)
Retreives which element is being destructed in a non-POD type array.
Definition ExprEngine.cpp:533
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.
Definition ExprEngine.cpp:3679
static const ProgramPointTag * cleanupNodeTag()
A tag to track convenience transitions, which can be removed at cleanup.
Definition ExprEngine.cpp:1113
void processCFGElement(const CFGElement E, ExplodedNode *Pred, unsigned StmtIdx, NodeBuilderContext *Ctx)
processCFGElement - Called by CoreEngine.
Definition ExprEngine.cpp:967
void processStaticInitializer(const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
void ConstructInitList(const Expr *Source, ArrayRef< Expr * > Args, bool IsTransparent, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Definition ExprEngine.cpp:4134
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.
Definition ExprEngine.cpp:1689
void processBranch(const Stmt *Condition, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF, std::optional< unsigned > IterationsCompletedInLoop)
ProcessBranch - Called by CoreEngine.
Definition ExprEngine.cpp:2830
void ProcessLoopExit(const Stmt *S, ExplodedNode *Pred)
Definition ExprEngine.cpp:1148
void processSwitch(SwitchNodeBuilder &builder)
ProcessSwitch - Called by CoreEngine.
Definition ExprEngine.cpp:3104
void processEndWorklist()
Called by CoreEngine when the analysis worklist has terminated.
Definition ExprEngine.cpp:961
CheckerManager & getCheckerManager() const
SymbolManager & getSymbolManager()
void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAtomicExpr - Transfer function for builtin atomic expressions.
Definition ExprEngine.cpp:3585
MemRegionManager & getRegionManager()
void ProcessMemberDtor(const CFGMemberDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Definition ExprEngine.cpp:1511
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.
Definition ExprEngine.cpp:3497
void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
bool didEagerlyAssumeBifurcateAt(ProgramStateRef State, const Expr *Ex) const
Definition ExprEngine.cpp:3934
ConstraintManager & getConstraintManager()
void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, NodeBuilderContext &BldCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
Definition ExprEngine.cpp:1646
void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Definition ExprEngine.cpp:1343
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.
Definition ExprEngine.cpp:3802
void removeDeadOnEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Remove dead bindings/symbols before exiting a function.
void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Visit - Transfer function logic for all statements.
Definition ExprEngine.cpp:1716
AnalysisManager & getAnalysisManager()
ExplodedGraph & getGraph()
void runCheckersForBlockEntrance(const NodeBuilderContext &BldCtx, const BlockEntrance &Entrance, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Definition ExprEngine.cpp:2636
void ProcessDeleteDtor(const CFGDeleteDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Definition ExprEngine.cpp:1415
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.
Definition ExprEngine.cpp:3348
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.
Definition ExprEngine.cpp:3779
void VisitAttributedStmt(const AttributedStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAttributedStmt - Transfer function logic for AttributedStmt.
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, ExplodedNodeSet &PreVisit, ExplodedNodeSet &Dst)
Definition ExprEngine.cpp:1662
void processIndirectGoto(IndirectGotoNodeBuilder &builder)
processIndirectGoto - Called by CoreEngine.
Definition ExprEngine.cpp:2982
const NodeBuilderContext & getBuilderContext()
static ProgramStateRef setWhetherHasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC, bool HasMoreIteraton)
Note whether this loop has any more iterations to model. These methods.
Definition ExprEngine.cpp:2758
static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives the size of the array in the pending ArrayInitLoopExpr.
Definition ExprEngine.cpp:487
void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred)
Definition ExprEngine.cpp:1323
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)
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...
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.
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.
Information about invalidation for a particular region/symbol.
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the 'this' object reference.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const LocationContext *LCtx, 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.
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.
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.
void markAllDynamicExtentLive(ProgramStateRef State, SymbolReaper &SymReaper)
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, const LocationContext *LCtx, unsigned BlockCount, ConstCFGElementRef Elem)
Get the states that result from widening the 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)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
StorageDuration
The storage duration for an object (per C++ [basic.stc]).
@ SD_Thread
Thread storage duration.
@ SD_Static
Static storage duration.
@ SD_FullExpression
Full-expression storage duration (for temporaries).
@ Result
The result type of a method or function.
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 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...
Traits for storing the call processing policy inside GDM.
DOTGraphTraits(bool isSimple=false)
Definition ExprEngine.cpp:3990
static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G)
Definition ExprEngine.cpp:4037
static bool nodeHasBugReport(const ExplodedNode *N)
Definition ExprEngine.cpp:3992
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.
Definition ExprEngine.cpp:4014
static bool isNodeHidden(const ExplodedNode *N, const ExplodedGraph *G)
Definition ExprEngine.cpp:4033