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/ADT/Statistic.h"
71#include "llvm/Support/Casting.h"
72#include "llvm/Support/Compiler.h"
73#include "llvm/Support/DOTGraphTraits.h"
74#include "llvm/Support/ErrorHandling.h"
75#include "llvm/Support/GraphWriter.h"
76#include "llvm/Support/SaveAndRestore.h"
77#include "llvm/Support/raw_ostream.h"
78#include
79#include
80#include
81#include
82#include
83#include
84#include
85#include
86
87using namespace clang;
88using namespace ento;
89
90#define DEBUG_TYPE "ExprEngine"
91
93 "The # of times RemoveDeadBindings is called");
95 "The # of aborted paths due to reaching the maximum block count in "
96 "a top level function");
97STATISTIC(NumMaxBlockCountReachedInInlined,
98 "The # of aborted paths due to reaching the maximum block count in "
99 "an inlined function");
101 "The # of times we re-evaluated a call without inlining");
102
103
104
105
106
107namespace {
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122class ConstructedObjectKey {
123 using ConstructedObjectKeyImpl =
124 std::pair<ConstructionContextItem, const LocationContext *>;
125 const ConstructedObjectKeyImpl Impl;
126
127public:
130 : Impl(Item, LC) {}
131
133 const LocationContext *getLocationContext() const { return Impl.second; }
134
136 return getLocationContext()->getDecl()->getASTContext();
137 }
138
139 void printJson(llvm::raw_ostream &Out, PrinterHelper *Helper,
141 const Stmt *S = getItem().getStmtOrNull();
143 if (!S)
144 I = getItem().getCXXCtorInitializer();
145
146 if (S)
147 Out << "\"stmt_id\": " << S->getID(getASTContext());
148 else
149 Out << "\"init_id\": " << I->getID(getASTContext());
150
151
152 Out << ", \"kind\": \"" << getItem().getKindAsString()
153 << "\", \"argument_index\": ";
154
156 Out << getItem().getIndex();
157 else
158 Out << "null";
159
160
161 Out << ", \"pretty\": ";
162
163 if (S) {
164 S->printJson(Out, Helper, PP, true);
165 } else {
167 }
168 }
169
170 void Profile(llvm::FoldingSetNodeID &ID) const {
171 ID.Add(Impl.first);
172 ID.AddPointer(Impl.second);
173 }
174
175 bool operator==(const ConstructedObjectKey &RHS) const {
176 return Impl == RHS.Impl;
177 }
178
179 bool operator<(const ConstructedObjectKey &RHS) const {
180 return Impl < RHS.Impl;
181 }
182};
183}
184
185typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
189
190
191
192
193
194
195
196typedef llvm::ImmutableMap<
197 std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>
198 IndexOfElementToConstructMap;
200 IndexOfElementToConstructMap)
201
202
203
204
205typedef llvm::ImmutableMap<
206 std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>
207 PendingInitLoopMap;
209
210typedef llvm::ImmutableMap<const LocationContext *, unsigned>
214
215
216
217
218
219static const char* TagProviderName = "ExprEngine";
220
224 : CTU(CTU), IsCTUEnabled(mgr.getAnalyzerOptions().IsNaiveCTUEnabled),
225 AMgr(mgr), AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
226 Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.getGraph()),
227 StateMgr(getContext(), mgr.getStoreManagerCreator(),
228 mgr.getConstraintManagerCreator(), G.getAllocator(), this),
229 SymMgr(StateMgr.getSymbolManager()), MRMgr(StateMgr.getRegionManager()),
230 svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
231 BR(mgr, *this), VisitedCallees(VisitedCalleesIn),
232 HowToInline(HowToInlineIn) {
233 unsigned TrimInterval = mgr.options.GraphTrimInterval;
234 if (TrimInterval != 0) {
235
237 }
238}
239
240
241
242
243
247
248
249
250
251 do {
252 if (const auto *FD = dyn_cast(D)) {
253
254
256 if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))
257 break;
258
259 const ParmVarDecl *PD = FD->getParamDecl(0);
261 const auto *BT = dyn_cast(T);
262 if (!BT || !BT->isInteger())
263 break;
264
265 const MemRegion *R = state->getRegion(PD, InitLoc);
266 if (!R)
267 break;
268
270 SVal Constraint_untested = evalBinOp(state, BO_GT, V,
273
274 std::optional Constraint =
276
277 if (!Constraint)
278 break;
279
280 if (ProgramStateRef newState = state->assume(*Constraint, true))
281 state = newState;
282 }
283 break;
284 }
285 while (false);
286
287 if (const auto *MD = dyn_cast(D)) {
288
289
291 const MemRegion *R = state->getRegion(SelfD, InitLoc);
293
294 if (std::optional LV = V.getAs<Loc>()) {
295
296 state = state->assume(*LV, true);
297 assert(state && "'self' cannot be null");
298 }
299 }
300
301 if (const auto *MD = dyn_cast(D)) {
302 if (MD->isImplicitObjectMemberFunction()) {
303
304
305
307 if (SFC->getParent() == nullptr) {
309 SVal V = state->getSVal(L);
310 if (std::optional LV = V.getAs<Loc>()) {
311 state = state->assume(*LV, true);
312 assert(state && "'this' cannot be null");
313 }
314 }
315 }
316 }
317
318 return state;
319}
320
321ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
324 const SubRegion **OutRegionWithAdjustments) {
325
326
327
328
329
330 SVal InitValWithAdjustments = State->getSVal(InitWithAdjustments, LC);
332
333
334 if (!isa(InitValWithAdjustments)) {
335 if (OutRegionWithAdjustments)
336 *OutRegionWithAdjustments = nullptr;
337 return State;
338 }
339 Result = InitWithAdjustments;
340 } else {
341
342
343 assert(!isa(InitValWithAdjustments) ||
345 Result->getType()->isMemberPointerType());
346 }
347
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
375
377 CommaLHSs, Adjustments);
378
379
380
381
382
383
385 if (const auto *MT = dyn_cast(Result)) {
387 State = finishObjectConstruction(State, MT, LC);
388 State = State->BindExpr(Result, LC, *V);
389 return State;
390 } else if (const ValueDecl *VD = MT->getExtendingDecl()) {
393
394
397 } else {
399 }
400 } else {
403 }
404 } else {
406 }
407
409 SVal BaseReg = Reg;
410
411
413 switch (Adj.Kind) {
415 Reg = StoreMgr.evalDerivedToBase(Reg, Adj.DerivedToBase.BasePath);
416 break;
419 break;
421
422 State = State->invalidateRegions(Reg, InitWithAdjustments,
424 nullptr, nullptr, nullptr);
425 return State;
426 }
427 }
428
429
430
431
432
433
434
435
436
437 SVal InitVal = State->getSVal(Init, LC);
441 State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
442
443
444
445 if (InitValWithAdjustments.isUnknown()) {
446
447
451 }
452 State =
453 State->bindLoc(Reg.castAs<Loc>(), InitValWithAdjustments, LC, false);
454 } else {
455 State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
456 }
457
458
459
460
461 if (Result->isGLValue()) {
462 State = State->BindExpr(Result, LC, Reg);
463 } else {
464 State = State->BindExpr(Result, LC, InitValWithAdjustments);
465 }
466
467
469
470 if (OutRegionWithAdjustments)
471 *OutRegionWithAdjustments = cast(Reg.getAsRegion());
472 return State;
473}
474
479
480 assert(!State->contains(Key) || Idx > 0);
481
482 return State->set(Key, Idx);
483}
484
485std::optional
488 const unsigned *V = State->get({E, LCtx->getStackFrame()});
489 return V ? std::make_optional(*V) : std::nullopt;
490}
491
496
497 assert(E && State->contains(Key));
498 return State->remove(Key);
499}
500
504 unsigned Size) {
506
507 assert(!State->contains(Key) && Size > 0);
508
509 return State->set(Key, Size);
510}
511
512std::optional
516 const unsigned *V =
517 State->get({E, LCtx->getStackFrame()});
518 return V ? std::make_optional(*V) : std::nullopt;
519}
520
522ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State,
526
527 assert(E && State->contains(Key));
528 return State->remove(Key);
529}
530
531std::optional
534 assert(LCtx && "LocationContext shouldn't be null!");
535
536 const unsigned *V =
537 State->get(LCtx->getStackFrame());
538 return V ? std::make_optional(*V) : std::nullopt;
539}
540
543 assert(LCtx && "LocationContext shouldn't be null!");
544
546
547 return State->set(Key, Idx);
548}
549
551ExprEngine::removePendingArrayDestruction(ProgramStateRef State,
553 assert(LCtx && "LocationContext shouldn't be null!");
554
556
557 assert(LCtx && State->contains(Key));
558 return State->remove(Key);
559}
560
562ExprEngine::addObjectUnderConstruction(ProgramStateRef State,
565 ConstructedObjectKey Key(Item, LC->getStackFrame());
566
568
569 if (auto DS = dyn_cast_or_null(Item.getStmtOrNull())) {
570 if (auto VD = dyn_cast_or_null(DS->getSingleDecl()))
571 Init = VD->getInit();
572 }
573
574 if (auto LE = dyn_cast_or_null(Item.getStmtOrNull()))
575 Init = *(LE->capture_init_begin() + Item.getIndex());
576
579
580
581
582
583 if (const auto *AILE = dyn_cast_or_null(Init))
585
586
587
588
589
590
591
592 assert((!State->get(Key) ||
593 Key.getItem().getKind() ==
595 State->contains(
596 {dyn_cast_or_null(Init), LC})) &&
597 "The object is already marked as `UnderConstruction`, when it's not "
598 "supposed to!");
599 return State->set(Key, V);
600}
601
602std::optional
606 ConstructedObjectKey Key(Item, LC->getStackFrame());
607 const SVal *V = State->get(Key);
608 return V ? std::make_optional(*V) : std::nullopt;
609}
610
612ExprEngine::finishObjectConstruction(ProgramStateRef State,
615 ConstructedObjectKey Key(Item, LC->getStackFrame());
616 assert(State->contains(Key));
617 return State->remove(Key);
618}
619
623 ConstructedObjectKey Key({BTE, true}, LC);
624
625
626 return State->set(Key, UnknownVal());
627}
628
630ExprEngine::cleanupElidedDestructor(ProgramStateRef State,
633 ConstructedObjectKey Key({BTE, true}, LC);
634 assert(State->contains(Key));
635 return State->remove(Key);
636}
637
638bool ExprEngine::isDestructorElided(ProgramStateRef State,
641 ConstructedObjectKey Key({BTE, true}, LC);
642 return State->contains(Key);
643}
644
645bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
649 while (LC != ToLC) {
650 assert(LC && "ToLC must be a parent of FromLC!");
651 for (auto I : State->get())
652 if (I.first.getLocationContext() == LC)
653 return false;
654
656 }
657 return true;
658}
659
660
661
662
663
664
665
666
668 SVal cond, bool assumption) {
670}
671
680 Explicits, Regions,
682}
683
684static void
687 unsigned int Space = 0, bool IsDot = false) {
690
691 ++Space;
692 bool HasItem = false;
693
694
695 const ConstructedObjectKey *LastKey = nullptr;
696 for (const auto &I : State->get()) {
697 const ConstructedObjectKey &Key = I.first;
698 if (Key.getLocationContext() != LCtx)
699 continue;
700
701 if (!HasItem) {
702 Out << '[' << NL;
703 HasItem = true;
704 }
705
706 LastKey = &Key;
707 }
708
709 for (const auto &I : State->get()) {
710 const ConstructedObjectKey &Key = I.first;
712 if (Key.getLocationContext() != LCtx)
713 continue;
714
715 Indent(Out, Space, IsDot) << "{ ";
716 Key.printJson(Out, nullptr, PP);
717 Out << ", \"value\": \"" << Value << "\" }";
718
719 if (&Key != LastKey)
720 Out << ',';
721 Out << NL;
722 }
723
724 if (HasItem)
725 Indent(Out, --Space, IsDot) << ']';
726 else {
727 Out << "null ";
728 }
729}
730
733 const LocationContext *LCtx, unsigned int Space = 0, bool IsDot = false) {
734 using KeyT = std::pair<const Expr *, const LocationContext *>;
735
738
739 ++Space;
740 bool HasItem = false;
741
742
743 KeyT LastKey;
744 for (const auto &I : State->get()) {
745 const KeyT &Key = I.first;
746 if (Key.second != LCtx)
747 continue;
748
749 if (!HasItem) {
750 Out << '[' << NL;
751 HasItem = true;
752 }
753
754 LastKey = Key;
755 }
756
757 for (const auto &I : State->get()) {
758 const KeyT &Key = I.first;
759 unsigned Value = I.second;
760 if (Key.second != LCtx)
761 continue;
762
763 Indent(Out, Space, IsDot) << "{ ";
764
765
766 const Expr *E = Key.first;
767 Out << "\"stmt_id\": " << E->getID(Context);
768
769
770 Out << ", \"kind\": null";
771
772
773 Out << ", \"pretty\": ";
777 Out << "'\"";
778
779 Out << ", \"value\": \"Current index: " << Value - 1 << "\" }";
780
781 if (Key != LastKey)
782 Out << ',';
783 Out << NL;
784 }
785
786 if (HasItem)
787 Indent(Out, --Space, IsDot) << ']';
788 else {
789 Out << "null ";
790 }
791}
792
794 const char *NL,
796 unsigned int Space = 0,
797 bool IsDot = false) {
798 using KeyT = std::pair<const CXXConstructExpr *, const LocationContext *>;
799
802
803 ++Space;
804 bool HasItem = false;
805
806
807 KeyT LastKey;
808 for (const auto &I : State->get()) {
809 const KeyT &Key = I.first;
810 if (Key.second != LCtx)
811 continue;
812
813 if (!HasItem) {
814 Out << '[' << NL;
815 HasItem = true;
816 }
817
818 LastKey = Key;
819 }
820
821 for (const auto &I : State->get()) {
822 const KeyT &Key = I.first;
823 unsigned Value = I.second;
824 if (Key.second != LCtx)
825 continue;
826
827 Indent(Out, Space, IsDot) << "{ ";
828
830 Out << "\"stmt_id\": " << E->getID(Context);
831
832 Out << ", \"kind\": null";
833 Out << ", \"pretty\": ";
837 Out << "'\"";
838
839 Out << ", \"value\": \"Flattened size: " << Value << "\"}";
840
841 if (Key != LastKey)
842 Out << ',';
843 Out << NL;
844 }
845
846 if (HasItem)
847 Indent(Out, --Space, IsDot) << ']';
848 else {
849 Out << "null ";
850 }
851}
852
853static void
856 unsigned int Space = 0, bool IsDot = false) {
858
859 ++Space;
860 bool HasItem = false;
861
862
863 KeyT LastKey = nullptr;
864 for (const auto &I : State->get()) {
865 const KeyT &Key = I.first;
866 if (Key != LCtx)
867 continue;
868
869 if (!HasItem) {
870 Out << '[' << NL;
871 HasItem = true;
872 }
873
874 LastKey = Key;
875 }
876
877 for (const auto &I : State->get()) {
878 const KeyT &Key = I.first;
879 if (Key != LCtx)
880 continue;
881
882 Indent(Out, Space, IsDot) << "{ ";
883
884 Out << "\"stmt_id\": null";
885 Out << ", \"kind\": null";
886 Out << ", \"pretty\": \"Current index: \"";
887 Out << ", \"value\": \"" << I.second << "\" }";
888
889 if (Key != LastKey)
890 Out << ',';
891 Out << NL;
892 }
893
894 if (HasItem)
895 Indent(Out, --Space, IsDot) << ']';
896 else {
897 Out << "null ";
898 }
899}
900
901
902
903
904
905
906
907
908
909template <typename Trait, typename Printer, typename... Args>
912 const char *NL, unsigned int Space, bool IsDot,
913 const char *jsonPropertyName, Printer printer, Args &&...args) {
914
915 using RequiredType =
918
919
920
921 static_assert(std::is_function_v<std::remove_pointer_t>,
922 "Printer is not a function!");
923 static_assert(std::is_convertible_v<Printer, RequiredType>,
924 "Printer doesn't have the required type!");
925
926 if (LCtx && !State->get().isEmpty()) {
927 Indent(Out, Space, IsDot) << '\"' << jsonPropertyName << "\": ";
928 ++Space;
929 Out << '[' << NL;
931 printer(Out, State, NL, LC, Space, IsDot, std::forward(args)...);
932 });
933
934 --Space;
935 Indent(Out, Space, IsDot) << "]," << NL;
936 }
937}
938
941 unsigned int Space, bool IsDot) const {
942
943 printStateTraitWithLocationContextJson(
944 Out, State, LCtx, NL, Space, IsDot, "constructing_objects",
946 printStateTraitWithLocationContextJson(
947 Out, State, LCtx, NL, Space, IsDot, "index_of_element",
949 printStateTraitWithLocationContextJson(
950 Out, State, LCtx, NL, Space, IsDot, "pending_init_loops",
952 printStateTraitWithLocationContextJson(
953 Out, State, LCtx, NL, Space, IsDot, "pending_destructors",
955
957 IsDot);
958}
959
961
964}
965
969 currStmtIdx = StmtIdx;
970 currBldrCtx = Ctx;
971
972 switch (E.getKind()) {
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
1016 if (!isa(S))
1017 return true;
1018
1019
1021 return true;
1022
1023
1024
1027}
1028
1030 const Stmt *ReferenceStmt,
1032 const Stmt *DiagnosticStmt,
1035 ReferenceStmt == nullptr || isa(ReferenceStmt))
1036 && "PostStmt is not generally supported by the SymbolReaper yet");
1037 assert(LC && "Must pass the current (or expiring) LocationContext");
1038
1039 if (!DiagnosticStmt) {
1040 DiagnosticStmt = ReferenceStmt;
1041 assert(DiagnosticStmt && "Required for clearing a LocationContext");
1042 }
1043
1044 NumRemoveDeadBindings++;
1046
1047
1048
1049
1050 if (!ReferenceStmt) {
1052 "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");
1054 }
1055
1058
1059 for (auto I : CleanedState->get()) {
1060 if (SymbolRef Sym = I.second.getAsSymbol())
1062 if (const MemRegion *MR = I.second.getAsRegion())
1064 }
1065
1067
1068
1069
1070
1072 CleanedState, SFC, SymReaper);
1073
1074
1075
1076
1079 DiagnosticStmt, *this, K);
1080
1081
1082
1083
1085 for (const auto I : CheckedSet) {
1087
1088
1089 CheckerState =
1091
1093 "Checkers are not allowed to modify the Environment as a part of "
1094 "checkDeadSymbols processing.");
1096 "Checkers are not allowed to modify the Store as a part of "
1097 "checkDeadSymbols processing.");
1098
1099
1100
1104 }
1105}
1106
1109 return &cleanupTag;
1110}
1111
1113
1115
1118 "Error evaluating statement");
1119
1120
1124 removeDead(Pred, CleanedStates, currStmt,
1126 } else
1127 CleanedStates.Add(Pred);
1128
1129
1131 for (const auto I : CleanedStates) {
1133
1134 Visit(currStmt, I, DstI);
1136 }
1137
1138
1139 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1140}
1141
1144 S->getBeginLoc(),
1145 "Error evaluating end of the loop");
1147 Dst.Add(Pred);
1148 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1150
1151 if(AMgr.options.ShouldUnrollLoops)
1153
1156
1157 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1158}
1159
1165
1168 "Error evaluating initializer");
1169
1170
1171 const auto *stackFrame = cast(Pred->getLocationContext());
1172 const auto *decl = cast(stackFrame->getDecl());
1173
1175 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));
1176
1178 SVal FieldLoc;
1179
1180
1182
1183
1185
1186
1187 State = finishObjectConstruction(State, BMI, LC);
1188 NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
1189 PostStore PS(Init, LC, nullptr, nullptr);
1191 } else {
1196 } else {
1198 FieldLoc = State->getLValue(BMI->getMember(), thisVal);
1199 }
1200
1201 SVal InitVal;
1202 if (Init->getType()->isArrayType()) {
1203
1204
1206 while ((ASE = dyn_cast(Init)))
1208
1209 InitVal = State->getSVal(Init, stackFrame);
1210
1211
1215 Field->getType(),
1217 }
1218 } else {
1219 InitVal = State->getSVal(BMI->getInit(), stackFrame);
1220 }
1221
1223 evalBind(Tmp, Init, Pred, FieldLoc, InitVal, true, &PP);
1224 }
1226
1227
1228
1231 SVal InitVal = State->getSVal(Init, stackFrame);
1232 evalBind(Tmp, Init, Pred, BaseLoc, InitVal, true);
1233 } else {
1236
1237 }
1238
1239
1240
1243 NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
1244 for (const auto I : Tmp) {
1247 }
1248
1249
1250 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1251}
1252
1253std::pair<ProgramStateRef, uint64_t>
1254ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,
1258 SVal *ElementCountVal) {
1259 assert(Region != nullptr && "Not-null region expected");
1260
1262 while (const auto *NTy = dyn_cast(Ty))
1263 Ty = NTy->getElementType().getDesugaredType(getContext());
1264
1266
1267 if (ElementCountVal)
1268 *ElementCountVal = ElementCount;
1269
1270
1271 unsigned Idx = 0;
1273 Idx = *OptionalIdx;
1274 } else {
1275
1276 if (!ElementCount.isConstant())
1277 return {State, 0};
1278
1279 Idx = ElementCount.getAsInteger()->getLimitedValue();
1280 }
1281
1282 if (Idx == 0)
1283 return {State, 0};
1284
1285 --Idx;
1286
1287 return {setPendingArrayDestruction(State, LCtx, Idx), Idx};
1288}
1289
1296 break;
1299 break;
1302 break;
1305 break;
1308 break;
1309 default:
1310 llvm_unreachable("Unexpected dtor kind.");
1311 }
1312
1313
1314 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1315}
1316
1322
1323
1324
1325 if (Opts.MayInlineCXXAllocator)
1327 else {
1328 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1330 PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx,
1333 }
1334 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
1335}
1336
1343
1346
1347 SVal dest = state->getLValue(varDecl, LCtx);
1349
1351 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
1352 if (!ValueRegion) {
1353
1354
1355
1356
1357 return;
1358 }
1360 varType = cast(Region)->getValueType();
1361 }
1362
1363 unsigned Idx = 0;
1364 if (isa(varType)) {
1365 SVal ElementCount;
1366 std::tie(state, Idx) = prepareStateForArrayDestruction(
1367 state, Region, varType, LCtx, &ElementCount);
1368
1370 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1371 assert(ArrayLength &&
1372 "An automatic dtor for a 0 length array shouldn't be triggered!");
1373
1374
1375 if (!ArrayLength) {
1377 "ExprEngine", "Skipping automatic 0 length array destruction, "
1378 "which shouldn't be in the CFG.");
1381 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1383 return;
1384 }
1385 }
1386 }
1387
1389 Region = makeElementRegion(state, loc::MemRegionVal(Region), varType,
1392
1394
1396 "Prepare for object destruction");
1398 &PT);
1400
1401 if (!Pred)
1402 return;
1404
1406 false, Pred, Dst, CallOpts);
1407}
1408
1417 SVal ArgVal = State->getSVal(Arg, LCtx);
1418
1419
1420
1421 if (State->isNull(ArgVal).isConstrainedTrue()) {
1425
1427 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1429 return;
1430 }
1431
1432 auto getDtorDecl = [](const QualType &DTy) {
1435 };
1436
1437 unsigned Idx = 0;
1440
1443
1445 DTy = AT->getElementType();
1446
1447 if (ArgR) {
1448 SVal ElementCount;
1449 std::tie(State, Idx) = prepareStateForArrayDestruction(
1450 State, ArgR, DTy, LCtx, &ElementCount);
1451
1452
1453
1455 ElementCount.getAsInteger()->getLimitedValue() == 0) {
1456
1458 "ExprEngine", "Skipping 0 length array delete destruction");
1461 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1463 return;
1464 }
1465
1466 ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
1467 .getAsRegion();
1468 }
1469 }
1470
1473 "Prepare for object destruction");
1477
1478 if (!Pred)
1479 return;
1481
1482 VisitCXXDestructor(DTy, ArgR, DE, false, Pred, Dst, CallOpts);
1483}
1484
1488
1489 const auto *CurDtor = cast(LCtx->getDecl());
1492 SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
1493
1494
1498 Base->isVirtual());
1499
1502 true, Pred, Dst, CallOpts);
1503}
1504
1507 const auto *DtorDecl = D.getDestructorDecl(getContext());
1512
1513 const auto *CurDtor = cast(LCtx->getDecl());
1514 Loc ThisStorageLoc =
1516 Loc ThisLoc = State->getSVal(ThisStorageLoc).castAs<Loc>();
1517 SVal FieldVal = State->getLValue(Member, ThisLoc);
1518
1519 unsigned Idx = 0;
1520 if (isa(T)) {
1521 SVal ElementCount;
1522 std::tie(State, Idx) = prepareStateForArrayDestruction(
1523 State, FieldVal.getAsRegion(), T, LCtx, &ElementCount);
1524
1526 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1527 assert(ArrayLength &&
1528 "A member dtor for a 0 length array shouldn't be triggered!");
1529
1530
1531 if (!ArrayLength) {
1533 "ExprEngine", "Skipping member 0 length array destruction, which "
1534 "shouldn't be in the CFG.");
1537 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1539 return;
1540 }
1541 }
1542 }
1543
1545 FieldVal =
1546 makeElementRegion(State, FieldVal, T, CallOpts.IsArrayCtorOrDtor, Idx);
1547
1549
1551 "Prepare for object destruction");
1553 &PT);
1555
1556 if (!Pred)
1557 return;
1559
1561 false, Pred, Dst, CallOpts);
1562}
1563
1571
1574
1575
1576
1577 State = finishObjectConstruction(State, D.getBindTemporaryExpr(),
1579 MR = V->getAsRegion();
1580 }
1581
1582
1583
1584 if (isDestructorElided(State, BTE, LC)) {
1585 State = cleanupElidedDestructor(State, BTE, LC);
1586 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1591 return;
1592 }
1593
1595 StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);
1596 StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
1597
1598 QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType();
1599
1600
1601 assert(CleanDtorState.size() <= 1);
1603 CleanDtorState.empty() ? Pred : *CleanDtorState.begin();
1604
1607 if (!MR) {
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1626 T = AT->getElementType();
1627
1628
1629
1630 }
1631 } else {
1632
1633
1634
1635 }
1637 false, CleanPred, Dst, CallOpts);
1638}
1639
1646 BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);
1650 TempDtorBuilder.generateNode(State, true, Pred);
1651 } else {
1652 TempDtorBuilder.generateNode(State, false, Pred);
1653 }
1654}
1655
1659
1660
1661
1662 if (().options.ShouldIncludeTemporaryDtorsInCFG) {
1663
1664
1665 Dst = PreVisit;
1666 return;
1667 }
1673
1674
1675
1676
1677 State = addObjectUnderConstruction(State, BTE, LC, UnknownVal());
1678 }
1680 }
1681}
1682
1687 class CollectReachableSymbolsCallback final : public SymbolVisitor {
1689
1690 public:
1691 explicit CollectReachableSymbolsCallback(InvalidatedSymbols &Symbols)
1692 : Symbols(Symbols) {}
1693
1695
1696 bool VisitSymbol(SymbolRef Sym) override {
1697 Symbols.insert(Sym);
1698 return true;
1699 }
1700 };
1702 CollectReachableSymbolsCallback CallBack(Symbols);
1704 State->scanReachableSymbols(V, CallBack);
1705
1707 State, CallBack.getSymbols(), Call, K, nullptr);
1708}
1709
1713 S->getBeginLoc(), "Error evaluating statement");
1716
1717 assert(!isa(S) || S == cast(S)->IgnoreParens());
1718
1719 switch (S->getStmtClass()) {
1720
1721 case Stmt::CXXDependentScopeMemberExprClass:
1722 case Stmt::CXXTryStmtClass:
1723 case Stmt::CXXTypeidExprClass:
1724 case Stmt::CXXUuidofExprClass:
1725 case Stmt::CXXFoldExprClass:
1726 case Stmt::MSPropertyRefExprClass:
1727 case Stmt::MSPropertySubscriptExprClass:
1728 case Stmt::CXXUnresolvedConstructExprClass:
1729 case Stmt::DependentScopeDeclRefExprClass:
1730 case Stmt::ArrayTypeTraitExprClass:
1731 case Stmt::ExpressionTraitExprClass:
1732 case Stmt::UnresolvedLookupExprClass:
1733 case Stmt::UnresolvedMemberExprClass:
1734 case Stmt::TypoExprClass:
1735 case Stmt::RecoveryExprClass:
1736 case Stmt::CXXNoexceptExprClass:
1737 case Stmt::PackExpansionExprClass:
1738 case Stmt::PackIndexingExprClass:
1739 case Stmt::SubstNonTypeTemplateParmPackExprClass:
1740 case Stmt::FunctionParmPackExprClass:
1741 case Stmt::CoroutineBodyStmtClass:
1742 case Stmt::CoawaitExprClass:
1743 case Stmt::DependentCoawaitExprClass:
1744 case Stmt::CoreturnStmtClass:
1745 case Stmt::CoyieldExprClass:
1746 case Stmt::SEHTryStmtClass:
1747 case Stmt::SEHExceptStmtClass:
1748 case Stmt::SEHLeaveStmtClass:
1749 case Stmt::SEHFinallyStmtClass:
1750 case Stmt::OMPCanonicalLoopClass:
1751 case Stmt::OMPParallelDirectiveClass:
1752 case Stmt::OMPSimdDirectiveClass:
1753 case Stmt::OMPForDirectiveClass:
1754 case Stmt::OMPForSimdDirectiveClass:
1755 case Stmt::OMPSectionsDirectiveClass:
1756 case Stmt::OMPSectionDirectiveClass:
1757 case Stmt::OMPScopeDirectiveClass:
1758 case Stmt::OMPSingleDirectiveClass:
1759 case Stmt::OMPMasterDirectiveClass:
1760 case Stmt::OMPCriticalDirectiveClass:
1761 case Stmt::OMPParallelForDirectiveClass:
1762 case Stmt::OMPParallelForSimdDirectiveClass:
1763 case Stmt::OMPParallelSectionsDirectiveClass:
1764 case Stmt::OMPParallelMasterDirectiveClass:
1765 case Stmt::OMPParallelMaskedDirectiveClass:
1766 case Stmt::OMPTaskDirectiveClass:
1767 case Stmt::OMPTaskyieldDirectiveClass:
1768 case Stmt::OMPBarrierDirectiveClass:
1769 case Stmt::OMPTaskwaitDirectiveClass:
1770 case Stmt::OMPErrorDirectiveClass:
1771 case Stmt::OMPTaskgroupDirectiveClass:
1772 case Stmt::OMPFlushDirectiveClass:
1773 case Stmt::OMPDepobjDirectiveClass:
1774 case Stmt::OMPScanDirectiveClass:
1775 case Stmt::OMPOrderedDirectiveClass:
1776 case Stmt::OMPAtomicDirectiveClass:
1777 case Stmt::OMPAssumeDirectiveClass:
1778 case Stmt::OMPTargetDirectiveClass:
1779 case Stmt::OMPTargetDataDirectiveClass:
1780 case Stmt::OMPTargetEnterDataDirectiveClass:
1781 case Stmt::OMPTargetExitDataDirectiveClass:
1782 case Stmt::OMPTargetParallelDirectiveClass:
1783 case Stmt::OMPTargetParallelForDirectiveClass:
1784 case Stmt::OMPTargetUpdateDirectiveClass:
1785 case Stmt::OMPTeamsDirectiveClass:
1786 case Stmt::OMPCancellationPointDirectiveClass:
1787 case Stmt::OMPCancelDirectiveClass:
1788 case Stmt::OMPTaskLoopDirectiveClass:
1789 case Stmt::OMPTaskLoopSimdDirectiveClass:
1790 case Stmt::OMPMasterTaskLoopDirectiveClass:
1791 case Stmt::OMPMaskedTaskLoopDirectiveClass:
1792 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
1793 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1794 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
1795 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1796 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
1797 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
1798 case Stmt::OMPDistributeDirectiveClass:
1799 case Stmt::OMPDistributeParallelForDirectiveClass:
1800 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
1801 case Stmt::OMPDistributeSimdDirectiveClass:
1802 case Stmt::OMPTargetParallelForSimdDirectiveClass:
1803 case Stmt::OMPTargetSimdDirectiveClass:
1804 case Stmt::OMPTeamsDistributeDirectiveClass:
1805 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
1806 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
1807 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
1808 case Stmt::OMPTargetTeamsDirectiveClass:
1809 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
1810 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
1811 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
1812 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1813 case Stmt::OMPReverseDirectiveClass:
1814 case Stmt::OMPTileDirectiveClass:
1815 case Stmt::OMPInterchangeDirectiveClass:
1816 case Stmt::OMPInteropDirectiveClass:
1817 case Stmt::OMPDispatchDirectiveClass:
1818 case Stmt::OMPMaskedDirectiveClass:
1819 case Stmt::OMPGenericLoopDirectiveClass:
1820 case Stmt::OMPTeamsGenericLoopDirectiveClass:
1821 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
1822 case Stmt::OMPParallelGenericLoopDirectiveClass:
1823 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1824 case Stmt::CapturedStmtClass:
1825 case Stmt::SYCLKernelCallStmtClass:
1826 case Stmt::OpenACCComputeConstructClass:
1827 case Stmt::OpenACCLoopConstructClass:
1828 case Stmt::OpenACCCombinedConstructClass:
1829 case Stmt::OpenACCDataConstructClass:
1830 case Stmt::OpenACCEnterDataConstructClass:
1831 case Stmt::OpenACCExitDataConstructClass:
1832 case Stmt::OpenACCHostDataConstructClass:
1833 case Stmt::OpenACCWaitConstructClass:
1834 case Stmt::OpenACCInitConstructClass:
1835 case Stmt::OpenACCShutdownConstructClass:
1836 case Stmt::OpenACCSetConstructClass:
1837 case Stmt::OpenACCUpdateConstructClass:
1838 case Stmt::OMPUnrollDirectiveClass:
1839 case Stmt::OMPMetaDirectiveClass:
1840 case Stmt::HLSLOutArgExprClass: {
1843 break;
1844 }
1845
1846 case Stmt::ParenExprClass:
1847 llvm_unreachable("ParenExprs already handled.");
1848 case Stmt::GenericSelectionExprClass:
1849 llvm_unreachable("GenericSelectionExprs already handled.");
1850
1851
1852 case Stmt::BreakStmtClass:
1853 case Stmt::CaseStmtClass:
1854 case Stmt::CompoundStmtClass:
1855 case Stmt::ContinueStmtClass:
1856 case Stmt::CXXForRangeStmtClass:
1857 case Stmt::DefaultStmtClass:
1858 case Stmt::DoStmtClass:
1859 case Stmt::ForStmtClass:
1860 case Stmt::GotoStmtClass:
1861 case Stmt::IfStmtClass:
1862 case Stmt::IndirectGotoStmtClass:
1863 case Stmt::LabelStmtClass:
1865 case Stmt::NullStmtClass:
1866 case Stmt::SwitchStmtClass:
1867 case Stmt::WhileStmtClass:
1868 case Expr::MSDependentExistsStmtClass:
1869 llvm_unreachable("Stmt should not be in analyzer evaluation loop");
1870 case Stmt::ImplicitValueInitExprClass:
1871
1872
1873
1874 llvm_unreachable("Should be pruned from CFG");
1875
1876 case Stmt::ObjCSubscriptRefExprClass:
1877 case Stmt::ObjCPropertyRefExprClass:
1878 llvm_unreachable("These are handled by PseudoObjectExpr");
1879
1880 case Stmt::GNUNullExprClass: {
1881
1883 state = state->BindExpr(
1887 break;
1888 }
1889
1890 case Stmt::ObjCAtSynchronizedStmtClass:
1894 break;
1895
1896 case Expr::ConstantExprClass:
1897 case Stmt::ExprWithCleanupsClass:
1898
1899 break;
1900
1901 case Stmt::CXXBindTemporaryExprClass: {
1909 break;
1910 }
1911
1912 case Stmt::ArrayInitLoopExprClass:
1916 break;
1917
1918 case Stmt::DesignatedInitExprClass:
1919 case Stmt::DesignatedInitUpdateExprClass:
1920 case Stmt::ArrayInitIndexExprClass:
1921 case Stmt::ExtVectorElementExprClass:
1922 case Stmt::ImaginaryLiteralClass:
1923 case Stmt::ObjCAtCatchStmtClass:
1924 case Stmt::ObjCAtFinallyStmtClass:
1925 case Stmt::ObjCAtTryStmtClass:
1926 case Stmt::ObjCAutoreleasePoolStmtClass:
1927 case Stmt::ObjCEncodeExprClass:
1928 case Stmt::ObjCIsaExprClass:
1929 case Stmt::ObjCProtocolExprClass:
1930 case Stmt::ObjCSelectorExprClass:
1931 case Stmt::ParenListExprClass:
1932 case Stmt::ShuffleVectorExprClass:
1933 case Stmt::ConvertVectorExprClass:
1934 case Stmt::VAArgExprClass:
1935 case Stmt::CUDAKernelCallExprClass:
1936 case Stmt::OpaqueValueExprClass:
1937 case Stmt::AsTypeExprClass:
1938 case Stmt::ConceptSpecializationExprClass:
1939 case Stmt::CXXRewrittenBinaryOperatorClass:
1940 case Stmt::RequiresExprClass:
1941 case Expr::CXXParenListInitExprClass:
1942 case Stmt::EmbedExprClass:
1943
1944
1945
1946
1947 case Stmt::PredefinedExprClass:
1948 case Stmt::AddrLabelExprClass:
1949 case Stmt::AttributedStmtClass:
1950 case Stmt::IntegerLiteralClass:
1951 case Stmt::FixedPointLiteralClass:
1952 case Stmt::CharacterLiteralClass:
1953 case Stmt::CXXScalarValueInitExprClass:
1954 case Stmt::CXXBoolLiteralExprClass:
1955 case Stmt::ObjCBoolLiteralExprClass:
1956 case Stmt::ObjCAvailabilityCheckExprClass:
1957 case Stmt::FloatingLiteralClass:
1958 case Stmt::NoInitExprClass:
1959 case Stmt::SizeOfPackExprClass:
1960 case Stmt::StringLiteralClass:
1961 case Stmt::SourceLocExprClass:
1962 case Stmt::ObjCStringLiteralClass:
1963 case Stmt::CXXPseudoDestructorExprClass:
1964 case Stmt::SubstNonTypeTemplateParmExprClass:
1965 case Stmt::CXXNullPtrLiteralExprClass:
1966 case Stmt::ArraySectionExprClass:
1967 case Stmt::OMPArrayShapingExprClass:
1968 case Stmt::OMPIteratorExprClass:
1969 case Stmt::SYCLUniqueStableNameExprClass:
1970 case Stmt::OpenACCAsteriskSizeExprClass:
1971 case Stmt::TypeTraitExprClass: {
1977 break;
1978 }
1979
1980 case Stmt::CXXDefaultArgExprClass:
1981 case Stmt::CXXDefaultInitExprClass: {
1985
1988
1989 const Expr *ArgE;
1990 if (const auto *DefE = dyn_cast(S))
1991 ArgE = DefE->getExpr();
1992 else if (const auto *DefE = dyn_cast(S))
1993 ArgE = DefE->getExpr();
1994 else
1995 llvm_unreachable("unknown constant wrapper kind");
1996
1997 bool IsTemporary = false;
1998 if (const auto *MTE = dyn_cast(ArgE)) {
1999 ArgE = MTE->getSubExpr();
2000 IsTemporary = true;
2001 }
2002
2003 std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);
2004 if (!ConstantVal)
2006
2008 for (const auto I : PreVisit) {
2010 State = State->BindExpr(S, LCtx, *ConstantVal);
2011 if (IsTemporary)
2012 State = createTemporaryRegionIfNeeded(State, LCtx,
2013 cast(S),
2014 cast(S));
2016 }
2017
2020 break;
2021 }
2022
2023
2024 case Stmt::CXXStdInitializerListExprClass:
2025 case Expr::ObjCArrayLiteralClass:
2026 case Expr::ObjCDictionaryLiteralClass:
2027 case Expr::ObjCBoxedExprClass: {
2029
2032
2035
2036 const auto *Ex = cast(S);
2037 QualType resultType = Ex->getType();
2038
2039 for (const auto N : preVisit) {
2042 resultType,
2044 ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
2045
2046
2047
2048 if (!(isa(Ex) &&
2049 !cast(Ex)->getSubExpr()
2051 for (auto Child : Ex->children()) {
2052 assert(Child);
2053 SVal Val = State->getSVal(Child, LCtx);
2055 }
2056
2058 }
2059
2062 break;
2063 }
2064
2065 case Stmt::ArraySubscriptExprClass:
2069 break;
2070
2071 case Stmt::MatrixSubscriptExprClass:
2072 llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
2073 break;
2074
2075 case Stmt::GCCAsmStmtClass: {
2084 break;
2085 }
2086
2087 case Stmt::MSAsmStmtClass:
2091 break;
2092
2093 case Stmt::BlockExprClass:
2097 break;
2098
2099 case Stmt::LambdaExprClass:
2100 if (AMgr.options.ShouldInlineLambdas) {
2104 } else {
2107 }
2108 break;
2109
2110 case Stmt::BinaryOperatorClass: {
2111 const auto *B = cast(S);
2112 if (B->isLogicalOp()) {
2116 break;
2117 }
2118 else if (B->getOpcode() == BO_Comma) {
2122 state->getSVal(B->getRHS(),
2124 break;
2125 }
2126
2128
2129 if (AMgr.options.ShouldEagerlyAssume &&
2130 (B->isRelationalOp() || B->isEqualityOp())) {
2134 }
2135 else
2137
2139 break;
2140 }
2141
2142 case Stmt::CXXOperatorCallExprClass: {
2143 const auto *OCE = cast(S);
2144
2145
2146
2147 const Decl *Callee = OCE->getCalleeDecl();
2148 if (const auto *MD = dyn_cast_or_null(Callee)) {
2149 if (MD->isImplicitObjectMemberFunction()) {
2153 createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
2154 if (NewState != State) {
2155 Pred = Bldr.generateNode(OCE, Pred, NewState, nullptr,
2157
2158 if (!Pred)
2159 break;
2160 }
2161 }
2162 }
2163 [[fallthrough]];
2164 }
2165
2166 case Stmt::CallExprClass:
2167 case Stmt::CXXMemberCallExprClass:
2168 case Stmt::UserDefinedLiteralClass:
2172 break;
2173
2174 case Stmt::CXXCatchStmtClass:
2178 break;
2179
2180 case Stmt::CXXTemporaryObjectExprClass:
2181 case Stmt::CXXConstructExprClass:
2185 break;
2186
2187 case Stmt::CXXInheritedCtorInitExprClass:
2190 Dst);
2192 break;
2193
2194 case Stmt::CXXNewExprClass: {
2196
2199
2201 for (const auto i : PreVisit)
2203
2206 break;
2207 }
2208
2209 case Stmt::CXXDeleteExprClass: {
2212 const auto *CDE = cast(S);
2216
2219
2221 break;
2222 }
2223
2224
2225
2226 case Stmt::ChooseExprClass: {
2228 const auto *C = cast(S);
2231 break;
2232 }
2233
2234 case Stmt::CompoundAssignOperatorClass:
2238 break;
2239
2240 case Stmt::CompoundLiteralExprClass:
2244 break;
2245
2246 case Stmt::BinaryConditionalOperatorClass:
2247 case Stmt::ConditionalOperatorClass: {
2249 const auto *C = cast(S);
2252 break;
2253 }
2254
2255 case Stmt::CXXThisExprClass:
2259 break;
2260
2261 case Stmt::DeclRefExprClass: {
2263 const auto *DE = cast(S);
2266 break;
2267 }
2268
2269 case Stmt::DeclStmtClass:
2273 break;
2274
2275 case Stmt::ImplicitCastExprClass:
2276 case Stmt::CStyleCastExprClass:
2277 case Stmt::CXXStaticCastExprClass:
2278 case Stmt::CXXDynamicCastExprClass:
2279 case Stmt::CXXReinterpretCastExprClass:
2280 case Stmt::CXXConstCastExprClass:
2281 case Stmt::CXXFunctionalCastExprClass:
2282 case Stmt::BuiltinBitCastExprClass:
2283 case Stmt::ObjCBridgedCastExprClass:
2284 case Stmt::CXXAddrspaceCastExprClass: {
2286 const auto *C = cast(S);
2288 VisitCast(C, C->getSubExpr(), Pred, dstExpr);
2289
2290
2293 break;
2294 }
2295
2296 case Expr::MaterializeTemporaryExprClass: {
2298 const auto *MTE = cast(S);
2302 for (const auto i : dstPrevisit)
2306 break;
2307 }
2308
2309 case Stmt::InitListExprClass:
2313 break;
2314
2315 case Stmt::MemberExprClass:
2319 break;
2320
2321 case Stmt::AtomicExprClass:
2325 break;
2326
2327 case Stmt::ObjCIvarRefExprClass:
2331 break;
2332
2333 case Stmt::ObjCForCollectionStmtClass:
2337 break;
2338
2339 case Stmt::ObjCMessageExprClass:
2343 break;
2344
2345 case Stmt::ObjCAtThrowStmtClass:
2346 case Stmt::CXXThrowExprClass:
2347
2348
2350 break;
2351
2352 case Stmt::ReturnStmtClass:
2356 break;
2357
2358 case Stmt::OffsetOfExprClass: {
2362
2364 for (const auto Node : PreVisit)
2366
2369 break;
2370 }
2371
2372 case Stmt::UnaryExprOrTypeTraitExprClass:
2375 Pred, Dst);
2377 break;
2378
2379 case Stmt::StmtExprClass: {
2380 const auto *SE = cast(S);
2381
2382 if (SE->getSubStmt()->body_empty()) {
2383
2384 assert(SE->getType() == getContext().VoidTy
2385 && "Empty statement expression must have void type.");
2386 break;
2387 }
2388
2389 if (const auto *LastExpr =
2390 dyn_cast(*SE->getSubStmt()->body_rbegin())) {
2394 state->getSVal(LastExpr,
2396 }
2397 break;
2398 }
2399
2400 case Stmt::UnaryOperatorClass: {
2402 const auto *U = cast(S);
2403 if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
2407 }
2408 else
2411 break;
2412 }
2413
2414 case Stmt::PseudoObjectExprClass: {
2417 const auto *PE = cast(S);
2418 if (const Expr *Result = PE->getResultExpr()) {
2422 }
2423 else
2427
2429 break;
2430 }
2431
2432 case Expr::ObjCIndirectCopyRestoreExprClass: {
2433
2434
2435
2438 const auto *OIE = cast(S);
2439 const Expr *E = OIE->getSubExpr();
2444 break;
2445 }
2446 }
2447}
2448
2449bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
2453 assert(CalleeSF && CallerSF);
2454 ExplodedNode *BeforeProcessingCall = nullptr;
2456
2457
2458 while (N) {
2460 BeforeProcessingCall = N;
2462
2463
2465 continue;
2466
2467
2469 continue;
2471 continue;
2473 continue;
2474 if (std::optional SP = L.getAs<StmtPoint>())
2475 if (SP->getStmt() == CE)
2476 continue;
2477 break;
2478 }
2479
2480 if (!BeforeProcessingCall)
2481 return false;
2482
2483
2484
2485
2486
2490
2491
2493 NewNodeState =
2495
2496
2497 bool IsNew = false;
2498 ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew);
2499
2500
2501 if (!IsNew)
2502 return true;
2503
2505
2506
2509 NumTimesRetriedWithoutInlining++;
2510 return true;
2511}
2512
2513
2518
2519
2520 if(AMgr.options.ShouldUnrollLoops) {
2523 if (Term) {
2525 Pred, maxBlockVisitOnPath);
2526 if (NewState != Pred->getState()) {
2528 if (!UpdatedNode)
2529 return;
2530 Pred = UpdatedNode;
2531 }
2532 }
2533
2535 return;
2536 }
2537
2538
2539
2542 AMgr.options.ShouldWidenLoops) {
2544 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
2545 return;
2546
2550 nodeBuilder.generateNode(WidenedState, Pred);
2551 return;
2552 }
2553
2554
2559
2560
2561
2565 (*G.roots_begin())->getLocation().getLocationContext();
2568
2569
2570
2571
2572
2574 replayWithoutInlining(Pred, CalleeLC)))
2575 return;
2576 NumMaxBlockCountReachedInInlined++;
2577 } else
2578 NumMaxBlockCountReached++;
2579
2580
2581 Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
2582 }
2583}
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2598
2599 const auto *Ex = dyn_cast(Condition);
2600 if (!Ex)
2602
2603 uint64_t bits = 0;
2604 bool bitsInit = false;
2605
2606 while (const auto *CE = dyn_cast(Ex)) {
2608
2611
2613 if (!bitsInit || newBits < bits) {
2614 bitsInit = true;
2615 bits = newBits;
2616 }
2617
2618 Ex = CE->getSubExpr();
2619 }
2620
2621
2623
2627
2628 return state->getSVal(Ex, LCtx);
2629}
2630
2631#ifndef NDEBUG
2634 const auto *BO = dyn_cast(Condition);
2635 if (!BO || !BO->isLogicalOp()) {
2637 }
2638 Condition = BO->getRHS()->IgnoreParens();
2639 }
2640 return nullptr;
2641}
2642#endif
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2660 if (const auto *Ex = dyn_cast(Condition))
2662
2663 const auto *BO = dyn_cast(Condition);
2664 if (!BO || !BO->isLogicalOp())
2666
2668 "Other kinds of branches are handled separately!");
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678 for (CFGElement Elem : llvm::reverse(*B)) {
2679 std::optional CS = Elem.getAs<CFGStmt>();
2680 if (!CS)
2681 continue;
2682 const Stmt *LastStmt = CS->getStmt();
2684 return LastStmt;
2685 }
2686 llvm_unreachable("could not resolve condition");
2687}
2688
2690 std::pair<const ObjCForCollectionStmt *, const LocationContext *>;
2691
2693
2697 assert(!State->contains({O, LC}));
2698 return State->set({O, LC}, HasMoreIteraton);
2699}
2700
2705 assert(State->contains({O, LC}));
2706 return State->remove({O, LC});
2707}
2708
2712 assert(State->contains({O, LC}));
2713 return *State->get({O, LC});
2714}
2715
2716
2717
2718
2719static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
2722 if (const auto *ObjCFor = dyn_cast(Condition)) {
2723 bool HasMoreIteraton =
2725
2726
2727
2730 if (HasMoreIteraton)
2731 return std::pair<ProgramStateRef, ProgramStateRef>{State, nullptr};
2732 else
2733 return std::pair<ProgramStateRef, ProgramStateRef>{nullptr, State};
2734 }
2736
2737 if (X.isUnknownOrUndef()) {
2738
2739 if (const auto *Ex = dyn_cast(Condition)) {
2740 if (Ex->getType()->isIntegralOrEnumerationType()) {
2741
2742
2743
2744
2745 SVal recovered =
2747 N->getState()->getStateManager().getContext());
2748
2750 X = recovered;
2751 }
2752 }
2753 }
2754 }
2755
2756
2757 if (X.isUnknownOrUndef())
2758 return std::nullopt;
2759
2761
2763 return State->assume(V);
2764}
2765
2769 std::optional IterationsCompletedInLoop) {
2771 "CXXBindTemporaryExprs are handled by processBindTemporary.");
2774 currBldrCtx = &BldCtx;
2775
2776
2780 return;
2781 }
2782
2783 if (const auto *Ex = dyn_cast(Condition))
2785
2789 "Error evaluating branch");
2790
2793 Pred, *this);
2794
2795 if (CheckersOutSet.empty())
2796 return;
2797
2798 BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
2799 for (ExplodedNode *PredN : CheckersOutSet) {
2800 if (PredN->isSink())
2801 continue;
2802
2804
2805 ProgramStateRef StTrue = PrevState, StFalse = PrevState;
2807 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2808
2809 if (StTrue && StFalse)
2810 assert(!isa(Condition));
2811
2812 if (StTrue) {
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828 bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;
2829 bool FalseAlsoFeasible =
2830 StFalse ||
2832 bool SkipTrueBranch = CompletedTwoIterations && FalseAlsoFeasible;
2833
2834
2835
2836
2837
2838 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops)
2839 Builder.generateNode(StTrue, true, PredN);
2840 }
2841
2842 if (StFalse)
2843 Builder.generateNode(StFalse, false, PredN);
2844 }
2845 currBldrCtx = nullptr;
2846}
2847
2848
2849
2851 llvm::ImmutableSet<const VarDecl *>)
2852
2860 currBldrCtx = &BuilderCtx;
2861
2862 const auto *VD = cast(DS->getSingleDecl());
2864 bool initHasRun = state->contains(VD);
2866
2867 if (!initHasRun) {
2868 state = state->add(VD);
2869 }
2870
2871 Builder.generateNode(state, initHasRun, Pred);
2872
2873 currBldrCtx = nullptr;
2874}
2875
2876
2877
2881
2882
2883
2884
2885
2886
2887
2888
2890
2891 if (std::optionalloc::GotoLabel LV = V.getAs<loc::GotoLabel>()) {
2892 const LabelDecl *L = LV->getLabel();
2893
2894 for (iterator Succ : builder) {
2895 if (Succ.getLabel() == L) {
2896 builder.generateNode(Succ, state);
2897 return;
2898 }
2899 }
2900
2901 llvm_unreachable("No block with label.");
2902 }
2903
2904 if (isa<UndefinedVal, loc::ConcreteInt>(V)) {
2905
2906
2907
2908
2909 return;
2910 }
2911
2912
2913
2914
2915 for (iterator Succ : builder)
2917}
2918
2925}
2926
2927
2928
2933
2935 State = finishArgumentConstruction(
2936 State, *getStateManager().getCallEventManager().getCaller(
2938
2939
2940
2941
2942
2943
2944
2945
2946 {
2950 while (LC != ToLC) {
2951 assert(LC && "ToLC must be a parent of FromLC!");
2952 for (auto I : State->get())
2953 if (I.first.getLocationContext() == LC) {
2954
2955
2956
2957 assert(I.first.getItem().getKind() ==
2959 I.first.getItem().getKind() ==
2961 State = State->remove(I.first);
2962 }
2964 }
2965 }
2966
2967
2968 if (State != Pred->getState()) {
2970 NodeBuilder Bldr(Pred, PostCleanup, BC);
2972 if (!Pred) {
2973
2974
2975 return;
2976 }
2977 }
2978
2979 assert(areAllObjectsFullyConstructed(Pred->getState(),
2982
2984
2987
2990
2991
2992 for (const auto I : AfterRemovedDead)
2994 } else {
2996 }
2997
2999}
3000
3001
3002
3005
3009
3010 if (CondV_untested.isUndef()) {
3011
3012
3013
3014
3015 return;
3016 }
3018
3020
3021 iterator I = builder.begin(), EI = builder.end();
3022 bool defaultIsFeasible = I == EI;
3023
3024 for ( ; I != EI; ++I) {
3025
3026 if (!I.getBlock())
3027 continue;
3028
3029 const CaseStmt *Case = I.getCase();
3030
3031
3033 assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType()));
3034
3035
3036 llvm::APSInt V2;
3039 else
3040 V2 = V1;
3041
3043 if (std::optional NL = CondV.getAs<NonLoc>())
3044 std::tie(StateCase, DefaultSt) =
3045 DefaultSt->assumeInclusiveRange(*NL, V1, V2);
3046 else
3047 StateCase = DefaultSt;
3048
3049 if (StateCase)
3051
3052
3053
3054 if (DefaultSt)
3055 defaultIsFeasible = true;
3056 else {
3057 defaultIsFeasible = false;
3058 break;
3059 }
3060 }
3061
3062 if (!defaultIsFeasible)
3063 return;
3064
3065
3066
3067
3068
3069
3070
3071
3076 return;
3077 }
3078
3080}
3081
3082
3083
3084
3085
3090
3093
3094 if (const auto *VD = dyn_cast(D)) {
3095
3096
3097 assert(Ex->isGLValue() || VD->getType()->isVoidType());
3100 const auto *MD = dyn_cast_or_null(D);
3101 const auto *DeclRefEx = dyn_cast(Ex);
3102 std::optional<std::pair<SVal, QualType>> VInfo;
3103
3104 if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
3105 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
3106 MD->getParent()->isLambda()) {
3107
3109 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
3110 FieldDecl *LambdaThisCaptureField;
3111 CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
3112
3113
3114
3115 if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
3118 SVal CXXThisVal = state->getSVal(CXXThis);
3119 VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
3120 }
3121 }
3122
3123 if (!VInfo)
3124 VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());
3125
3127 bool IsReference = VInfo->second->isReferenceType();
3128
3129
3130
3131 if (IsReference) {
3132 if (const MemRegion *R = V.getAsRegion())
3133 V = state->getSVal(R);
3134 else
3136 }
3137
3138 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3140 return;
3141 }
3142 if (const auto *ED = dyn_cast(D)) {
3145 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
3146 return;
3147 }
3148 if (const auto *FD = dyn_cast(D)) {
3150 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3152 return;
3153 }
3154 if (isa<FieldDecl, IndirectFieldDecl>(D)) {
3155
3156
3157 return;
3158 }
3159 if (const auto *BD = dyn_cast(D)) {
3160 const auto *DD = cast(BD->getDecomposedDecl());
3161
3162 SVal Base = state->getLValue(DD, LCtx);
3163 if (DD->getType()->isReferenceType()) {
3165 Base = state->getSVal(R);
3166 else
3168 }
3169
3171
3172
3173 if (const auto *ME = dyn_cast(BD->getBinding())) {
3174 const auto *Field = cast(ME->getMemberDecl());
3175 V = state->getLValue(Field, Base);
3176 }
3177
3178 else if (const auto *ASE = dyn_cast(BD->getBinding())) {
3179 SVal Idx = state->getSVal(ASE->getIdx(), LCtx);
3180
3181
3182
3183
3184 assert(Idx.isConstant() && "BindingDecl array index is not a constant!");
3185
3186 V = state->getLValue(BD->getType(), Idx, Base);
3187 }
3188
3189 else if (const auto *HV = BD->getHoldingVar()) {
3190 V = state->getLValue(HV, LCtx);
3191
3192 if (HV->getType()->isReferenceType()) {
3193 if (const MemRegion *R = V.getAsRegion())
3194 V = state->getSVal(R);
3195 else
3197 }
3198 } else
3199 llvm_unreachable("An unknown case of structured binding encountered!");
3200
3201
3202
3203 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3204 if (const MemRegion *R = V.getAsRegion())
3205 V = state->getSVal(R);
3206 else
3208 }
3209
3210 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
3212
3213 return;
3214 }
3215
3216 if (const auto *TPO = dyn_cast(D)) {
3217
3218 (void)TPO;
3219 return;
3220 }
3221
3222 llvm_unreachable("Support for this Decl not implemented.");
3223}
3224
3225
3231
3233 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
3234
3236
3237 for (auto *Node : CheckerPreStmt) {
3238
3239
3240 if (isa(Ex->getSubExpr()))
3241 break;
3242
3245
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282 if (const auto *ME = dyn_cast(Arr)) {
3283 Expr *MEBase = ME->getBase();
3284
3285
3286 if (auto CXXSCE = dyn_cast(MEBase)) {
3287 MEBase = CXXSCE->getSubExpr();
3288 }
3289
3290 auto ObjDeclExpr = cast(MEBase);
3291 SVal Obj = state->getLValue(cast(ObjDeclExpr->getDecl()), LCtx);
3292
3293 Base = state->getLValue(cast(ME->getMemberDecl()), Obj);
3294 }
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308 if (const DeclRefExpr *DRE = dyn_cast(Arr))
3309 Base = state->getLValue(cast(DRE->getDecl()), LCtx);
3310
3311
3313 Base = state->getSVal(R);
3314 else
3316
3317 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, Base));
3318 }
3319
3321}
3322
3323
3329
3332
3334 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
3335
3337
3338
3339
3340
3341 bool IsGLValueLike = A->isGLValue() ||
3343
3344 for (auto *Node : CheckerPreStmt) {
3347
3348 if (IsGLValueLike) {
3350
3351
3352
3353
3356
3357 SVal V = state->getLValue(T,
3358 state->getSVal(Idx, LCtx),
3359 state->getSVal(Base, LCtx));
3360 Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
3362 } else if (IsVectorType) {
3363
3365 } else {
3366 llvm_unreachable("Array subscript should be an lValue when not \
3367a vector and not a forbidden lvalue type");
3368 }
3369 }
3370
3372}
3373
3374
3377
3380
3383
3384
3385
3386 if (isa<VarDecl, EnumConstantDecl>(Member)) {
3387 for (const auto I : CheckedSet)
3389 } else {
3390 StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
3392
3393 for (const auto I : CheckedSet) {
3397
3398
3399 if (const auto *MD = dyn_cast(Member)) {
3400 if (MD->isImplicitObjectMemberFunction())
3401 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
3402
3404 state = state->BindExpr(M, LCtx, MDVal);
3405
3407 continue;
3408 }
3409
3410
3412 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,
3413 nullptr,
3414 &MR);
3415 SVal baseExprVal =
3417
3418
3419 if (const auto *SR =
3420 dyn_cast_or_null(baseExprVal.getAsRegion())) {
3421 QualType T = SR->getPointeeStaticType();
3422 baseExprVal =
3424 }
3425
3426 const auto *field = cast(Member);
3427 SVal L = state->getLValue(field, baseExprVal);
3428
3430
3431
3432
3433
3436 const auto *PE =
3437 dyn_cast(I->getParentMap().getParentIgnoreParens(M));
3438 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
3439 llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
3440 }
3441 }
3442
3443 if (field->getType()->isReferenceType()) {
3445 L = state->getSVal(R);
3446 else
3448 }
3449
3450 Bldr.generateNode(M, I, state->BindExpr(M, LCtx, L), nullptr,
3452 } else {
3454 evalLoad(Tmp, M, M, I, state, L);
3456 }
3457 }
3458 }
3459
3461}
3462
3467
3468
3469
3470
3472 StmtNodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx);
3473
3474 for (const auto I : AfterPreSet) {
3477
3479 for (unsigned SI = 0, Count = AE->getNumSubExprs(); SI != Count; SI++) {
3481 SVal SubExprVal = State->getSVal(SubExpr, LCtx);
3482 ValuesToInvalidate.push_back(SubExprVal);
3483 }
3484
3485 State = State->invalidateRegions(ValuesToInvalidate, AE,
3487 LCtx,
3488 true,
3489 nullptr);
3490
3492 State = State->BindExpr(AE, LCtx, ResultVal);
3495 }
3496
3498}
3499
3500
3501
3502
3503
3504
3505
3506
3512 for (const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
3513
3514 const MemRegion *MR = LocAndVal.first.getAsRegion();
3515 if (!MR ||
3516 !isa<StackSpaceRegion, StaticGlobalSpaceRegion>(MR->getMemorySpace())) {
3517 Escaped.push_back(LocAndVal.second);
3518 continue;
3519 }
3520
3521
3522 if (const auto *VR = dyn_cast(MR->getBaseRegion()))
3523 if (VR->hasStackParametersStorage() && VR->getStackFrame()->inTopFrame())
3524 if (const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3525 if (!RD->hasTrivialDestructor()) {
3526 Escaped.push_back(LocAndVal.second);
3527 continue;
3528 }
3529
3530
3531
3532
3533
3534
3535 SVal StoredVal = State->getSVal(MR);
3536 if (StoredVal != LocAndVal.second)
3537 if (State ==
3538 (State->bindLoc(loc::MemRegionVal(MR), LocAndVal.second, LCtx)))
3539 Escaped.push_back(LocAndVal.second);
3540 }
3541
3542 if (Escaped.empty())
3543 return State;
3544
3545 return escapeValues(State, Escaped, Kind, Call);
3546}
3547
3551 std::pair<SVal, SVal> LocAndVal(Loc, Val);
3553 nullptr);
3554}
3555
3562 if (!Invalidated || Invalidated->empty())
3563 return State;
3564
3567 *Invalidated,
3568 nullptr,
3570 &ITraits);
3571
3572
3573
3575 for (const auto I : ExplicitRegions) {
3577 SymbolsDirectlyInvalidated.insert(R->getSymbol());
3578 }
3579
3581 for (const auto &sym : *Invalidated) {
3582 if (SymbolsDirectlyInvalidated.count(sym))
3583 continue;
3584 SymbolsIndirectlyInvalidated.insert(sym);
3585 }
3586
3587 if (!SymbolsDirectlyInvalidated.empty())
3590
3591
3592 if (!SymbolsIndirectlyInvalidated.empty())
3595
3596 return State;
3597}
3598
3599
3600
3607 if (!PP)
3608 PP = &PS;
3609
3610
3613 StoreE, *this, *PP);
3614
3616
3617
3618
3619 if (!isa(location)) {
3621 nullptr);
3624 Bldr.generateNode(L, state, Pred);
3625 return;
3626 }
3627
3628 for (const auto PredI : CheckedSet) {
3630
3632
3633
3634
3635
3636 state = state->bindLoc(location.castAs<Loc>(),
3637 Val, LC, !atDeclInit);
3638
3639 const MemRegion *LocReg = nullptr;
3640 if (std::optionalloc::MemRegionVal LocRegVal =
3642 LocReg = LocRegVal->getRegion();
3643 }
3644
3646 Bldr.generateNode(L, state, PredI);
3647 }
3648}
3649
3650
3651
3652
3653
3654
3655
3656
3657
3659 const Expr *LocationE,
3663
3664
3665 const Expr *StoreE = AssignE ? AssignE : LocationE;
3666
3667
3669 evalLocation(Tmp, AssignE, LocationE, Pred, state, location, false);
3670
3671 if (Tmp.empty())
3672 return;
3673
3675 return;
3676
3677 for (const auto I : Tmp)
3678 evalBind(Dst, StoreE, I, location, Val, false);
3679}
3680
3682 const Expr *NodeEx,
3683 const Expr *BoundEx,
3686 SVal location,
3689 assert(!isa(location) && "location cannot be a NonLoc.");
3690 assert(NodeEx);
3691 assert(BoundEx);
3692
3694 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, true);
3695 if (Tmp.empty())
3696 return;
3697
3700 return;
3701
3702
3703 for (const auto I : Tmp) {
3704 state = I->getState();
3706
3708 if (location.isValid()) {
3709 if (LoadTy.isNull())
3710 LoadTy = BoundEx->getType();
3711 V = state->getSVal(location.castAs<Loc>(), LoadTy);
3712 }
3713
3714 Bldr.generateNode(NodeEx, I, state->BindExpr(BoundEx, LCtx, V), tag,
3716 }
3717}
3718
3720 const Stmt *NodeEx,
3721 const Stmt *BoundEx,
3724 SVal location,
3725 bool isLoad) {
3727
3729 return;
3730 }
3731
3733 BldrTop.takeNodes(Pred);
3735 if (Pred->getState() != state) {
3736
3737
3738
3739
3740
3741
3742
3743
3744
3746 Bldr.generateNode(NodeEx, Pred, state, &tag);
3747 }
3750 NodeEx, BoundEx, *this);
3751 BldrTop.addNodes(Tmp);
3752}
3753
3754std::pair<const ProgramPointTag *, const ProgramPointTag *>
3757 FalseTag(TagProviderName, "Eagerly Assume False");
3758
3759 return std::make_pair(&TrueTag, &FalseTag);
3760}
3761
3762
3763
3764
3766 const Expr *)
3767
3770 const Expr *Ex) {
3772
3774
3775
3776
3779 continue;
3780 }
3781
3783 State = State->set(nullptr);
3785 std::optionalnonloc::SymbolVal SEV = V.getAs<nonloc::SymbolVal>();
3786 if (SEV && SEV->isExpression()) {
3788
3789 auto [StateTrue, StateFalse] = State->assume(*SEV);
3790
3791 if (StateTrue && StateFalse) {
3792 StateTrue = StateTrue->set(Ex);
3793 StateFalse = StateFalse->set(Ex);
3794 }
3795
3796
3797 if (StateTrue) {
3799 StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
3800 Bldr.generateNode(Ex, Pred, StateTrue, TrueTag);
3801 }
3802
3803
3804 if (StateFalse) {
3806 StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
3807 Bldr.generateNode(Ex, Pred, StateFalse, FalseTag);
3808 }
3809 }
3810 }
3811}
3812
3814 const Expr *Ex) const {
3815 return Ex && State->get() == Ex;
3816}
3817
3821
3822
3823
3824
3825
3826
3827
3829
3832 assert(!isa(X));
3833
3834 if (std::optional LV = X.getAs<Loc>())
3835 state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),
3837 true);
3838 }
3839
3840
3843
3844 if (std::optional LV = X.getAs<Loc>())
3845 state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),
3847 true);
3848 }
3849
3851}
3852
3857}
3858
3859
3860
3861
3862
3863namespace llvm {
3864
3865template<>
3868
3871 N->getState()->getStateManager().getOwningEngine()).getBugReporter();
3872
3874 for (const auto &Report : Class.getReports()) {
3875 const auto *PR = dyn_cast(Report.get());
3876 if (!PR)
3877 continue;
3878 const ExplodedNode *EN = PR->getErrorNode();
3881 return true;
3882 }
3883 }
3884 return false;
3885 }
3886
3887
3888
3889
3890
3893 llvm::function_ref<void(const ExplodedNode *)> PreCallback,
3894 llvm::function_ref<void(const ExplodedNode *)> PostCallback,
3895 llvm::function_ref<bool(const ExplodedNode *)> Stop) {
3896 while (true) {
3897 PreCallback(N);
3898 if (Stop(N))
3899 return true;
3900
3902 break;
3903 PostCallback(N);
3904
3906 }
3907 return false;
3908 }
3909
3912 }
3913
3915 std::string Buf;
3916 llvm::raw_string_ostream Out(Buf);
3917
3918 const bool IsDot = true;
3919 const unsigned int Space = 1;
3921
3922 Out << "{ \"state_id\": " << State->getID()
3923 << ",\\l";
3924
3925 Indent(Out, Space, IsDot) << "\"program_points\": [\\l";
3926
3927
3928 traverseHiddenNodes(
3929 N,
3931 Indent(Out, Space + 1, IsDot) << "{ ";
3933 Out << ", \"tag\": ";
3935 Out << '\"' << Tag->getTagDescription() << '\"';
3936 else
3937 Out << "null";
3938 Out << ", \"node_id\": " << OtherNode->getID() <<
3939 ", \"is_sink\": " << OtherNode->isSink() <<
3940 ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
3941 },
3942
3943 [&](const ExplodedNode *) { Out << ",\\l"; },
3944 [&](const ExplodedNode *) { return false; });
3945
3946 Out << "\\l";
3947 Indent(Out, Space, IsDot) << "],\\l";
3948
3950
3951 Out << "\\l}\\l";
3952 return Buf;
3953 }
3954};
3955
3956}
3957
3960 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
3961}
3962
3965 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
3966}
3967
3969 if (trim) {
3970 std::vector<const ExplodedNode *> Src;
3971
3972
3974 const auto *R =
3975 dyn_cast(Class.getReports()[0].get());
3976 if (!R)
3977 continue;
3978 const auto *N = const_cast<ExplodedNode *>(R->getErrorNode());
3979 Src.push_back(N);
3980 }
3982 }
3983
3984 return llvm::WriteGraph(&G, "ExprEngine", false,
3985 "Exploded Graph",
3986 std::string(Filename));
3987}
3988
3991 std::unique_ptr TrimmedG(G.trim(Nodes));
3992
3993 if (!TrimmedG.get()) {
3994 llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
3995 return "";
3996 }
3997
3998 return llvm::WriteGraph(TrimmedG.get(), "TrimmedExprEngine",
3999 false,
4000 "Trimmed Exploded Graph",
4001 std::string(Filename));
4002}
4003
4005 static int index = 0;
4006 return &index;
4007}
4008
4009void ExprEngine::anchor() { }
Defines the clang::ASTContext interface.
BoundNodesTreeBuilder Nodes
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static 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....
Defines the clang::Expr interface and subclasses for C++ expressions.
static const Stmt * getRightmostLeaf(const Stmt *Condition)
std::pair< const ObjCForCollectionStmt *, const LocationContext * > ObjCForLctxPair
static SVal RecoverCastedSymbol(ProgramStateRef state, const Stmt *Condition, const LocationContext *LCtx, ASTContext &Ctx)
RecoverCastedSymbol - A helper function for ProcessBranch that is used to try to recover some path-se...
static void printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
static void printIndicesOfElementsToConstructJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
static void printStateTraitWithLocationContextJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, const char *NL, unsigned int Space, bool IsDot, const char *jsonPropertyName, Printer printer, Args &&...args)
A helper function to generalize program state trait printing.
static void printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S, const ExplodedNode *Pred, const LocationContext *LC)
static const Stmt * ResolveCondition(const Stmt *Condition, const CFGBlock *B)
REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction, ObjectsUnderConstructionMap) typedef llvm REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct, IndexOfElementToConstructMap) typedef llvm typedef llvm::ImmutableMap< const LocationContext *, unsigned > PendingArrayDestructionMap
static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)
llvm::ImmutableMap< ConstructedObjectKey, SVal > ObjectsUnderConstructionMap
static std::optional< std::pair< ProgramStateRef, ProgramStateRef > > assumeCondition(const Stmt *Condition, ExplodedNode *N)
Split the state on whether there are any more iterations left for this loop.
STATISTIC(NumRemoveDeadBindings, "The # of times RemoveDeadBindings is called")
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
This header contains the declarations of functions which are used to decide which loops should be com...
This header contains the declarations of functions which are used to widen loops which do not otherwi...
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy.
static bool isRecordType(QualType T)
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines various enumerations that describe declaration and type specifiers.
Defines the Objective-C statement AST node classes.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
const clang::PrintingPolicy & getPrintingPolicy() const
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
ParentMap & getParentMap()
ASTContext & getASTContext() const
Stores options for the analyzer from the command line.
unsigned NoRetryExhausted
Do not re-analyze paths leading to exhausted nodes with a different strategy.
unsigned maxBlockVisitOnPath
The maximum number of times the analyzer visits a block.
AnalysisPurgeMode AnalysisPurgeOpt
Represents a loop initializing the elements of an array.
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Expr * getSubExpr() const
Get the initializer to use for each array element.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
static unsigned getNumSubExprs(AtomicOp Op)
Determine the number of arguments the specified atomic builtin should have.
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
const VarDecl * getVarDecl() const
const Stmt * getTriggerStmt() const
Represents C++ object destructor implicitly generated for base object in destructor.
Represents a single basic block in a source-level CFG.
CFGTerminator getTerminator() const
Stmt * getTerminatorStmt()
Represents C++ object destructor generated from a call to delete.
const CXXDeleteExpr * getDeleteExpr() const
Represents a top-level expression in a basic block.
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.
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...
bool isStmtBranch() const
Represents a base class of a C++ class.
Represents binding an expression to a temporary.
Represents a call to a C++ constructor.
Represents a C++ base or member initializer.
FieldDecl * getMember() const
If this is a member initializer, returns the declaration of the non-static data member being initiali...
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
Expr * getInit() const
Get the initializer.
SourceLocation getSourceLocation() const
Determine the source location of the initializer.
bool isAnyMemberInitializer() const
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
bool isIndirectMemberInitializer() const
int64_t getID(const ASTContext &Context) const
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
FieldDecl * getAnyMember() const
IndirectFieldDecl * getIndirectMember() const
bool isBaseVirtual() const
Returns whether the base is virtual or not.
Represents a delete expression for memory deallocation and destructor calls, e.g.
SourceLocation getBeginLoc() const
QualType getDestroyedType() const
Retrieve the type being destroyed.
Represents a C++ destructor within a class.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Represents a C++ struct/union/class.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
Represents a point when we begin processing an inlined call.
CaseStmt - Represent a case statement.
Represents a single point (AST node) in the program that requires attention during construction of an...
unsigned getIndex() const
If a single trigger statement triggers multiple constructors, they are usually being enumerated.
const CXXCtorInitializer * getCXXCtorInitializer() const
The construction site is not necessarily a statement.
@ TemporaryDestructorKind
const Stmt * getStmtOrNull() const
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
const Decl * getSingleDecl() const
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
This is a meta program point, which should be skipped by all the diagnostic reasoning etc.
This represents one expression.
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Represents a member of a struct/union/class.
This represents a GCC inline-assembly statement extension.
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Represents the declaration of a label.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const LocationContext * getParent() const
It might return null.
const StackFrameContext * getStackFrame() const
virtual bool inTopFrame() const
void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const LocationContext *)> printMoreInfoPerContext=[](const LocationContext *) {}) const
Prints out the call stack in json format.
Represents a point when we exit a loop.
This represents a Microsoft inline-assembly statement extension.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
This represents a decl that may have a name.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents Objective-C's collection statement.
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
bool isConsumedExpr(Expr *E) const
Represents a parameter to a function.
Represents a program point just after an implicit call event.
Represents a program point after a store evaluation.
Represents a program point just before an implicit call event.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
const ProgramPointTag * getTag() const
bool isPurgeKind()
Is this a program point corresponding to purge/removal of dead symbols and bindings.
void printJson(llvm::raw_ostream &Out, const char *NL="\n") const
@ PreStmtPurgeDeadSymbolsKind
@ PostStmtPurgeDeadSymbolsKind
const StackFrameContext * getStackFrame() const
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
const LocationContext * getLocationContext() const
A (possibly-)qualified type.
QualType getDesugaredType(const ASTContext &Context) const
Return the specified type with any "sugar" removed from the type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
SplitQualType split() const
Divides a QualType into its unqualified type and a set of local qualifiers.
bool isCForbiddenLValueType() const
Determine whether expressions of the given type are forbidden from being lvalues in C.
std::string getAsString() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
std::string printToString(const SourceManager &SM) const
It represents a stack frame of the call stack (based on CallEvent).
unsigned getIndex() const
const Stmt * getCallSite() const
const CFGBlock * getCallSiteBlock() const
bool inTopFrame() const override
const Stmt * getStmt() const
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
int64_t getID(const ASTContext &Context) const
SourceLocation getBeginLoc() const LLVM_READONLY
SwitchStmt - This represents a 'switch' stmt.
bool isAllEnumCasesCovered() const
Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isReferenceType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isVectorType() const
const T * getAs() const
Member-template getAs'.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
This class is used for tools that requires cross translation unit capability.
const LangOptions & getLangOpts() const
ASTContext & getASTContext() override
AnalyzerOptions & options
BranchNodeBuilder is responsible for constructing the nodes corresponding to the two branches of the ...
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 runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, ExprEngine &Eng, const ProgramPoint &PP)
Run checkers for binding of a value to a location.
void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, const ReturnStmt *RS)
Run checkers on end of function.
void runCheckersForLocation(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, bool isLoad, const Stmt *NodeEx, const Stmt *BoundEx, ExprEngine &Eng)
Run checkers for load/store of a location.
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng)
Run checkers for end of analysis.
void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const
Run checkers for debug-printing a ProgramState.
void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SymbolReaper &SymReaper, const Stmt *S, ExprEngine &Eng, ProgramPoint::Kind K)
Run checkers for dead symbols.
ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call)
Run checkers for region changes.
void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper)
Run checkers for live symbols.
void runCheckersForBeginFunction(ExplodedNodeSet &Dst, const BlockEdge &L, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers on beginning of function.
void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)
Run checkers for post-visiting Stmts.
void runCheckersForPreStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng)
Run checkers for pre-visiting Stmts.
void runCheckersForBranchCondition(const Stmt *condition, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng)
Run checkers for branch condition.
ProgramStateRef runCheckersForPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, RegionAndSymbolInvalidationTraits *ITraits)
Run checkers when pointers escape.
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption)
Run checkers for handling assumptions on symbolic values.
virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, SymbolReaper &SymReaper)=0
Scan all symbols referenced by the constraints.
void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block)
Inform the CoreEngine that a basic block was aborted because it could not be completely analyzed.
void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx)
Enqueue a single node created as a result of statement processing.
void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS)
enqueue the nodes corresponding to the end of function onto the end of path / work list.
void enqueue(ExplodedNodeSet &Set)
Enqueue the given set of nodes onto the work list.
std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy * > Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const
Creates a trimmed version of the graph that only contains paths leading to the given nodes.
void enableNodeReclamation(unsigned Interval)
Enable tracking of recently allocated nodes for potential reclamation when calling reclaimRecentlyAll...
void reclaimRecentlyAllocatedNodes()
Reclaim "uninteresting" nodes created since the last time this method was called.
ExplodedNode * getNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink=false, bool *IsNew=nullptr)
Retrieve the node associated with a (Location,State) pair, where the 'Location' is a ProgramPoint in ...
roots_iterator roots_begin()
void insert(const ExplodedNodeSet &S)
void Add(ExplodedNode *N)
const ProgramStateRef & getState() const
pred_iterator pred_begin()
bool isTrivial() const
The node is trivial if it has only one successor, only one predecessor, it's predecessor has only one...
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
void addPredecessor(ExplodedNode *V, ExplodedGraph &G)
addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...
ExplodedNode * getFirstSucc()
const StackFrameContext * getStackFrame() const
const LocationContext * getLocationContext() const
unsigned succ_size() const
void processEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, const ReturnStmt *RS=nullptr)
Called by CoreEngine.
void VisitBinaryOperator(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBinaryOperator - Transfer function logic for binary operators.
ProgramStateManager & getStateManager()
void VisitArraySubscriptExpr(const ArraySubscriptExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitArraySubscriptExpr - Transfer function for array accesses.
void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred)
void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void ProcessTemporaryDtor(const CFGTemporaryDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGuardedExpr - Transfer function logic for ?, __builtin_choose.
void processBeginOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L)
Called by CoreEngine.
void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCast - Transfer function logic for all casts (implicit and explicit).
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const LocationContext *LC, const Stmt *DiagnosticStmt=nullptr, ProgramPoint::Kind K=ProgramPoint::PreStmtPurgeDeadSymbolsKind)
Run the analyzer's garbage collection - remove dead symbols and bindings from the state.
void VisitLogicalExpr(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitLogicalExpr - Transfer function logic for '&&', '||'.
void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst, EvalCallOptions &Options)
void 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)
void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitObjCForCollectionStmt - Transfer function logic for ObjCForCollectionStmt.
void VisitUnaryOperator(const UnaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitUnaryOperator - Transfer function logic for unary operators.
ProgramStateRef getInitialState(const LocationContext *InitLoc)
getInitialState - Return the initial state used for the root vertex in the ExplodedGraph.
void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Transfer function logic for computing the lvalue of an Objective-C ivar.
static bool hasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitMSAsmStmt - Transfer function logic for MS inline asm.
static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const LocationContext *LC)
By looking at a certain item that may be potentially part of an object's ConstructionContext,...
std::string DumpGraph(bool trim=false, StringRef Filename="")
Dump graph to the specified filename.
void printJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, const char *NL, unsigned int Space, bool IsDot) const
printJson - Called by ProgramStateManager to print checker-specific data.
InliningModes
The modes of inlining, which override the default analysis-wide settings.
ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, ArrayRef< std::pair< SVal, SVal > > LocAndVals, const LocationContext *LCtx, PointerEscapeKind Kind, const CallEvent *Call)
Call PointerEscape callback when a value escapes as a result of bind.
const LocationContext * getRootLocationContext() const
static ProgramStateRef removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
ProgramStateRef processAssume(ProgramStateRef state, SVal cond, bool assumption)
evalAssume - Callback function invoked by the ConstraintManager when making assumptions about state v...
static std::optional< unsigned > getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives which element is being constructed in a non-POD type array.
void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitBlockExpr - Transfer function logic for BlockExprs.
void ProcessBaseDtor(const CFGBaseDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
static std::pair< const ProgramPointTag *, const ProgramPointTag * > getEagerlyAssumeBifurcationTags()
void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCall - Transfer function for function calls.
ASTContext & getContext() const
getContext - Return the ASTContext associated with this analysis.
StoreManager & getStoreManager()
void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Create a C++ temporary object for an rvalue.
CFGBlock::ConstCFGElementRef getCFGElementRef() const
void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitGCCAsmStmt - Transfer function logic for inline asm.
void processCFGBlockEntrance(const BlockEdge &L, NodeBuilderWithSinks &nodeBuilder, ExplodedNode *Pred)
Called by CoreEngine when processing the entrance of a CFGBlock.
void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
ProgramStateRef processRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call)
processRegionChanges - Called by ProgramStateManager whenever a change is made to the store.
void ProcessStmt(const Stmt *S, ExplodedNode *Pred)
ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS, InliningModes HowToInlineIn)
void ViewGraph(bool trim=false)
Visualize the ExplodedGraph created by executing the simulation.
static std::optional< unsigned > getPendingArrayDestruction(ProgramStateRef State, const LocationContext *LCtx)
Retreives which element is being destructed in a non-POD type array.
ProgramStateRef notifyCheckersOfPointerEscape(ProgramStateRef State, const InvalidatedSymbols *Invalidated, ArrayRef< const MemRegion * > ExplicitRegions, const CallEvent *Call, RegionAndSymbolInvalidationTraits &ITraits)
Call PointerEscape callback when a value escapes as a result of region invalidation.
static const ProgramPointTag * cleanupNodeTag()
A tag to track convenience transitions, which can be removed at cleanup.
void processCFGElement(const CFGElement E, ExplodedNode *Pred, unsigned StmtIdx, NodeBuilderContext *Ctx)
processCFGElement - Called by CoreEngine.
void processStaticInitializer(const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
void processBranch(const Stmt *Condition, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF, std::optional< unsigned > IterationsCompletedInLoop)
ProcessBranch - Called by CoreEngine.
void ProcessLoopExit(const Stmt *S, ExplodedNode *Pred)
void processSwitch(SwitchNodeBuilder &builder)
ProcessSwitch - Called by CoreEngine.
void processEndWorklist()
Called by CoreEngine when the analysis worklist has terminated.
CheckerManager & getCheckerManager() const
void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitAtomicExpr - Transfer function for builtin atomic expressions.
void ProcessMemberDtor(const CFGMemberDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitMemberExpr - Transfer function for member expressions.
void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)
bool didEagerlyAssumeBifurcateAt(ProgramStateRef State, const Expr *Ex) const
ConstraintManager & getConstraintManager()
void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, NodeBuilderContext &BldCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)
Called by CoreEngine.
void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitOffsetOfExpr - Transfer function for offsetof.
void evalLoad(ExplodedNodeSet &Dst, const Expr *NodeEx, const Expr *BoundExpr, ExplodedNode *Pred, ProgramStateRef St, SVal location, const ProgramPointTag *tag=nullptr, QualType LoadTy=QualType())
Simulate a read of the result of Ex.
void removeDeadOnEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Remove dead bindings/symbols before exiting a function.
void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)
Visit - Transfer function logic for all statements.
AnalysisManager & getAnalysisManager()
void ProcessDeleteDtor(const CFGDeleteDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, ExplodedNodeSet &Dst)
void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitCompoundLiteralExpr - Transfer function logic for compound literals.
SValBuilder & getSValBuilder()
void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)
VisitArrayInitLoopExpr - Transfer function for array init loop.
void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, const ProgramPointTag *tag=nullptr)
evalStore - Handle the semantics of a store via an assignment.
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, ExplodedNodeSet &PreVisit, ExplodedNodeSet &Dst)
void processIndirectGoto(IndirectGotoNodeBuilder &builder)
processIndirectGoto - Called by CoreEngine.
const NodeBuilderContext & getBuilderContext()
static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)
Retreives the size of the array in the pending ArrayInitLoopExpr.
void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred)
void markReachedMaxBlockCount(const Decl *D)
const Expr * getTarget() const
const LocationContext * getLocationContext() const
ProgramStateRef getState() const
ExplodedNode * generateNode(const iterator &I, ProgramStateRef State, bool isSink=false)
static bool isLocType(QualType T)
const CXXLifetimeExtendedObjectRegion * getCXXLifetimeExtendedObjectRegion(Expr const *Ex, ValueDecl const *VD, LocationContext const *LC)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by local referen...
const CXXTempObjectRegion * getCXXTempObjectRegion(Expr const *Ex, LocationContext const *LC)
const CXXLifetimeExtendedObjectRegion * getCXXStaticLifetimeExtendedObjectRegion(const Expr *Ex, ValueDecl const *VD)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by static refere...
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
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.
ProgramStateRef removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, const StackFrameContext *LCtx, SymbolReaper &SymReaper)
bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) const
bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) const
ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState)
MemRegionManager & getRegionManager()
ProgramStateRef getInitialState(const LocationContext *InitLoc)
StoreManager & getStoreManager()
Information about invalidation for a particular region/symbol.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
DefinedSVal getFunctionPointer(const FunctionDecl *func)
NonLoc makeIntValWithWidth(QualType ptrType, uint64_t integer)
NonLoc makeArrayIndex(uint64_t idx)
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
QualType getConditionType() const
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the 'this' object reference.
std::optional< SVal > getConstantVal(const Expr *E)
Returns the value of E, if it can be determined in a non-path-sensitive manner.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
bool isUnknownOrUndef() const
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const llvm::APSInt * getAsInteger() const
If this SVal is loc::ConcreteInt or nonloc::ConcreteInt, return a pointer to APSInt which is held in ...
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
This builder class is useful for generating nodes that resulted from visiting a statement.
ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
ExplodedNode * generateSink(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)
SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)
Evaluates a chain of derived-to-base casts through the path specified in Cast.
virtual SVal getLValueField(const FieldDecl *D, SVal Base)
SubRegion - A region that subsets another larger region.
ProgramStateRef getState() const
const Expr * getCondition() const
ExplodedNode * generateDefaultCaseNode(ProgramStateRef State, bool isSink=false)
ExplodedNode * generateCaseStmtNode(const iterator &I, ProgramStateRef State)
const LocationContext * getLocationContext() const
const SwitchStmt * getSwitch() const
A class responsible for cleaning up unused symbols.
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
SymbolicRegion - A special, "non-concrete" region.
TypedValueRegion - An abstract class representing regions having a typed value.
Represents symbolic expression that isn't a location.
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
llvm::DenseSet< const Decl * > SetOfConstDecls
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
@ PSK_DirectEscapeOnCall
The pointer has been passed to a function call directly.
@ PSK_EscapeOnBind
A pointer escapes due to binding its value to a location that the analyzer cannot track.
@ PSK_IndirectEscapeOnCall
The pointer has been passed to a function indirectly.
@ PSK_EscapeOther
The reason for pointer escape is unknown.
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State)
Updates the given ProgramState.
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, const LocationContext *LCtx, unsigned BlockCount, const Stmt *LoopStmt)
Get the states that result from widening the loop.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
bool isUnrolledState(ProgramStateRef State)
Returns if the given State indicates that is inside a completely unrolled loop.
ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx, ExplodedNode *Pred, unsigned maxVisitOnPath)
Updates the stack of loops contained by the ProgramState.
bool LE(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
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
@ 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.
An adjustment to be made to the temporary created when emitting a reference binding,...
@ DerivedToBaseAdjustment
@ MemberPointerAdjustment
Hints for figuring out of a call should be inlined during evalCall().
bool IsTemporaryCtorOrDtor
This call is a constructor or a destructor of a temporary value.
bool IsArrayCtorOrDtor
This call is a constructor or a destructor for a single element within an array, a part of array cons...
Traits for storing the call processing policy inside GDM.
DOTGraphTraits(bool isSimple=false)
static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G)
static bool nodeHasBugReport(const ExplodedNode *N)
static bool traverseHiddenNodes(const ExplodedNode *N, llvm::function_ref< void(const ExplodedNode *)> PreCallback, llvm::function_ref< void(const ExplodedNode *)> PostCallback, llvm::function_ref< bool(const ExplodedNode *)> Stop)
PreCallback: callback before break.
static bool isNodeHidden(const ExplodedNode *N, const ExplodedGraph *G)