clang: lib/StaticAnalyzer/Core/RegionStore.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
30#include "llvm/ADT/ImmutableMap.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/Support/raw_ostream.h"
33#include
34#include
35
36using namespace clang;
37using namespace ento;
38
39
40
41
42
43namespace {
44class BindingKey {
45public:
47private:
48 enum { Symbolic = 0x2 };
49
50 llvm::PointerIntPair<const MemRegion *, 2> P;
52
53
54
57 assert(r && Base && "Must have known regions.");
58 assert(getConcreteOffsetRegion() == Base && "Failed to store base region");
59 }
60
61
62 explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
64 assert(r && "Must have known regions.");
65 assert(getOffset() == offset && "Failed to store offset");
67 isa<ObjCIvarRegion, CXXDerivedObjectRegion>(r)) &&
68 "Not a base");
69 }
70
71public:
72 bool isDirect() const { return P.getInt() & Direct; }
73 bool isDefault() const { return !isDirect(); }
74 bool hasSymbolicOffset() const { return P.getInt() & Symbolic; }
75
78 assert(!hasSymbolicOffset());
80 }
81
82 const SubRegion *getConcreteOffsetRegion() const {
83 assert(hasSymbolicOffset());
85 }
86
87 const MemRegion *getBaseRegion() const {
88 if (hasSymbolicOffset())
89 return getConcreteOffsetRegion()->getBaseRegion();
91 }
92
93 void Profile(llvm::FoldingSetNodeID& ID) const {
94 ID.AddPointer(P.getOpaqueValue());
95 ID.AddInteger(Data);
96 }
97
98 static BindingKey Make(const MemRegion *R, Kind k);
99
100 bool operator<(const BindingKey &X) const {
101 if (P.getOpaqueValue() < X.P.getOpaqueValue())
102 return true;
103 if (P.getOpaqueValue() > X.P.getOpaqueValue())
104 return false;
106 }
107
108 bool operator==(const BindingKey &X) const {
109 return P.getOpaqueValue() == X.P.getOpaqueValue() &&
111 }
112
113 LLVM_DUMP_METHOD void dump() const;
114};
115}
116
117BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
120 return BindingKey(cast(R), cast(RO.getRegion()), k);
121
123}
124
125namespace llvm {
126static inline raw_ostream &operator<<(raw_ostream &Out, BindingKey K) {
127 Out << "\"kind\": \"" << (K.isDirect() ? "Direct" : "Default")
128 << "\", \"offset\": ";
129
130 if (!K.hasSymbolicOffset())
131 Out << K.getOffset();
132 else
133 Out << "null";
134
135 return Out;
136}
137
138}
139
140#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
141void BindingKey::dump() const { llvm::errs() << *this; }
142#endif
143
144
145
146
147
151
152typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
154
155namespace {
156class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,
157 ClusterBindings> {
158 ClusterBindings::Factory *CBFactory;
159
160
161
162
163
164
165
166
167
168
169 bool IsMainAnalysis;
170
171public:
172 typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
173 ParentTy;
174
175 RegionBindingsRef(ClusterBindings::Factory &CBFactory,
176 const RegionBindings::TreeTy *T,
177 RegionBindings::TreeTy::Factory *F,
178 bool IsMainAnalysis)
179 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(T, F),
180 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
181
182 RegionBindingsRef(const ParentTy &P,
183 ClusterBindings::Factory &CBFactory,
184 bool IsMainAnalysis)
185 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(P),
186 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
187
188 RegionBindingsRef add(key_type_ref K, data_type_ref D) const {
189 return RegionBindingsRef(static_cast<const ParentTy *>(this)->add(K, D),
190 *CBFactory, IsMainAnalysis);
191 }
192
193 RegionBindingsRef remove(key_type_ref K) const {
194 return RegionBindingsRef(static_cast<const ParentTy *>(this)->remove(K),
195 *CBFactory, IsMainAnalysis);
196 }
197
198 RegionBindingsRef addBinding(BindingKey K, SVal V) const;
199
200 RegionBindingsRef addBinding(const MemRegion *R,
201 BindingKey::Kind k, SVal V) const;
202
203 const SVal *lookup(BindingKey K) const;
204 const SVal *lookup(const MemRegion *R, BindingKey::Kind k) const;
206
207 RegionBindingsRef removeBinding(BindingKey K);
208
209 RegionBindingsRef removeBinding(const MemRegion *R,
210 BindingKey::Kind k);
211
212 RegionBindingsRef removeBinding(const MemRegion *R) {
213 return removeBinding(R, BindingKey::Direct).
214 removeBinding(R, BindingKey::Default);
215 }
216
217 std::optional getDirectBinding(const MemRegion *R) const;
218
219
220
221 std::optional getDefaultBinding(const MemRegion *R) const;
222
223
224 Store asStore() const {
225 llvm::PointerIntPair<Store, 1, bool> Ptr = {
226 asImmutableMap().getRootWithoutRetain(), IsMainAnalysis};
227 return reinterpret_cast<Store>(Ptr.getOpaqueValue());
228 }
229
230 bool isMainAnalysis() const {
231 return IsMainAnalysis;
232 }
233
234 void printJson(raw_ostream &Out, const char *NL = "\n",
235 unsigned int Space = 0, bool IsDot = false) const {
236 using namespace llvm;
237 DenseMap<const MemRegion *, std::string> StringifyCache;
238 auto ToString = [&StringifyCache](const MemRegion *R) {
239 auto [Place, Inserted] = StringifyCache.try_emplace(R);
240 if (!Inserted)
241 return Place->second;
242 std::string Res;
243 raw_string_ostream OS(Res);
244 OS << R;
245 Place->second = Res;
246 return Res;
247 };
248
249 using Cluster =
250 std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;
251 using Binding = std::pair<BindingKey, SVal>;
252
253 const auto MemSpaceBeforeRegionName = [&ToString](const Cluster *L,
254 const Cluster *R) {
255 if (isa(L->first) && !isa(R->first))
256 return true;
257 if (!isa(L->first) && isa(R->first))
258 return false;
259 return ToString(L->first) < ToString(R->first);
260 };
261
262 const auto SymbolicBeforeOffset = [&ToString](const BindingKey &L,
263 const BindingKey &R) {
264 if (L.hasSymbolicOffset() && !R.hasSymbolicOffset())
265 return true;
266 if (!L.hasSymbolicOffset() && R.hasSymbolicOffset())
267 return false;
268 if (L.hasSymbolicOffset() && R.hasSymbolicOffset())
269 return ToString(L.getRegion()) < ToString(R.getRegion());
270 return L.getOffset() < R.getOffset();
271 };
272
273 const auto DefaultBindingBeforeDirectBindings =
274 [&SymbolicBeforeOffset](const Binding *LPtr, const Binding *RPtr) {
275 const BindingKey &L = LPtr->first;
276 const BindingKey &R = RPtr->first;
277 if (L.isDefault() && !R.isDefault())
278 return true;
279 if (!L.isDefault() && R.isDefault())
280 return false;
281 assert(L.isDefault() == R.isDefault());
282 return SymbolicBeforeOffset(L, R);
283 };
284
285 const auto AddrOf = [](const auto &Item) { return &Item; };
286
287 std::vector<const Cluster *> SortedClusters;
288 SortedClusters.reserve(std::distance(begin(), end()));
289 append_range(SortedClusters, map_range(*this, AddrOf));
290 llvm::sort(SortedClusters, MemSpaceBeforeRegionName);
291
292 for (auto [Idx, C] : llvm::enumerate(SortedClusters)) {
293 const auto &[BaseRegion, Bindings] = *C;
294 Indent(Out, Space, IsDot)
295 << "{ \"cluster\": \"" << BaseRegion << "\", \"pointer\": \""
296 << (const void *)BaseRegion << "\", \"items\": [" << NL;
297
298 std::vector<const Binding *> SortedBindings;
299 SortedBindings.reserve(std::distance(Bindings.begin(), Bindings.end()));
300 append_range(SortedBindings, map_range(Bindings, AddrOf));
301 llvm::sort(SortedBindings, DefaultBindingBeforeDirectBindings);
302
303 ++Space;
304 for (auto [Idx, B] : llvm::enumerate(SortedBindings)) {
305 const auto &[Key, Value] = *B;
306 Indent(Out, Space, IsDot) << "{ " << Key << ", \"value\": ";
307 Value.printJson(Out, true);
308 Out << " }";
309 if (Idx != SortedBindings.size() - 1)
310 Out << ',';
311 Out << NL;
312 }
313 --Space;
314 Indent(Out, Space, IsDot) << "]}";
315 if (Idx != SortedClusters.size() - 1)
316 Out << ',';
317 Out << NL;
318 }
319 }
320
321 LLVM_DUMP_METHOD void dump() const { printJson(llvm::errs()); }
322};
323}
324
326
327std::optional
328RegionBindingsRef::getDirectBinding(const MemRegion *R) const {
329 const SVal *V = lookup(R, BindingKey::Direct);
330 return V ? std::optional(*V) : std::nullopt;
331}
332
333std::optional
334RegionBindingsRef::getDefaultBinding(const MemRegion *R) const {
335 const SVal *V = lookup(R, BindingKey::Default);
336 return V ? std::optional(*V) : std::nullopt;
337}
338
339RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K, SVal V) const {
341
344 (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
345
347 return add(Base, NewCluster);
348}
349
350
351RegionBindingsRef RegionBindingsRef::addBinding(const MemRegion *R,
352 BindingKey::Kind k,
354 return addBinding(BindingKey::Make(R, k), V);
355}
356
357const SVal *RegionBindingsRef::lookup(BindingKey K) const {
358 const ClusterBindings *Cluster = lookup(K.getBaseRegion());
359 if (!Cluster)
360 return nullptr;
361 return Cluster->lookup(K);
362}
363
364const SVal *RegionBindingsRef::lookup(const MemRegion *R,
365 BindingKey::Kind k) const {
366 return lookup(BindingKey::Make(R, k));
367}
368
369RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
372 if (!Cluster)
373 return *this;
374
375 ClusterBindings NewCluster = CBFactory->remove(*Cluster, K);
376 if (NewCluster.isEmpty())
378 return add(Base, NewCluster);
379}
380
381RegionBindingsRef RegionBindingsRef::removeBinding(const MemRegion *R,
382 BindingKey::Kind k){
383 return removeBinding(BindingKey::Make(R, k));
384}
385
386
387
388
389
390namespace {
391class InvalidateRegionsWorker;
392
393class RegionStoreManager : public StoreManager {
394public:
395 RegionBindings::Factory RBFactory;
396 mutable ClusterBindings::Factory CBFactory;
397
398 typedef std::vector SValListTy;
399private:
401 SValListTy> LazyBindingsMapTy;
402 LazyBindingsMapTy LazyBindingsMap;
403
404
405
406
407
408
409
410
411
412 unsigned SmallStructLimit;
413
414
415
416
417
418
419
420
421
422 unsigned SmallArrayLimit;
423
424
425
426 void populateWorkList(InvalidateRegionsWorker &W,
428 InvalidatedRegions *TopLevelRegions);
429
430public:
432 : StoreManager(mgr), RBFactory(mgr.getAllocator()),
433 CBFactory(mgr.getAllocator()), SmallStructLimit(0), SmallArrayLimit(0) {
434 ExprEngine &Eng = StateMgr.getOwningEngine();
436 SmallStructLimit = Options.RegionStoreSmallStructLimit;
437 SmallArrayLimit = Options.RegionStoreSmallArrayLimit;
438 }
439
440
441
442
445
446
447
448
449
450
451
453
454
455
457 bool IsMainAnalysis = false;
458 if (const auto *FD = dyn_cast(InitLoc->getDecl()))
459 IsMainAnalysis = FD->isMain() && !Ctx.getLangOpts().CPlusPlus;
460 return StoreRef(RegionBindingsRef(
461 RegionBindingsRef::ParentTy(RBFactory.getEmptyMap(), RBFactory),
462 CBFactory, IsMainAnalysis).asStore(), *this);
463 }
464
465
466
467
468 RegionBindingsRef invalidateGlobalRegion(MemRegion::Kind K, const Stmt *S,
469 unsigned Count,
471 RegionBindingsRef B,
472 InvalidatedRegions *Invalidated);
473
478 InvalidatedRegions *Invalidated,
479 InvalidatedRegions *InvalidatedTopLevel) override;
480
483
486 std::optional
489 std::optional
490 getSValFromInitListExpr(const InitListExpr *ILE,
493 SVal getSValFromStringLiteral(const StringLiteral *SL, uint64_t Offset,
495
496public:
497
499 return StoreRef(bind(getRegionBindings(store), LV, V).asStore(), *this);
500 }
501
503
504
505
508 RegionBindingsRef B = getRegionBindings(store);
509
510
511 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
512 "Double initialization!");
513 B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);
514 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);
515 }
516
517
518
520
521
522
523
524
525
526
527
528
529 if (const auto *BR = dyn_cast(R))
530 if (BR->getDecl()->isEmpty())
531 return StoreRef(store, *this);
532
533 RegionBindingsRef B = getRegionBindings(store);
534 SVal V = svalBuilder.makeZeroVal(Ctx.CharTy);
535 B = removeSubRegionBindings(B, cast(R));
536 B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);
537 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);
538 }
539
540
541
542
543
544
545
546
547
548
549
550 std::optional
553
554
557
558
561
562 std::optional
565
569
570
571
574 SVal DefaultVal);
575
576
577
578
580
582 getRegionBindings(store).manualRetain();
583 }
584
585
586
587
589 getRegionBindings(store).manualRelease();
590 }
591
593
594
595
596
597
598
599
600
601
602
603
604
605
606
608 return getBinding(getRegionBindings(S), L, T);
609 }
610
613 std::optional
615
617 RegionBindingsRef B = getRegionBindings(S);
618
619
620
622 }
623
625
627
629
631
633
635
639
640 SVal getLazyBinding(const SubRegion *LazyBindingRegion,
641 RegionBindingsRef LazyBinding);
642
643
644
645
646
647
651
652
653
654
655
656
657 std::optional
661
662
663
664
665
666 std::pair<Store, const SubRegion *>
668 const SubRegion *originalRegion);
669
670
671
672
673
674
675
676
677
678
679
681
682
683
684
685
686
687
690
691
692
693
694
695 RegionBindingsRef getRegionBindings(Store store) const {
696 llvm::PointerIntPair<Store, 1, bool> Ptr;
697 Ptr.setFromOpaqueValue(const_cast<void *>(store));
698 return RegionBindingsRef(
699 CBFactory,
700 static_cast<const RegionBindings::TreeTy *>(Ptr.getPointer()),
701 RBFactory.getTreeFactory(),
702 Ptr.getInt());
703 }
704
705 void printJson(raw_ostream &Out, Store S, const char *NL = "\n",
706 unsigned int Space = 0, bool IsDot = false) const override;
707
709 RegionBindingsRef B = getRegionBindings(store);
710 for (const auto &[Region, Cluster] : B) {
711 for (const auto &[Key, Value] : Cluster) {
712 if (!Key.isDirect())
713 continue;
714 if (const SubRegion *R = dyn_cast(Key.getRegion())) {
715
716 if (!f.HandleBinding(*this, store, R, Value))
717 return;
718 }
719 }
720 }
721 }
722};
723
724}
725
726
727
728
729
730std::unique_ptr
732 return std::make_unique(StMgr);
733}
734
735
736
737
738
739namespace {
740
741
742enum GlobalsFilterKind {
743
744 GFK_None,
745
746 GFK_SystemOnly,
747
748 GFK_All
749};
750
751template
752class ClusterAnalysis {
753protected:
754 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
755 typedef const MemRegion * WorkListElement;
757
759
761
762 RegionStoreManager &RM;
765
766 RegionBindingsRef B;
767
768
769protected:
771 return B.lookup(R);
772 }
773
774
775
776
777 bool includeEntireMemorySpace(const MemRegion *Base) {
778 return false;
779 }
780
781public:
783 RegionBindingsRef b)
784 : RM(rm), Ctx(StateMgr.getContext()),
785 svalBuilder(StateMgr.getSValBuilder()), B(std::move(b)) {}
786
787 RegionBindingsRef getRegionBindings() const { return B; }
788
789 bool isVisited(const MemRegion *R) {
790 return Visited.count(getCluster(R));
791 }
792
793 void GenerateClusters() {
794
795 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
796 RI != RE; ++RI){
798
800 assert(!Cluster.isEmpty() && "Empty clusters should be removed");
801 static_cast<DERIVED*>(this)->VisitAddedToCluster(Base, Cluster);
802
803
804
805 if (static_cast<DERIVED*>(this)->includeEntireMemorySpace(Base))
806 AddToWorkList(WorkListElement(Base), &Cluster);
807 }
808 }
809
810 bool AddToWorkList(WorkListElement E, const ClusterBindings *C) {
811 if (C && .insert(C).second)
812 return false;
813 WL.push_back(E);
814 return true;
815 }
816
817 bool AddToWorkList(const MemRegion *R) {
818 return static_cast<DERIVED*>(this)->AddToWorkList(R);
819 }
820
821 void RunWorkList() {
822 while (!WL.empty()) {
823 WorkListElement E = WL.pop_back_val();
825
826 static_cast<DERIVED*>(this)->VisitCluster(BaseR, getCluster(BaseR));
827 }
828 }
829
832
834 bool Flag) {
835 static_cast<DERIVED*>(this)->VisitCluster(BaseR, C);
836 }
837};
838}
839
840
841
842
843
844bool RegionStoreManager::scanReachableSymbols(Store S, const MemRegion *R,
846 assert(R == R->getBaseRegion() && "Should only be called for base regions");
847 RegionBindingsRef B = getRegionBindings(S);
849
850 if (!Cluster)
851 return true;
852
853 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
854 RI != RE; ++RI) {
855 if (!Callbacks.scan(RI.getData()))
856 return false;
857 }
858
859 return true;
860}
861
864}
865
867
869 assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
870
871 const MemRegion *Base = K.getConcreteOffsetRegion();
872 const MemRegion *R = K.getRegion();
873
874 while (R != Base) {
875 if (const FieldRegion *FR = dyn_cast(R))
877 Fields.push_back(FR->getDecl());
878
879 R = cast(R)->getSuperRegion();
880 }
881}
882
884 assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
885
886 if (Fields.empty())
887 return true;
888
891
892 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
893 if (Delta >= 0)
894 return std::equal(FieldsInBindingKey.begin() + Delta,
895 FieldsInBindingKey.end(),
896 Fields.begin());
897 else
898 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
899 Fields.begin() - Delta);
900}
901
902
903
904
905
906
907
908
909
910
911static void
914 const SubRegion *Top, BindingKey TopKey,
915 bool IncludeAllDefaultBindings) {
917 if (TopKey.hasSymbolicOffset()) {
919 Top = TopKey.getConcreteOffsetRegion();
920 TopKey = BindingKey::Make(Top, BindingKey::Default);
921 }
922
923
924 uint64_t Length = UINT64_MAX;
926 if (std::optionalnonloc::ConcreteInt ExtentCI =
928 const llvm::APSInt &ExtentInt = ExtentCI->getValue();
929 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
930
932 } else if (const FieldRegion *FR = dyn_cast(Top)) {
933 if (FR->getDecl()->isBitField())
934 Length = FR->getDecl()->getBitWidthValue();
935 }
936
937 for (const auto &StoreEntry : Cluster) {
938 BindingKey NextKey = StoreEntry.first;
939 if (NextKey.getRegion() == TopKey.getRegion()) {
940
941
942
943
944
945 if (NextKey.getOffset() > TopKey.getOffset() &&
946 NextKey.getOffset() - TopKey.getOffset() < Length) {
947
948
949 Bindings.push_back(StoreEntry);
950
951 } else if (NextKey.getOffset() == TopKey.getOffset()) {
952
953
954
955
956
957
958 if (IncludeAllDefaultBindings || NextKey.isDirect())
959 Bindings.push_back(StoreEntry);
960 }
961
962 } else if (NextKey.hasSymbolicOffset()) {
963 const MemRegion *Base = NextKey.getConcreteOffsetRegion();
965
966
967
968 if (IncludeAllDefaultBindings || NextKey.isDirect())
970 Bindings.push_back(StoreEntry);
971 } else if (const SubRegion *BaseSR = dyn_cast(Base)) {
972
973
974 if (BaseSR->isSubRegionOf(Top))
976 Bindings.push_back(StoreEntry);
977 }
978 }
979 }
980}
981
982static void
985 const SubRegion *Top, bool IncludeAllDefaultBindings) {
987 BindingKey::Make(Top, BindingKey::Default),
988 IncludeAllDefaultBindings);
989}
990
991RegionBindingsRef
994 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
996
997 if (Top == ClusterHead) {
998
999 return B.remove(Top);
1000 }
1001
1003 if (!Cluster) {
1004
1005
1006 if (TopKey.hasSymbolicOffset()) {
1007 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1008 return B.addBinding(Concrete, BindingKey::Default, UnknownVal());
1009 }
1010 return B;
1011 }
1012
1015 false);
1016
1018 for (BindingKey Key : llvm::make_first_range(Bindings))
1019 Result = Result.remove(Key);
1020
1021
1022
1023
1024
1025 if (TopKey.hasSymbolicOffset()) {
1026 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1027 Result = Result.add(BindingKey::Make(Concrete, BindingKey::Default),
1029 }
1030
1031 if (Result.isEmpty())
1032 return B.remove(ClusterHead);
1033 return B.add(ClusterHead, Result.asImmutableMap());
1034}
1035
1036namespace {
1037class InvalidateRegionsWorker : public ClusterAnalysis
1038{
1039 const Stmt *S;
1040 unsigned Count;
1045 GlobalsFilterKind GlobalsFilter;
1046public:
1047 InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
1048 RegionBindingsRef b, const Stmt *S, unsigned count,
1052 GlobalsFilterKind GFK)
1053 : ClusterAnalysis(rm, stateMgr, b), S(S),
1054 Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
1055 GlobalsFilter(GFK) {}
1056
1058 void VisitBinding(SVal V);
1059
1060 using ClusterAnalysis::AddToWorkList;
1061
1062 bool AddToWorkList(const MemRegion *R);
1063
1064
1065
1066 bool includeEntireMemorySpace(const MemRegion *Base);
1067
1068
1069
1070 bool isInitiallyIncludedGlobalRegion(const MemRegion *R);
1071};
1072}
1073
1074bool InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
1075 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1078 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
1079}
1080
1081void InvalidateRegionsWorker::VisitBinding(SVal V) {
1082
1083 if (SymbolRef Sym = V.getAsSymbol())
1084 IS.insert(Sym);
1085
1086 if (const MemRegion *R = V.getAsRegion()) {
1087 AddToWorkList(R);
1088 return;
1089 }
1090
1091
1092 if (std::optionalnonloc::LazyCompoundVal LCS =
1094
1095
1096
1097 for (SVal V : RM.getInterestingValues(*LCS))
1098 if (!isanonloc::LazyCompoundVal(V))
1099 VisitBinding(V);
1100
1101 return;
1102 }
1103}
1104
1105void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
1107
1108 bool PreserveRegionsContents =
1109 ITraits.hasTrait(baseR,
1111
1112 if (C) {
1113 for (SVal Val : llvm::make_second_range(*C))
1114 VisitBinding(Val);
1115
1116
1117 if (!PreserveRegionsContents)
1118 B = B.remove(baseR);
1119 }
1120
1121 if (const auto *TO = dyn_cast(baseR)) {
1122 if (const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
1123
1124
1125
1126
1127 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
1128 using namespace ast_matchers;
1129
1130 const char *DeclBind = "DeclBind";
1132 to(varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
1133 auto Matches =
1134 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
1135 RD->getASTContext());
1136
1138 auto *VD = Match.getNodeAs<VarDecl>(DeclBind);
1140 RM.getRegionManager().getVarRegion(VD, LCtx);
1141 AddToWorkList(ToInvalidate);
1142 }
1143 }
1144 }
1145 }
1146
1147
1148
1149 if (const BlockDataRegion *BR = dyn_cast(baseR)) {
1150 for (auto Var : BR->referenced_vars()) {
1151 const VarRegion *VR = Var.getCapturedRegion();
1154 AddToWorkList(VR);
1155 }
1157
1158
1159
1160
1161
1163 if (std::optional L = V.getAs<Loc>()) {
1165 AddToWorkList(LR);
1166 }
1167 }
1168 }
1169 return;
1170 }
1171
1172
1173 if (const SymbolicRegion *SR = dyn_cast(baseR))
1174 IS.insert(SR->getSymbol());
1175
1176
1177 if (PreserveRegionsContents)
1178 return;
1179
1180
1181 if (Regions)
1182 Regions->push_back(baseR);
1183
1184 if (isa<AllocaRegion, SymbolicRegion>(baseR)) {
1185
1186
1189 B = B.addBinding(baseR, BindingKey::Default, V);
1190 return;
1191 }
1192
1194 return;
1195
1198
1199 if (isInitiallyIncludedGlobalRegion(baseR)) {
1200
1201
1202
1203 return;
1204 }
1205
1207
1208
1211 B = B.addBinding(baseR, BindingKey::Default, V);
1212 return;
1213 }
1214
1216 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1217 baseR,
1219
1220 if (doNotInvalidateSuperRegion) {
1221
1222
1223 std::optional<uint64_t> NumElements;
1224
1225
1226 if (const ConstantArrayType *CAT = dyn_cast(AT))
1227 NumElements = CAT->getZExtSize();
1228 if (!NumElements)
1229 goto conjure_default;
1230 QualType ElementTy = AT->getElementType();
1235
1236
1237 if (SuperR)
1238 AddToWorkList(SuperR);
1239 goto conjure_default;
1240 }
1241
1243 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
1244 bool UpperOverflow = UpperOffset < LowerOffset;
1245
1246
1247
1248 if (!SuperR)
1249 goto conjure_default;
1250
1252 if ()
1253 goto conjure_default;
1254
1255 for (const auto &[BK, V] : *C) {
1256 std::optional<uint64_t> ROffset =
1257 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
1258
1259
1260
1261 if (!ROffset ||
1262 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
1263 (UpperOverflow &&
1264 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
1265 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
1266 B = B.removeBinding(BK);
1267
1268
1269 const MemRegion *R = V.getAsRegion();
1270 if (isa_and_nonnull(R))
1271 VisitBinding(V);
1272 }
1273 }
1274 }
1275 conjure_default:
1276
1278 baseR, S, LCtx, AT->getElementType(), Count);
1279 B = B.addBinding(baseR, BindingKey::Default, V);
1280 return;
1281 }
1282
1286 B = B.addBinding(baseR, BindingKey::Direct, V);
1287}
1288
1289bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
1291 switch (GlobalsFilter) {
1292 case GFK_None:
1293 return false;
1294 case GFK_SystemOnly:
1295 return isa(R->getMemorySpace());
1296 case GFK_All:
1297 return isa(R->getMemorySpace());
1298 }
1299
1300 llvm_unreachable("unknown globals filter");
1301}
1302
1303bool InvalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
1304 if (isInitiallyIncludedGlobalRegion(Base))
1305 return true;
1306
1308 return ITraits.hasTrait(MemSpace,
1310}
1311
1312RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
1315 InvalidatedRegions *Invalidated) {
1316
1317
1320 svalBuilder.conjureSymbolVal( (const void *)GS, S, LCtx,
1321 Ctx.IntTy, Count);
1322
1323 B = B.removeBinding(GS)
1324 .addBinding(BindingKey::Make(GS, BindingKey::Default), V);
1325
1326
1327
1328 if (Invalidated)
1329 Invalidated->push_back(GS);
1330
1331 return B;
1332}
1333
1334void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
1336 InvalidatedRegions *TopLevelRegions) {
1339 for (SVal S : getInterestingValues(*LCS))
1340 if (const MemRegion *R = S.getAsRegion())
1341 W.AddToWorkList(R);
1342
1343 continue;
1344 }
1345
1346 if (const MemRegion *R = V.getAsRegion()) {
1347 if (TopLevelRegions)
1348 TopLevelRegions->push_back(R);
1349 W.AddToWorkList(R);
1350 continue;
1351 }
1352 }
1353}
1354
1355StoreRef RegionStoreManager::invalidateRegions(
1359 InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
1360 GlobalsFilterKind GlobalsFilter;
1362 if (Call->isInSystemHeader())
1363 GlobalsFilter = GFK_SystemOnly;
1364 else
1365 GlobalsFilter = GFK_All;
1366 } else {
1367 GlobalsFilter = GFK_None;
1368 }
1369
1370 RegionBindingsRef B = getRegionBindings(store);
1371 InvalidateRegionsWorker W(*this, StateMgr, B, S, Count, LCtx, IS, ITraits,
1372 Invalidated, GlobalsFilter);
1373
1374
1375 W.GenerateClusters();
1376
1377
1378 populateWorkList(W, Values, TopLevelRegions);
1379
1380 W.RunWorkList();
1381
1382
1383 B = W.getRegionBindings();
1384
1385
1386
1387
1388
1389 switch (GlobalsFilter) {
1390 case GFK_All:
1391 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, S,
1392 Count, LCtx, B, Invalidated);
1393 [[fallthrough]];
1394 case GFK_SystemOnly:
1395 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, S, Count,
1396 LCtx, B, Invalidated);
1397 [[fallthrough]];
1398 case GFK_None:
1399 break;
1400 }
1401
1402 return StoreRef(B.asStore(), *this);
1403}
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {
1416 if (isaloc::ConcreteInt(Array))
1417 return Array;
1418
1419 if (!isaloc::MemRegionVal(Array))
1421
1425 return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
1426}
1427
1428
1429
1430
1431
1433 assert(!isa(L) && "location unknown");
1434 assert(!isa(L) && "location undefined");
1435
1436
1437
1438
1439
1440
1441
1444 }
1447 }
1448
1450
1451 if (isa(MR)) {
1453 }
1454
1455
1456 if (T.isNull()) {
1457 if (const auto *TVR = dyn_cast(MR))
1458 T = TVR->getValueType();
1459 else if (const auto *TR = dyn_cast(MR))
1461 else if (const auto *SR = dyn_cast(MR))
1462 T = SR->getPointeeStaticType();
1463 }
1464 assert(.isNull() && "Unable to auto-detect binding type!");
1465 assert(->isVoidType() && "Attempting to dereference a void pointer!");
1466
1467 if (!isa(MR))
1468 MR = GetElementZeroRegion(cast(MR), T);
1469
1470
1471
1474
1475
1476
1479
1480
1481
1482
1483
1484
1485
1486
1487
1489 return getBindingForStruct(B, R);
1490
1491
1493 return createLazyBinding(B, R);
1494
1497 return getBindingForArray(B, R);
1498 else
1500 }
1501
1502
1505
1506 if (const FieldRegion* FR = dyn_cast(R))
1507 return svalBuilder.evalCast(getBindingForField(B, FR), T, QualType{});
1508
1509 if (const ElementRegion* ER = dyn_cast(R)) {
1510
1511
1512
1513
1514
1515 return svalBuilder.evalCast(getBindingForElement(B, ER), T, QualType{});
1516 }
1517
1518 if (const ObjCIvarRegion *IVR = dyn_cast(R)) {
1519
1520
1521
1522
1523
1524
1525 return svalBuilder.evalCast(getBindingForObjCIvar(B, IVR), T, QualType{});
1526 }
1527
1528 if (const VarRegion *VR = dyn_cast(R)) {
1529
1530
1531
1532
1533
1534
1535 return svalBuilder.evalCast(getBindingForVar(B, VR), T, QualType{});
1536 }
1537
1538 const SVal *V = B.lookup(R, BindingKey::Direct);
1539
1540
1541 if (V)
1542 return *V;
1543
1544
1545
1546
1548
1549
1550
1551
1553 }
1554
1555
1557}
1558
1561 if (const TypedValueRegion *TVR = dyn_cast(R))
1562 RegionTy = TVR->getValueType();
1563
1564 if (const SymbolicRegion *SR = dyn_cast(R))
1565 RegionTy = SR->getSymbol()->getType();
1566
1567 return RegionTy;
1568}
1569
1570
1571
1572
1573
1574
1575
1576
1577static std::optionalnonloc::LazyCompoundVal
1579 const SubRegion *R, bool AllowSubregionBindings) {
1580 std::optional V = B.getDefaultBinding(R);
1581 if ()
1582 return std::nullopt;
1583
1584 std::optionalnonloc::LazyCompoundVal LCV =
1586 if (!LCV)
1587 return std::nullopt;
1588
1589
1590
1592 if (!RegionTy.isNull() &&
1594 QualType SourceRegionTy = LCV->getRegion()->getValueType();
1596 return std::nullopt;
1597 }
1598
1599 if (!AllowSubregionBindings) {
1600
1601
1604 true);
1606 return std::nullopt;
1607 }
1608
1609 return *LCV;
1610}
1611
1612std::pair<Store, const SubRegion *>
1615 const SubRegion *originalRegion) {
1616 if (originalRegion != R) {
1617 if (std::optionalnonloc::LazyCompoundVal V =
1619 return std::make_pair(V->getStore(), V->getRegion());
1620 }
1621
1622 typedef std::pair<Store, const SubRegion *> StoreRegionPair;
1623 StoreRegionPair Result = StoreRegionPair();
1624
1625 if (const ElementRegion *ER = dyn_cast(R)) {
1626 Result = findLazyBinding(B, cast(ER->getSuperRegion()),
1627 originalRegion);
1628
1629 if (Result.second)
1630 Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);
1631
1632 } else if (const FieldRegion *FR = dyn_cast(R)) {
1633 Result = findLazyBinding(B, cast(FR->getSuperRegion()),
1634 originalRegion);
1635
1636 if (Result.second)
1637 Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);
1638
1640 dyn_cast(R)) {
1641
1642
1643 Result = findLazyBinding(B, cast(BaseReg->getSuperRegion()),
1644 originalRegion);
1645
1646 if (Result.second)
1647 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
1648 Result.second);
1649 }
1650
1651 return Result;
1652}
1653
1654
1655
1656
1657
1658
1661 assert(CAT && "ConstantArrayType should not be null");
1664 do {
1666 } while ((CAT = dyn_cast(CAT->getElementType())));
1667 return Extents;
1668}
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684static std::pair<SmallVector<SVal, 2>, const MemRegion *>
1686 assert(ER && "ConstantArrayType should not be null");
1689 do {
1690 SValOffsets.push_back(ER->getIndex());
1692 ER = dyn_cast(Base);
1693 } while (ER);
1694 return {SValOffsets, Base};
1695}
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718static std::optional
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739 DstOffsets.resize(SrcOffsets.size());
1740 auto ExtentIt = ArrayExtents.begin();
1741 auto OffsetIt = DstOffsets.begin();
1742
1743 for (SVal V : llvm::reverse(SrcOffsets)) {
1745
1746 const llvm::APSInt &Offset = CI->getValue();
1747 if (Offset.isNegative() || Offset.uge(*(ExtentIt++)))
1749
1750 *(OffsetIt++) = Offset.getZExtValue();
1751 continue;
1752 }
1753
1754
1755
1757 }
1758 return std::nullopt;
1759}
1760
1761std::optional RegionStoreManager::getConstantValFromConstArrayInitializer(
1763 assert(R && "ElementRegion should not be null");
1764
1765
1769 const VarRegion *VR = dyn_cast(Base);
1770 if (!VR)
1771 return std::nullopt;
1772
1773 assert(!SValOffsets.empty() && "getElementRegionOffsets guarantees the "
1774 "offsets vector is not empty.");
1775
1776
1777
1782 return std::nullopt;
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1794
1795
1797 return std::nullopt;
1798
1799
1800
1802 if (!CAT)
1803 return std::nullopt;
1804
1805
1807
1808
1809
1810
1811
1812
1813
1814 if (SValOffsets.size() != Extents.size())
1815 return std::nullopt;
1816
1819 SValOffsets, Extents, ConcreteOffsets))
1820 return *V;
1821
1822
1823
1824
1825 if (const auto *ILE = dyn_cast(Init))
1826 return getSValFromInitListExpr(ILE, ConcreteOffsets, R->getElementType());
1827
1828
1829
1830
1831 if (const auto *SL = dyn_cast(Init))
1832 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
1834
1835
1836
1837 return std::nullopt;
1838}
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857std::optional RegionStoreManager::getSValFromInitListExpr(
1860 assert(ILE && "InitListExpr should not be null");
1861
1862 for (uint64_t Offset : Offsets) {
1863
1864
1865
1866
1867
1869 if (const auto *SL = dyn_cast(ILE->getInit(0)))
1870 return getSValFromStringLiteral(SL, Offset, ElemT);
1871
1872
1873
1874
1877
1879 const auto *IL = dyn_cast(E);
1880 if (!IL)
1881
1882
1884
1885
1886 ILE = IL;
1887 }
1888
1889 assert(ILE);
1890
1891
1892
1893 return std::nullopt;
1894}
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921SVal RegionStoreManager::getSValFromStringLiteral(const StringLiteral *SL,
1922 uint64_t Offset,
1924 assert(SL && "StringLiteral should not be null");
1925
1926
1927
1929 return svalBuilder.makeIntVal(Code, ElemT);
1930}
1931
1935 assert(BaseRegion);
1940 if (const std::optional &ParentValue =
1941 B.getDirectBinding(BaseRegion)) {
1942 if (SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
1944
1945 if (ParentValue->isUndef())
1947
1948
1949
1951 }
1952 }
1953 }
1954 return std::nullopt;
1955}
1956
1959
1960 if (const std::optional &V = B.getDirectBinding(R))
1961 return *V;
1962
1964
1965
1966 if (const StringRegion *StrR = dyn_cast(superR)) {
1967
1968
1969
1974 const llvm::APSInt &Idx = CI->getValue();
1975 if (Idx < 0)
1977 const StringLiteral *SL = StrR->getStringLiteral();
1978 return getSValFromStringLiteral(SL, Idx.getZExtValue(), T);
1979 }
1980 } else if (isa<ElementRegion, VarRegion>(superR)) {
1981 if (std::optional V = getConstantValFromConstArrayInitializer(B, R))
1982 return *V;
1983 }
1984
1985
1986 if (isa(superR))
1988
1989
1990
1991
1992
1993
1994
1996
1997
2000
2003 return *V;
2004
2005 return getBindingForFieldOrElementCommon(B, R, R->getElementType());
2006}
2007
2010
2011
2012 if (const std::optional &V = B.getDirectBinding(R))
2013 return *V;
2014
2015
2019 if (const auto *VR = dyn_cast(superR)) {
2023
2024
2025
2029 if (const auto *InitList = dyn_cast(Init)) {
2030 if (Index < InitList->getNumInits()) {
2031 if (const Expr *FieldInit = InitList->getInit(Index))
2032 if (std::optional V = svalBuilder.getConstantVal(FieldInit))
2033 return *V;
2034 } else {
2036 }
2037 }
2038 }
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056 if (const auto *Base = dyn_cast(R->getBaseRegion()))
2058 return *V;
2059
2060 return getBindingForFieldOrElementCommon(B, R, Ty);
2061}
2062
2063std::optional RegionStoreManager::getBindingForDerivedDefaultValue(
2066
2067 if (const std::optional &D = B.getDefaultBinding(superR)) {
2071
2074
2076 return val;
2077
2078
2079
2080 if (isa<nonloc::LazyCompoundVal, nonloc::CompoundVal>(val))
2081 return val;
2082
2083 llvm_unreachable("Unknown default value");
2084 }
2085
2086 return std::nullopt;
2087}
2088
2089SVal RegionStoreManager::getLazyBinding(const SubRegion *LazyBindingRegion,
2090 RegionBindingsRef LazyBinding) {
2091 SVal Result;
2092 if (const ElementRegion *ER = dyn_cast(LazyBindingRegion))
2093 Result = getBindingForElement(LazyBinding, ER);
2094 else
2095 Result = getBindingForField(LazyBinding,
2096 cast(LazyBindingRegion));
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112 if (Result.isUndef())
2114
2115 return Result;
2116}
2117
2122
2123
2124
2125
2126
2127 Store lazyBindingStore = nullptr;
2128 const SubRegion *lazyBindingRegion = nullptr;
2129 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
2130 if (lazyBindingRegion)
2131 return getLazyBinding(lazyBindingRegion,
2132 getRegionBindings(lazyBindingStore));
2133
2134
2135
2136 bool hasSymbolicIndex = false;
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152 bool hasPartialLazyBinding = false;
2153
2155 while (SR) {
2157 if (std::optional D =
2158 getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
2160 hasPartialLazyBinding = true;
2161 break;
2162 }
2163
2164 return *D;
2165 }
2166
2168 NonLoc index = ER->getIndex();
2170 hasSymbolicIndex = true;
2171 }
2172
2173
2174
2175 SR = dyn_cast(Base);
2176 }
2177
2179 if (isa(R)) {
2180
2181
2184 if (typedSuperR->getValueType()->isVectorType())
2186 }
2187 }
2188
2189
2190
2191
2192
2193 if (hasSymbolicIndex)
2195
2196
2197
2198
2199 if (!hasPartialLazyBinding && !isa(R->getBaseRegion())) {
2200 if (const std::optional &V = B.getDefaultBinding(R))
2201 return *V;
2203 }
2204 }
2205
2206
2208}
2209
2212
2213 if (const std::optional &V = B.getDirectBinding(R))
2214 return *V;
2215
2217
2218
2219 if (const std::optional &V = B.getDefaultBinding(superR)) {
2220 if (SymbolRef parentSym = V->getAsSymbol())
2222
2223
2225 }
2226
2227 return getBindingForLazySymbol(R);
2228}
2229
2232
2233
2234 if (std::optional V = B.getDirectBinding(R))
2235 return *V;
2236
2237 if (std::optional V = B.getDefaultBinding(R))
2238 return *V;
2239
2240
2243
2244
2245 if (isa(MS))
2247
2248
2252 return *V;
2253
2254
2255
2256
2258 }
2259 }
2260
2261
2262
2263 if (isa(MS))
2265
2266 if (isa(MS)) {
2268
2269
2270 if (B.isMainAnalysis())
2273 return *V;
2274
2275
2276
2277
2278
2279 if (isa(MS))
2281
2282 if (std::optional V = getBindingForDerivedDefaultValue(B, MS, R, T)) {
2284 return *V;
2285 }
2286
2288 }
2289
2291}
2292
2293SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) {
2294
2296}
2297
2298const RegionStoreManager::SValListTy &
2300
2301 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.getCVData());
2302 if (I != LazyBindingsMap.end())
2303 return I->second;
2304
2305
2306 SValListTy List;
2307
2309 RegionBindingsRef B = getRegionBindings(LCV.getStore());
2310
2311
2312
2314 if (!Cluster)
2315 return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
2316
2319 true);
2320 for (SVal V : llvm::make_second_range(Bindings)) {
2321 if (V.isUnknownOrUndef() || V.isConstant())
2322 continue;
2323
2325 const SValListTy &InnerList = getInterestingValues(*InnerLCV);
2326 List.insert(List.end(), InnerList.begin(), InnerList.end());
2327 }
2328
2329 List.push_back(V);
2330 }
2331
2332 return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
2333}
2334
2337 if (std::optionalnonloc::LazyCompoundVal V =
2339 return *V;
2340
2342}
2343
2349
2350
2351
2352
2353
2354
2355
2356
2357 if (std::optional Val = getUniqueDefaultBinding(B, R))
2358 return *Val;
2359 return createLazyBinding(B, R);
2360}
2361
2365 "Only constant array types can have compound bindings.");
2366
2367 return createLazyBinding(B, R);
2368}
2369
2370bool RegionStoreManager::includedInBindings(Store store,
2371 const MemRegion *region) const {
2372 RegionBindingsRef B = getRegionBindings(store);
2374
2375
2376 if (B.lookup(region))
2377 return true;
2378
2379
2380 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
2382 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
2383 CI != CE; ++CI) {
2385 if (const MemRegion *R = D.getAsRegion())
2387 return true;
2388 }
2389 }
2390
2391 return false;
2392}
2393
2394
2395
2396
2397
2400 if (const MemRegion* R = LV->getRegion())
2401 return StoreRef(getRegionBindings(ST).removeBinding(R)
2402 .asImmutableMap()
2403 .getRootWithoutRetain(),
2404 *this);
2405
2407}
2408
2409RegionBindingsRef
2411
2413 if (!MemRegVal)
2414 return B;
2415
2416 const MemRegion *R = MemRegVal->getRegion();
2417
2418
2419 if (const TypedValueRegion* TR = dyn_cast(R)) {
2422 return bindArray(B, TR, V);
2424 return bindStruct(B, TR, V);
2426 return bindVector(B, TR, V);
2428 return bindAggregate(B, TR, V);
2429 }
2430
2431
2432
2433 if (const auto *SymReg = dyn_cast(R)) {
2434 QualType Ty = SymReg->getPointeeStaticType();
2436 Ty = StateMgr.getContext().CharTy;
2437 R = GetElementZeroRegion(SymReg, Ty);
2438 }
2439
2440 assert((!isa(R) || !B.lookup(R)) &&
2441 "'this' pointer is not an l-value and is not assignable");
2442
2443
2444 RegionBindingsRef NewB = removeSubRegionBindings(B, cast(R));
2445
2446
2447 auto KeyKind = isanonloc::LazyCompoundVal(V) ? BindingKey::Default
2448 : BindingKey::Direct;
2449 return NewB.addBinding(BindingKey::Make(R, KeyKind), V);
2450}
2451
2452RegionBindingsRef
2457
2463
2464
2466 }
2467 else {
2468
2469
2470
2471
2474 }
2475
2476 return B.addBinding(R, BindingKey::Default, V);
2477}
2478
2479std::optional RegionStoreManager::tryBindSmallArray(
2482
2483 auto CAT = dyn_cast(AT);
2484
2485
2486 if (!CAT)
2487 return std::nullopt;
2488
2491 return std::nullopt;
2492
2493
2495 if (ArrSize > SmallArrayLimit)
2496 return std::nullopt;
2497
2498 RegionBindingsRef NewB = B;
2499
2500 for (uint64_t i = 0; i < ArrSize; ++i) {
2503 MRMgr.getElementRegion(Ty, Idx, LCV.getRegion(), Ctx);
2504 SVal V = getBindingForElement(getRegionBindings(LCV.getStore()), SrcER);
2505
2506 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2508 }
2509
2510 return NewB;
2511}
2512
2513RegionBindingsRef
2517
2520 std::optional<uint64_t> Size;
2521
2522 if (const ConstantArrayType* CAT = dyn_cast(AT))
2524
2525
2526
2527
2530 return bindAggregate(B, R, V);
2531 }
2532
2533
2534 if (std::optionalnonloc::LazyCompoundVal LCV =
2536 if (std::optional NewB =
2537 tryBindSmallArray(B, R, AT, *LCV))
2538 return *NewB;
2539
2540 return bindAggregate(B, R, Init);
2541 }
2542
2543 if (Init.isUnknown())
2544 return bindAggregate(B, R, UnknownVal());
2545
2546
2550
2551 RegionBindingsRef NewB(B);
2552
2553 for (; Size ? i < *Size : true; ++i, ++VI) {
2554
2555 if (VI == VE)
2556 break;
2557
2559 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2560
2562 NewB = bindStruct(NewB, ER, *VI);
2564 NewB = bindArray(NewB, ER, *VI);
2565 else
2567 }
2568
2569
2570
2571
2572 if (!Size || i < *Size)
2573 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2574
2575 return NewB;
2576}
2577
2583
2584
2585 if (isa<nonloc::LazyCompoundVal, nonloc::SymbolVal>(V))
2586 return bindAggregate(B, R, V);
2587
2588
2589
2590
2591 if (!isanonloc::CompoundVal(V)) {
2592 return bindAggregate(B, R, UnknownVal());
2593 }
2594
2598 unsigned index = 0, numElements = VT->getNumElements();
2599 RegionBindingsRef NewB(B);
2600
2601 for ( ; index != numElements ; ++index) {
2602 if (VI == VE)
2603 break;
2604
2606 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2607
2609 NewB = bindArray(NewB, ER, *VI);
2611 NewB = bindStruct(NewB, ER, *VI);
2612 else
2614 }
2615 return NewB;
2616}
2617
2618std::optional
2622 return std::nullopt;
2623
2624 const auto *Cluster = B.lookup(R);
2625 if (!Cluster || !llvm::hasSingleElement(*Cluster))
2626 return std::nullopt;
2627
2628 const auto [Key, Value] = *Cluster->begin();
2629 return Key.isDirect() ? std::optional{} : Value;
2630}
2631
2632std::optional
2635 return getUniqueDefaultBinding(B, LCV.getRegion());
2636}
2637
2638std::optional RegionStoreManager::tryBindSmallStruct(
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655 if (std::optional Val = getUniqueDefaultBinding(LCV)) {
2656 return B.addBinding(BindingKey::Make(R, BindingKey::Default), Val.value());
2657 }
2658
2660
2661 if (const CXXRecordDecl *Class = dyn_cast(RD))
2662 if (Class->getNumBases() != 0 || Class->getNumVBases() != 0)
2663 return std::nullopt;
2664
2665 for (const auto *FD : RD->fields()) {
2667 continue;
2668
2669
2670
2671 if (Fields.size() == SmallStructLimit)
2672 return std::nullopt;
2673
2675
2676
2679 continue;
2680
2682 return std::nullopt;
2683
2684 Fields.push_back(FD);
2685 }
2686
2687 RegionBindingsRef NewB = B;
2688
2689 for (const FieldDecl *Field : Fields) {
2691 SVal V = getBindingForField(getRegionBindings(LCV.getStore()), SourceFR);
2692
2693 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
2695 }
2696
2697 return NewB;
2698}
2699
2705
2708
2709 if (!RD->isCompleteDefinition())
2710 return B;
2711
2712
2713 if (std::optionalnonloc::LazyCompoundVal LCV =
2715 if (std::optional NewB =
2716 tryBindSmallStruct(B, R, RD, *LCV))
2717 return *NewB;
2718 return bindAggregate(B, R, V);
2719 }
2720 if (isanonloc::SymbolVal(V))
2721 return bindAggregate(B, R, V);
2722
2723
2724
2725
2726 if (V.isUnknown() || !isanonloc::CompoundVal(V))
2727 return bindAggregate(B, R, UnknownVal());
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2747
2748 RegionBindingsRef NewB(B);
2749
2750
2751
2752 if (const auto *CRD = dyn_cast(RD)) {
2753
2754
2755
2756
2757
2758
2759
2760 assert((CRD->isAggregate() || (Ctx.getLangOpts().ObjC && VI == VE)) &&
2761 "Non-aggregates are constructed with a constructor!");
2762
2763 for (const auto &B : CRD->bases()) {
2764
2765 assert(!B.isVirtual() && "Aggregates cannot have virtual base classes!");
2766
2767 if (VI == VE)
2768 break;
2769
2772
2774 assert(BRD && "Base classes must be C++ classes!");
2775
2777 MRMgr.getCXXBaseObjectRegion(BRD, R, false);
2778
2779 NewB = bindStruct(NewB, BR, *VI);
2780
2781 ++VI;
2782 }
2783 }
2784
2786
2787 for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) {
2788
2789 if (VI == VE)
2790 break;
2791
2792
2793 if (FI->isUnnamedBitField())
2794 continue;
2795
2796 QualType FTy = FI->getType();
2797 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2798
2800 NewB = bindArray(NewB, FR, *VI);
2802 NewB = bindStruct(NewB, FR, *VI);
2803 else
2805 ++VI;
2806 }
2807
2808
2809 if (FI != FE) {
2810 NewB = NewB.addBinding(R, BindingKey::Default,
2812 }
2813
2814 return NewB;
2815}
2816
2817RegionBindingsRef
2821
2822
2823 return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);
2824}
2825
2826
2827
2828
2829
2830namespace {
2831class RemoveDeadBindingsWorker
2832 : public ClusterAnalysis {
2836
2837public:
2838 RemoveDeadBindingsWorker(RegionStoreManager &rm,
2842 : ClusterAnalysis(rm, stateMgr, b),
2843 SymReaper(symReaper), CurrentLCtx(LCtx) {}
2844
2845
2848 using ClusterAnalysis::VisitCluster;
2849
2850 using ClusterAnalysis::AddToWorkList;
2851
2852 bool AddToWorkList(const MemRegion *R);
2853
2854 bool UpdatePostponed();
2855 void VisitBinding(SVal V);
2856};
2857}
2858
2859bool RemoveDeadBindingsWorker::AddToWorkList(const MemRegion *R) {
2861 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
2862}
2863
2864void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
2866
2867 if (const VarRegion *VR = dyn_cast(baseR)) {
2868 if (SymReaper.isLive(VR))
2869 AddToWorkList(baseR, &C);
2870
2871 return;
2872 }
2873
2874 if (const SymbolicRegion *SR = dyn_cast(baseR)) {
2875 if (SymReaper.isLive(SR->getSymbol()))
2876 AddToWorkList(SR, &C);
2877 else
2878 Postponed.push_back(SR);
2879
2880 return;
2881 }
2882
2883 if (isa(baseR)) {
2884 AddToWorkList(baseR, &C);
2885 return;
2886 }
2887
2888
2889 if (const CXXThisRegion *TR = dyn_cast(baseR)) {
2890 const auto *StackReg =
2891 cast(TR->getSuperRegion());
2893 if (CurrentLCtx &&
2894 (RegCtx == CurrentLCtx || RegCtx->isParentOf(CurrentLCtx)))
2895 AddToWorkList(TR, &C);
2896 }
2897}
2898
2899void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
2901 if ()
2902 return;
2903
2904
2905
2906 if (const SymbolicRegion *SymR = dyn_cast(baseR))
2907 SymReaper.markLive(SymR->getSymbol());
2908
2909 for (const auto &[Key, Val] : *C) {
2910
2911 SymReaper.markElementIndicesLive(Key.getRegion());
2912
2913 VisitBinding(Val);
2914 }
2915}
2916
2917void RemoveDeadBindingsWorker::VisitBinding(SVal V) {
2918
2919
2921 SymReaper.markLazilyCopied(LCS->getRegion());
2922
2923 for (SVal V : RM.getInterestingValues(*LCS)) {
2925 SymReaper.markLazilyCopied(DepLCS->getRegion());
2926 else
2927 VisitBinding(V);
2928 }
2929
2930 return;
2931 }
2932
2933
2934 if (const MemRegion *R = V.getAsRegion()) {
2935 AddToWorkList(R);
2936 SymReaper.markLive(R);
2937
2938
2939 if (const BlockDataRegion *BR = dyn_cast(R)) {
2940 for (auto Var : BR->referenced_vars())
2941 AddToWorkList(Var.getCapturedRegion());
2942 }
2943 }
2944
2945
2946
2948 SymReaper.markLive(Sym);
2949}
2950
2951bool RemoveDeadBindingsWorker::UpdatePostponed() {
2952
2953
2955
2957 if (SymReaper.isLive(SR->getSymbol())) {
2958 Changed |= AddToWorkList(SR);
2959 SR = nullptr;
2960 }
2961 }
2962
2964}
2965
2966StoreRef RegionStoreManager::removeDeadBindings(Store store,
2969 RegionBindingsRef B = getRegionBindings(store);
2970 RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
2971 W.GenerateClusters();
2972
2973
2975 W.AddToWorkList(Reg);
2976 }
2977
2978 do W.RunWorkList(); while (W.UpdatePostponed());
2979
2980
2981
2982
2983 for (const MemRegion *Base : llvm::make_first_range(B)) {
2984
2985
2986 if (!W.isVisited(Base))
2987 B = B.remove(Base);
2988 }
2989
2990 return StoreRef(B.asStore(), *this);
2991}
2992
2993
2994
2995
2996
2997void RegionStoreManager::printJson(raw_ostream &Out, Store S, const char *NL,
2998 unsigned int Space, bool IsDot) const {
2999 RegionBindingsRef Bindings = getRegionBindings(S);
3000
3001 Indent(Out, Space, IsDot) << "\"store\": ";
3002
3004 Out << "null," << NL;
3005 return;
3006 }
3007
3008 Out << "{ \"pointer\": \"" << Bindings.asStore() << "\", \"items\": [" << NL;
3009 Bindings.printJson(Out, NL, Space + 1, IsDot);
3010 Indent(Out, Space, IsDot) << "]}," << NL;
3011}
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 void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
llvm::DenseSet< const void * > Visited
static std::optional< SVal > convertOffsetsFromSvalToUnsigneds(const SmallVector< SVal, 2 > &SrcOffsets, const SmallVector< uint64_t, 2 > ArrayExtents, SmallVector< uint64_t, 2 > &DstOffsets)
llvm::ImmutableMap< const MemRegion *, ClusterBindings > RegionBindings
static std::optional< SVal > getDerivedSymbolForBinding(RegionBindingsConstRef B, const TypedValueRegion *BaseRegion, const TypedValueRegion *SubReg, const ASTContext &Ctx, SValBuilder &SVB)
std::pair< BindingKey, SVal > BindingPair
static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields)
SmallVector< const FieldDecl *, 8 > FieldVector
llvm::ImmutableMap< BindingKey, SVal > ClusterBindings
static bool isUnionField(const FieldRegion *FR)
static void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields)
static QualType getUnderlyingType(const SubRegion *R)
llvm::ImmutableMapRef< BindingKey, SVal > ClusterBindingsRef
static SmallVector< uint64_t, 2 > getConstantArrayExtents(const ConstantArrayType *CAT)
This is a helper function for getConstantValFromConstArrayInitializer.
static std::pair< SmallVector< SVal, 2 >, const MemRegion * > getElementRegionOffsetsWithBase(const ElementRegion *ER)
This is a helper function for getConstantValFromConstArrayInitializer.
const RegionBindingsRef & RegionBindingsConstRef
static std::optional< nonloc::LazyCompoundVal > getExistingLazyBinding(SValBuilder &SVB, RegionBindingsConstRef B, const SubRegion *R, bool AllowSubregionBindings)
Checks to see if store B has a lazy binding for region R.
static void collectSubRegionBindings(SmallVectorImpl< BindingPair > &Bindings, SValBuilder &SVB, const ClusterBindings &Cluster, const SubRegion *Top, BindingKey TopKey, bool IncludeAllDefaultBindings)
Collects all bindings in Cluster that may refer to bindings within Top.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
__PTRDIFF_TYPE__ ptrdiff_t
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
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.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
Stores options for the analyzer from the command line.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Represents a C++ struct/union/class.
Represents the canonical version of C arrays with a specified constant size.
uint64_t getLimitedSize() const
Return the size zero-extended to uint64_t or UINT64_MAX if the value is larger than UINT64_MAX.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
This represents one expression.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
Describes an C or C++ initializer list.
bool isStringLiteralInit() const
Is this an initializer for an array of characters, initialized by a string literal or an @encode?
unsigned getNumInits() const
const Expr * getInit(unsigned Init) const
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
bool isParentOf(const LocationContext *LC) const
const Decl * getDecl() const
const StackFrameContext * getStackFrame() const
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool isConstQualified() const
Determine whether this type is const-qualified.
Represents a struct/union/class.
field_range fields() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
It represents a stack frame of the call stack (based on CallEvent).
Stmt - This represents one statement.
StringLiteral - This represents a string literal expression, e.g.
unsigned getLength() const
uint32_t getCodeUnit(size_t i) const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool isVoidPointerType() const
const T * castAs() const
Member-template castAs.
bool isReferenceType() const
bool isScalarType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isAnyComplexType() const
QualType getCanonicalTypeInternal() const
bool isStructureOrClassType() const
bool isVectorType() const
bool isRecordType() const
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
Maps string IDs to AST nodes matched by parts of a matcher.
AnalyzerOptions & options
BlockDataRegion - A region that represents a block instance.
CXXThisRegion - Represents the region for the implicit 'this' parameter in a call to a C++ method.
Represents an abstract call to a function or method along a particular path.
ElementRegion is used to represent both array elements and casts.
QualType getElementType() const
RegionRawOffset getAsArrayOffset() const
Compute the offset within the array. The array might also be a subobject.
AnalysisManager & getAnalysisManager()
LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override
static bool isLocType(QualType T)
DefinedOrUnknownSVal getStaticSize(const MemRegion *MR, SValBuilder &SVB) const
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() const
virtual bool isBoundable() const
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
bool hasStackNonParametersStorage() const
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
Information about invalidation for a particular region/symbol.
@ TK_PreserveContents
Tells that a region's contents is not changed.
@ TK_DoNotInvalidateSuperRegion
@ TK_EntireMemSpace
When applied to a MemSpaceRegion, indicates the entire memory space should be invalidated.
Represent a region's offset within the top level base region.
bool hasSymbolicOffset() const
const MemRegion * getRegion() const
It might return null.
int64_t getOffset() const
const MemRegion * getRegion() const
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
NonLoc makeArrayIndex(uint64_t idx)
ASTContext & getContext()
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy)
Cast a given SVal to another SVal using given QualType's.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, const TypedValueRegion *region)
loc::ConcreteInt makeNullWithType(QualType type)
Create NULL pointer, with proper pointer bit-width for given address space.
std::optional< SVal > getConstantVal(const Expr *E)
Returns the value of E, if it can be determined in a non-path-sensitive manner.
NonLoc makeZeroArrayIndex()
DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region)
Make a unique symbol for value of region.
NonLoc makeLazyCompoundVal(const StoreRef &store, const TypedValueRegion *region)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
bool isZeroConstant() const
bool isUnknownOrUndef() const
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
A utility class that visits the reachable symbols using a custom SymbolVisitor.
bool scan(nonloc::LazyCompoundVal val)
virtual StoreRef invalidateRegions(Store store, ArrayRef< SVal > Values, const Stmt *S, unsigned Count, const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits, InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated)=0
invalidateRegions - Clears out the specified regions from the store, marking their values as unknown.
virtual bool scanReachableSymbols(Store S, const MemRegion *R, ScanReachableSymbols &Visitor)=0
Finds the transitive closure of symbols within the given region.
virtual void iterBindings(Store store, BindingsHandler &f)=0
iterBindings - Iterate over the bindings in the Store.
virtual StoreRef getInitialStore(const LocationContext *InitLoc)=0
getInitialStore - Returns the initial "empty" store representing the value bindings upon entry to an ...
virtual StoreRef BindDefaultZero(Store store, const MemRegion *R)=0
Return a store with in which all values within the given region are reset to zero.
virtual std::optional< SVal > getDefaultBinding(Store store, const MemRegion *R)=0
Return the default value bound to a region in a given store.
virtual StoreRef killBinding(Store ST, Loc L)=0
Create a new store with the specified binding removed.
virtual void decrementReferenceCount(Store store)
If the StoreManager supports it, decrement the reference count of the specified Store object.
virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx, SymbolReaper &SymReaper)=0
virtual void incrementReferenceCount(Store store)
If the StoreManager supports it, increment the reference count of the specified Store object.
virtual SVal ArrayToPointer(Loc Array, QualType ElementTy)=0
ArrayToPointer - Used by ExprEngine::VistCast to handle implicit conversions between arrays and point...
virtual bool includedInBindings(Store store, const MemRegion *region) const =0
virtual SVal getBinding(Store store, Loc loc, QualType T=QualType())=0
Return the value bound to specified location in a given state.
virtual StoreRef BindDefaultInitial(Store store, const MemRegion *R, SVal V)=0
Return a store with the specified value bound to all sub-regions of the region.
virtual void printJson(raw_ostream &Out, Store S, const char *NL, unsigned int Space, bool IsDot) const =0
StringRegion - Region associated with a StringLiteral.
SubRegion - A region that subsets another larger region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
bool isSubRegionOf(const MemRegion *R) const override
Check if the region is a subregion of the given region.
MemRegionManager & getMemRegionManager() const override
static bool canSymbolicate(QualType T)
A class responsible for cleaning up unused symbols.
llvm::iterator_range< RegionSetTy::const_iterator > regions() const
SymbolicRegion - A special, "non-concrete" region.
TypedRegion - An abstract class representing regions that are typed.
TypedValueRegion - An abstract class representing regions having a typed value.
virtual QualType getValueType() const =0
QualType getLocationType() const override
QualType getValueType() const override
const VarDecl * getDecl() const override=0
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getRegion() const
Get the underlining region.
The simplest example of a concrete compound value is nonloc::CompoundVal, which represents a concrete...
llvm::ImmutableList< SVal >::iterator iterator
Value representing integer constant.
While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...
LLVM_ATTRIBUTE_RETURNS_NONNULL const LazyCompoundValData * getCVData() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
This function itself is immaterial.
const void * getStore() const
It might return null.
Defines the clang::TargetInfo interface.
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, DeclRefExpr > declRefExpr
Matches expressions that refer to declarations.
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< Stmt > StatementMatcher
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
ASTEdit remove(RangeSelector S)
Removes the source selected by S.
The JSON file list parser is used to communicate input to InstallAPI.
@ Bind
'bind' clause, allowed on routine constructs.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Diagnostic wrappers for TextAPI types for error reporting.
static raw_ostream & operator<<(raw_ostream &Out, BindingKey K)
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...