28#include "llvm/ADT/ImmutableMap.h"
29#include "llvm/ADT/STLExtras.h"
30#include "llvm/Support/TimeProfiler.h"
31#include "llvm/Support/raw_ostream.h"
53 llvm::PointerIntPair<const MemRegion *, 2> P;
58 explicit BindingKey(
const SubRegion *r,
const SubRegion *Base, Kind k)
59 : P(r, k | Symbolic), Data(reinterpret_cast<
uintptr_t>(
Base)) {
60 assert(r && Base &&
"Must have known regions.");
61 assert(getConcreteOffsetRegion() == Base &&
"Failed to store base region");
65 explicit BindingKey(
const MemRegion *r, uint64_t offset, Kind k)
66 : P(r, k), Data(offset) {
67 assert(r &&
"Must have known regions.");
68 assert(getOffset() == offset &&
"Failed to store offset");
75 bool isDirect()
const {
return P.getInt() & Direct; }
76 bool isDefault()
const {
return !isDirect(); }
77 bool hasSymbolicOffset()
const {
return P.getInt() & Symbolic; }
79 const MemRegion *
getRegion()
const {
return P.getPointer(); }
81 assert(!hasSymbolicOffset());
85 const SubRegion *getConcreteOffsetRegion()
const {
86 assert(hasSymbolicOffset());
87 return reinterpret_cast<const SubRegion *
>(
static_cast<uintptr_t>(Data));
90 const MemRegion *getBaseRegion()
const {
91 if (hasSymbolicOffset())
92 return getConcreteOffsetRegion()->getBaseRegion();
96 void Profile(llvm::FoldingSetNodeID& ID)
const {
97 ID.AddPointer(P.getOpaqueValue());
101 static BindingKey
Make(
const MemRegion *R, Kind k);
104 if (P.getOpaqueValue() <
X.P.getOpaqueValue())
106 if (P.getOpaqueValue() >
X.P.getOpaqueValue())
108 return Data <
X.Data;
112 return P.getOpaqueValue() ==
X.P.getOpaqueValue() &&
116 LLVM_DUMP_METHOD
void dump()
const;
119std::string locDescr(
Loc L) {
121 llvm::raw_string_ostream
OS(S);
127BindingKey BindingKey::Make(
const MemRegion *R, Kind k) {
136static inline raw_ostream &
operator<<(raw_ostream &Out, BindingKey K) {
137 Out <<
"\"kind\": \"" << (K.isDirect() ?
"Direct" :
"Default")
138 <<
"\", \"offset\": ";
140 if (!K.hasSymbolicOffset())
141 Out << K.getOffset();
150#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
151void BindingKey::dump()
const { llvm::errs() << *
this; }
162typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
166class RegionBindingsRef :
public llvm::ImmutableMapRef<const MemRegion *,
168 ClusterBindings::Factory *CBFactory;
182 typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
185 RegionBindingsRef(ClusterBindings::Factory &CBFactory,
186 const RegionBindings::TreeTy *T,
187 RegionBindings::TreeTy::Factory *F,
bool IsMainAnalysis)
188 : RegionBindingsRef(ParentTy(T, F), CBFactory, IsMainAnalysis) {}
190 RegionBindingsRef(
const ParentTy &P, ClusterBindings::Factory &CBFactory,
192 : ParentTy(P), CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
194 RegionBindingsRef removeCluster(
const MemRegion *BaseRegion)
const {
195 return RegionBindingsRef(ParentTy::remove(BaseRegion), *CBFactory,
199 RegionBindingsRef addBinding(BindingKey K,
SVal V)
const;
201 RegionBindingsRef addBinding(
const MemRegion *R,
202 BindingKey::Kind k,
SVal V)
const;
204 const SVal *lookup(BindingKey K)
const;
205 const SVal *lookup(
const MemRegion *R, BindingKey::Kind k)
const;
208 RegionBindingsRef removeBinding(BindingKey K);
210 RegionBindingsRef removeBinding(
const MemRegion *R,
213 RegionBindingsRef removeBinding(
const MemRegion *R) {
214 return removeBinding(R, BindingKey::Direct).
215 removeBinding(R, BindingKey::Default);
218 std::optional<SVal> getDirectBinding(
const MemRegion *R)
const;
222 std::optional<SVal> getDefaultBinding(
const MemRegion *R)
const;
225 Store asStore()
const {
226 llvm::PointerIntPair<Store, 1, bool> Ptr = {
227 asImmutableMap().getRootWithoutRetain(), IsMainAnalysis};
228 return reinterpret_cast<Store>(Ptr.getOpaqueValue());
231 bool isMainAnalysis()
const {
232 return IsMainAnalysis;
235 void printJson(raw_ostream &Out,
const char *NL =
"\n",
236 unsigned int Space = 0,
bool IsDot =
false)
const {
237 using namespace llvm;
238 DenseMap<const MemRegion *, std::string> StringifyCache;
239 auto ToString = [&StringifyCache](
const MemRegion *R) {
240 auto [Place, Inserted] = StringifyCache.try_emplace(R);
242 return Place->second;
244 raw_string_ostream
OS(Res);
251 std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;
252 using Binding = std::pair<BindingKey, SVal>;
254 const auto MemSpaceBeforeRegionName = [&ToString](
const Cluster *L,
260 return ToString(L->first) < ToString(R->first);
263 const auto SymbolicBeforeOffset = [&ToString](
const BindingKey &L,
264 const BindingKey &R) {
265 if (L.hasSymbolicOffset() && !R.hasSymbolicOffset())
267 if (!L.hasSymbolicOffset() && R.hasSymbolicOffset())
269 if (L.hasSymbolicOffset() && R.hasSymbolicOffset())
270 return ToString(L.getRegion()) < ToString(R.getRegion());
271 return L.getOffset() < R.getOffset();
274 const auto DefaultBindingBeforeDirectBindings =
275 [&SymbolicBeforeOffset](
const Binding *LPtr,
const Binding *RPtr) {
276 const BindingKey &L = LPtr->first;
277 const BindingKey &R = RPtr->first;
278 if (L.isDefault() && !R.isDefault())
280 if (!L.isDefault() && R.isDefault())
282 assert(L.isDefault() == R.isDefault());
283 return SymbolicBeforeOffset(L, R);
286 const auto AddrOf = [](
const auto &Item) {
return &Item; };
288 std::vector<const Cluster *> SortedClusters;
289 SortedClusters.reserve(std::distance(begin(), end()));
290 append_range(SortedClusters, map_range(*
this, AddrOf));
291 llvm::sort(SortedClusters, MemSpaceBeforeRegionName);
293 for (
auto [Idx,
C] : llvm::enumerate(SortedClusters)) {
296 <<
"{ \"cluster\": \"" << BaseRegion <<
"\", \"pointer\": \""
297 << (
const void *)BaseRegion <<
"\", \"items\": [" << NL;
299 std::vector<const Binding *> SortedBindings;
301 append_range(SortedBindings, map_range(
Bindings, AddrOf));
302 llvm::sort(SortedBindings, DefaultBindingBeforeDirectBindings);
305 for (
auto [Idx, B] : llvm::enumerate(SortedBindings)) {
306 const auto &[Key,
Value] = *B;
307 Indent(Out, Space, IsDot) <<
"{ " << Key <<
", \"value\": ";
308 Value.printJson(Out,
true);
310 if (Idx != SortedBindings.size() - 1)
315 Indent(Out, Space, IsDot) <<
"]}";
316 if (Idx != SortedClusters.size() - 1)
322 LLVM_DUMP_METHOD
void dump()
const { printJson(llvm::errs()); }
326 commitBindingsToCluster(
const MemRegion *BaseRegion,
337 std::optional<unsigned> BindingsLeft)
338 : RegionBindingsRef(
Base),
339 EscapedValuesDuringBind(&EscapedValuesDuringBind),
340 BindingsLeft(BindingsLeft) {}
343 return BindingsLeft.has_value() && BindingsLeft.value() == 0;
347 EscapedValuesDuringBind->push_back(
V);
354 for (
SVal V : llvm::make_range(Begin, End))
361 data_type_ref BindingKeyAndValue)
const {
363 BaseRegion, BindingKeyAndValue),
364 *EscapedValuesDuringBind, BindingsLeft};
369 RegionBindingsRef::removeCluster(BaseRegion), *EscapedValuesDuringBind,
374 std::optional<unsigned> NewBindingsLeft = BindingsLeft;
375 if (NewBindingsLeft.has_value()) {
376 assert(NewBindingsLeft.value() != 0);
377 NewBindingsLeft.value() -= 1;
381 if (NewBindingsLeft.value() == 0) {
383 K = BindingKey::Make(K.getRegion(), BindingKey::Default);
389 *EscapedValuesDuringBind, NewBindingsLeft};
399 std::optional<unsigned> BindingsLeft;
406RegionBindingsRef::getDirectBinding(
const MemRegion *R)
const {
407 const SVal *
V = lookup(R, BindingKey::Direct);
408 return V ? std::optional<SVal>(*
V) : std::nullopt;
412RegionBindingsRef::getDefaultBinding(
const MemRegion *R)
const {
413 const SVal *
V = lookup(R, BindingKey::Default);
414 return V ? std::optional<SVal>(*
V) : std::nullopt;
417RegionBindingsRef RegionBindingsRef::commitBindingsToCluster(
419 return RegionBindingsRef(ParentTy::add(BaseRegion,
Bindings), *CBFactory,
423RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K, SVal
V)
const {
424 const MemRegion *
Base = K.getBaseRegion();
428 (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
430 return commitBindingsToCluster(Base,
Bindings);
433RegionBindingsRef RegionBindingsRef::addBinding(
const MemRegion *R,
436 return addBinding(BindingKey::Make(R, k),
V);
439const SVal *RegionBindingsRef::lookup(BindingKey K)
const {
443 return Cluster->lookup(K);
446const SVal *RegionBindingsRef::lookup(
const MemRegion *R,
447 BindingKey::Kind k)
const {
448 return lookup(BindingKey::Make(R, k));
451RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
452 const MemRegion *
Base = K.getBaseRegion();
458 if (NewCluster.isEmpty())
459 return removeCluster(Base);
460 return commitBindingsToCluster(Base, NewCluster);
463RegionBindingsRef RegionBindingsRef::removeBinding(
const MemRegion *R,
465 return removeBinding(BindingKey::Make(R, k));
473class InvalidateRegionsWorker;
475class RegionStoreManager :
public StoreManager {
477 RegionBindings::Factory RBFactory;
478 mutable ClusterBindings::Factory CBFactory;
480 typedef std::vector<SVal> SValListTy;
482 typedef llvm::DenseMap<
const LazyCompoundValData *,
483 SValListTy> LazyBindingsMapTy;
484 LazyBindingsMapTy LazyBindingsMap;
494 const unsigned SmallStructLimit;
504 const unsigned SmallArrayLimit;
510 const std::optional<unsigned> RegionStoreMaxBindingFanOutPlusOne;
514 void populateWorkList(InvalidateRegionsWorker &W,
515 ArrayRef<SVal> Values,
516 InvalidatedRegions *TopLevelRegions);
518 const AnalyzerOptions &getOptions() {
519 return StateMgr.getOwningEngine().getAnalysisManager().options;
523 RegionStoreManager(ProgramStateManager &mgr)
524 : StoreManager(mgr), RBFactory(mgr.getAllocator()),
525 CBFactory(mgr.getAllocator()),
526 SmallStructLimit(getOptions().RegionStoreSmallStructLimit),
527 SmallArrayLimit(getOptions().RegionStoreSmallArrayLimit),
528 RegionStoreMaxBindingFanOutPlusOne([&]() -> std::optional<unsigned> {
529 unsigned FanOut = getOptions().RegionStoreMaxBindingFanOut;
530 assert(FanOut != std::numeric_limits<unsigned>::max());
539 LimitedRegionBindingsRef
549 SVal ArrayToPointer(Loc Array, QualType ElementTy)
override;
553 StoreRef getInitialStore(
const LocationContext *InitLoc)
override {
554 bool IsMainAnalysis =
false;
555 if (
const auto *FD = dyn_cast<FunctionDecl>(InitLoc->
getDecl()))
556 IsMainAnalysis = FD->isMain() && !Ctx.getLangOpts().CPlusPlus;
557 return StoreRef(RegionBindingsRef(RegionBindingsRef::ParentTy(
558 RBFactory.getEmptyMap(), RBFactory),
559 CBFactory, IsMainAnalysis)
569 unsigned Count,
const LocationContext *LCtx,
570 RegionBindingsRef B, InvalidatedRegions *Invalidated);
572 StoreRef invalidateRegions(
Store store, ArrayRef<SVal> Values,
574 const LocationContext *LCtx,
const CallEvent *
Call,
576 RegionAndSymbolInvalidationTraits &ITraits,
577 InvalidatedRegions *Invalidated,
578 InvalidatedRegions *InvalidatedTopLevel)
override;
580 bool scanReachableSymbols(
Store S,
const MemRegion *R,
581 ScanReachableSymbols &Callbacks)
override;
583 LimitedRegionBindingsRef
587 const ElementRegion *R);
589 getSValFromInitListExpr(
const InitListExpr *ILE,
590 const SmallVector<uint64_t, 2> &ConcreteOffsets,
592 SVal getSValFromStringLiteral(
const StringLiteral *SL, uint64_t Offset,
596 BindResult
Bind(
Store store, Loc LV, SVal
V)
override {
597 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
598 LimitedRegionBindingsRef BoundedBindings =
599 getRegionBindings(store, EscapedValuesDuringBind);
600 return BindResult{StoreRef(bind(BoundedBindings, LV,
V).asStore(), *
this),
601 std::move(EscapedValuesDuringBind)};
609 BindResult BindDefaultInitial(
Store store,
const MemRegion *R,
611 RegionBindingsRef B = getRegionBindings(store);
614 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
615 "Double initialization!");
616 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
618 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this), {}};
623 BindResult BindDefaultZero(
Store store,
const MemRegion *R)
override {
633 if (
const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
634 if (BR->getDecl()->isEmpty())
635 return BindResult{StoreRef(store, *
this), {}};
637 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
638 LimitedRegionBindingsRef B =
639 getRegionBindings(store, EscapedValuesDuringBind);
640 SVal
V = svalBuilder.makeZeroVal(Ctx.CharTy);
642 B = B.
addBinding(BindingKey::Make(R, BindingKey::Default),
V);
644 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this),
645 std::move(EscapedValuesDuringBind)};
658 std::optional<LimitedRegionBindingsRef>
660 const RecordDecl *RD, nonloc::LazyCompoundVal LCV);
664 const TypedValueRegion *R, SVal
V);
668 const TypedValueRegion *R, SVal
V);
670 std::optional<LimitedRegionBindingsRef>
672 const ArrayType *AT, nonloc::LazyCompoundVal LCV);
675 const TypedValueRegion *R, SVal
V);
680 const TypedRegion *R, SVal DefaultVal);
685 StoreRef killBinding(
Store ST, Loc L)
override;
687 void incrementReferenceCount(
Store store)
override {
688 getRegionBindings(store).manualRetain();
694 void decrementReferenceCount(
Store store)
override {
695 getRegionBindings(store).manualRelease();
698 bool includedInBindings(
Store store,
const MemRegion *region)
const override;
713 SVal getBinding(
Store S, Loc L, QualType T)
override {
714 return getBinding(getRegionBindings(S), L, T);
717 std::optional<SVal> getDefaultBinding(
Store S,
const MemRegion *R)
override {
718 RegionBindingsRef B = getRegionBindings(S);
735 SVal getBindingForLazySymbol(
const TypedValueRegion *R);
738 const TypedValueRegion *R,
741 SVal getLazyBinding(
const SubRegion *LazyBindingRegion,
742 RegionBindingsRef LazyBinding);
760 const MemRegion *superR,
761 const TypedValueRegion *R, QualType Ty);
767 std::pair<Store, const SubRegion *>
769 const SubRegion *originalRegion);
781 const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);
789 StoreRef removeDeadBindings(
Store store,
const StackFrameContext *LCtx,
790 SymbolReaper& SymReaper)
override;
796 RegionBindingsRef getRegionBindings(
Store store)
const {
797 llvm::PointerIntPair<Store, 1, bool> Ptr;
798 Ptr.setFromOpaqueValue(
const_cast<void *
>(store));
800 static_cast<const RegionBindings::TreeTy *
>(Ptr.getPointer()),
801 RBFactory.getTreeFactory(), Ptr.getInt()};
804 LimitedRegionBindingsRef
805 getRegionBindings(
Store store,
806 SmallVectorImpl<SVal> &EscapedValuesDuringBind)
const {
807 return LimitedRegionBindingsRef(
808 getRegionBindings(store), EscapedValuesDuringBind,
809 RegionStoreMaxBindingFanOutPlusOne);
812 void printJson(raw_ostream &Out,
Store S,
const char *NL =
"\n",
813 unsigned int Space = 0,
bool IsDot =
false)
const override;
815 void iterBindings(
Store store, BindingsHandler& f)
override {
816 RegionBindingsRef B = getRegionBindings(store);
817 for (
const auto &[Region, Cluster] : B) {
818 for (
const auto &[Key,
Value] : Cluster) {
821 if (
const SubRegion *R = dyn_cast<SubRegion>(Key.getRegion())) {
823 if (!f.HandleBinding(*
this, store, R,
Value))
837std::unique_ptr<StoreManager>
839 return std::make_unique<RegionStoreManager>(StMgr);
849enum GlobalsFilterKind {
858template <
typename DERIVED>
859class ClusterAnalysis {
861 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
862 typedef const MemRegion * WorkListElement;
869 RegionStoreManager &RM;
884 bool includeEntireMemorySpace(
const MemRegion *Base) {
889 ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
891 : RM(rm), Ctx(StateMgr.getContext()),
892 svalBuilder(StateMgr.getSValBuilder()), B(std::move(
b)) {}
894 RegionBindingsRef getRegionBindings()
const {
return B; }
896 bool isVisited(
const MemRegion *R) {
897 return Visited.count(getCluster(R));
900 void GenerateClusters() {
902 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
904 const MemRegion *
Base = RI.getKey();
907 assert(!Cluster.isEmpty() &&
"Empty clusters should be removed");
908 static_cast<DERIVED*
>(
this)->VisitAddedToCluster(Base, Cluster);
912 if (
static_cast<DERIVED*
>(
this)->includeEntireMemorySpace(Base))
913 AddToWorkList(WorkListElement(Base), &Cluster);
918 if (
C && !Visited.insert(
C).second)
924 bool AddToWorkList(
const MemRegion *R) {
925 return static_cast<DERIVED*
>(
this)->AddToWorkList(R);
929 while (!WL.empty()) {
930 WorkListElement E = WL.pop_back_val();
931 const MemRegion *BaseR = E;
933 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR, getCluster(BaseR));
937 void VisitAddedToCluster(
const MemRegion *baseR,
const ClusterBindings &
C) {}
942 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR,
C);
951bool RegionStoreManager::scanReachableSymbols(
Store S,
const MemRegion *R,
952 ScanReachableSymbols &Callbacks) {
953 assert(R == R->
getBaseRegion() &&
"Should only be called for base regions");
954 RegionBindingsRef B = getRegionBindings(S);
960 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
962 if (!Callbacks.
scan(RI.getData()))
976 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
982 if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R))
984 Fields.push_back(FR->getDecl());
991 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
999 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
1001 return std::equal(FieldsInBindingKey.begin() + Delta,
1002 FieldsInBindingKey.end(),
1005 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
1006 Fields.begin() - Delta);
1021 const SubRegion *Top, BindingKey TopKey,
1022 bool IncludeAllDefaultBindings) {
1024 if (TopKey.hasSymbolicOffset()) {
1026 Top = TopKey.getConcreteOffsetRegion();
1027 TopKey = BindingKey::Make(Top, BindingKey::Default);
1031 uint64_t Length = UINT64_MAX;
1033 if (std::optional<nonloc::ConcreteInt> ExtentCI =
1035 const llvm::APSInt &ExtentInt = ExtentCI->getValue();
1036 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
1039 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
1040 if (FR->getDecl()->isBitField())
1041 Length = FR->getDecl()->getBitWidthValue();
1044 for (
const auto &StoreEntry : Cluster) {
1045 BindingKey NextKey = StoreEntry.first;
1046 if (NextKey.getRegion() == TopKey.getRegion()) {
1052 if (NextKey.getOffset() > TopKey.getOffset() &&
1053 NextKey.getOffset() - TopKey.getOffset() < Length) {
1058 }
else if (NextKey.getOffset() == TopKey.getOffset()) {
1065 if (IncludeAllDefaultBindings || NextKey.isDirect())
1069 }
else if (NextKey.hasSymbolicOffset()) {
1075 if (IncludeAllDefaultBindings || NextKey.isDirect())
1078 }
else if (
const SubRegion *BaseSR = dyn_cast<SubRegion>(
Base)) {
1081 if (BaseSR->isSubRegionOf(Top))
1092 const SubRegion *Top,
bool IncludeAllDefaultBindings) {
1094 BindingKey::Make(Top, BindingKey::Default),
1095 IncludeAllDefaultBindings);
1098LimitedRegionBindingsRef
1100 const SubRegion *Top) {
1101 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
1102 const MemRegion *ClusterHead = TopKey.getBaseRegion();
1104 if (Top == ClusterHead) {
1113 if (TopKey.hasSymbolicOffset()) {
1114 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1115 return B.
addBinding(Concrete, BindingKey::Default, UnknownVal());
1120 SmallVector<BindingPair, 32>
Bindings;
1125 for (BindingKey Key : llvm::make_first_range(
Bindings))
1132 if (TopKey.hasSymbolicOffset()) {
1133 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1134 Result =
Result.add(BindingKey::Make(Concrete, BindingKey::Default),
1144class InvalidateRegionsWorker :
public ClusterAnalysis<InvalidateRegionsWorker>
1148 const LocationContext *LCtx;
1150 RegionAndSymbolInvalidationTraits &ITraits;
1152 GlobalsFilterKind GlobalsFilter;
1154 InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
1156 unsigned count,
const LocationContext *lctx,
1158 RegionAndSymbolInvalidationTraits &ITraitsIn,
1160 GlobalsFilterKind GFK)
1161 : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr,
b), Elem(elem),
1162 Count(count), LCtx(lctx), IS(
is), ITraits(ITraitsIn), Regions(r),
1163 GlobalsFilter(GFK) {}
1166 void VisitBinding(SVal
V);
1168 using ClusterAnalysis::AddToWorkList;
1170 bool AddToWorkList(
const MemRegion *R);
1174 bool includeEntireMemorySpace(
const MemRegion *Base);
1178 bool isInitiallyIncludedGlobalRegion(
const MemRegion *R);
1182bool InvalidateRegionsWorker::AddToWorkList(
const MemRegion *R) {
1183 bool doNotInvalidateSuperRegion = ITraits.
hasTrait(
1185 const MemRegion *BaseR = doNotInvalidateSuperRegion ? R : R->
getBaseRegion();
1186 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
1189void InvalidateRegionsWorker::VisitBinding(SVal
V) {
1194 if (
const MemRegion *R =
V.getAsRegion()) {
1200 if (std::optional<nonloc::LazyCompoundVal> LCS =
1201 V.getAs<nonloc::LazyCompoundVal>()) {
1205 for (SVal
V : RM.getInterestingValues(*LCS))
1213void InvalidateRegionsWorker::VisitCluster(
const MemRegion *baseR,
1216 bool PreserveRegionsContents =
1221 for (SVal Val : llvm::make_second_range(*
C))
1225 if (!PreserveRegionsContents)
1229 if (
const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
1230 if (
const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
1235 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
1236 using namespace ast_matchers;
1238 const char *DeclBind =
"DeclBind";
1240 to(
varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
1242 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
1243 RD->getASTContext());
1245 for (BoundNodes &
Match : Matches) {
1246 auto *VD =
Match.getNodeAs<VarDecl>(DeclBind);
1247 const VarRegion *ToInvalidate =
1248 RM.getRegionManager().getVarRegion(VD, LCtx);
1249 AddToWorkList(ToInvalidate);
1257 if (
const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
1258 for (
auto Var : BR->referenced_vars()) {
1259 const VarRegion *VR = Var.getCapturedRegion();
1260 const VarDecl *VD = VR->
getDecl();
1270 SVal
V = RM.getBinding(B, loc::MemRegionVal(VR));
1271 if (std::optional<Loc> L =
V.getAs<Loc>()) {
1281 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
1282 IS.insert(SR->getSymbol());
1285 if (PreserveRegionsContents)
1290 Regions->push_back(baseR);
1295 DefinedOrUnknownSVal
V =
1307 if (isInitiallyIncludedGlobalRegion(baseR)) {
1317 DefinedOrUnknownSVal
V =
1324 bool doNotInvalidateSuperRegion = ITraits.
hasTrait(
1328 if (doNotInvalidateSuperRegion) {
1331 std::optional<uint64_t> NumElements;
1334 if (
const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
1335 NumElements = CAT->getZExtSize();
1337 goto conjure_default;
1338 QualType ElementTy = AT->getElementType();
1346 AddToWorkList(SuperR);
1347 goto conjure_default;
1351 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
1352 bool UpperOverflow = UpperOffset < LowerOffset;
1357 goto conjure_default;
1361 goto conjure_default;
1363 for (
const auto &[BK,
V] : *
C) {
1364 std::optional<uint64_t> ROffset =
1365 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
1370 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
1372 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
1373 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
1374 B = B.removeBinding(BK);
1377 const MemRegion *R =
V.getAsRegion();
1378 if (isa_and_nonnull<SymbolicRegion>(R))
1386 baseR, Elem, LCtx, AT->getElementType(), Count);
1391 DefinedOrUnknownSVal
V =
1397bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
1398 const MemRegion *R) {
1399 switch (GlobalsFilter) {
1402 case GFK_SystemOnly:
1408 llvm_unreachable(
"unknown globals filter");
1411bool InvalidateRegionsWorker::includeEntireMemorySpace(
const MemRegion *Base) {
1412 if (isInitiallyIncludedGlobalRegion(Base))
1415 const MemSpaceRegion *MemSpace =
Base->getRawMemorySpace();
1420RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
1422 const LocationContext *LCtx, RegionBindingsRef B,
1423 InvalidatedRegions *Invalidated) {
1426 const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
1428 (
const void *)GS, Elem, LCtx,
1431 B = B.removeBinding(GS)
1432 .addBinding(BindingKey::Make(GS, BindingKey::Default),
V);
1437 Invalidated->push_back(GS);
1442void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
1443 ArrayRef<SVal> Values,
1444 InvalidatedRegions *TopLevelRegions) {
1445 for (SVal
V : Values) {
1446 if (
auto LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
1447 for (SVal S : getInterestingValues(*LCS))
1448 if (
const MemRegion *R = S.getAsRegion())
1454 if (
const MemRegion *R =
V.getAsRegion()) {
1455 if (TopLevelRegions)
1456 TopLevelRegions->push_back(R);
1463StoreRef RegionStoreManager::invalidateRegions(
1466 RegionAndSymbolInvalidationTraits &ITraits,
1467 InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
1468 GlobalsFilterKind GlobalsFilter;
1470 if (
Call->isInSystemHeader())
1471 GlobalsFilter = GFK_SystemOnly;
1473 GlobalsFilter = GFK_All;
1475 GlobalsFilter = GFK_None;
1478 RegionBindingsRef B = getRegionBindings(store);
1479 InvalidateRegionsWorker W(*
this, StateMgr, B, Elem, Count, LCtx, IS, ITraits,
1480 Invalidated, GlobalsFilter);
1483 W.GenerateClusters();
1486 populateWorkList(W, Values, TopLevelRegions);
1491 B = W.getRegionBindings();
1497 switch (GlobalsFilter) {
1499 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, Elem,
1500 Count, LCtx, B, Invalidated);
1502 case GFK_SystemOnly:
1503 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, Elem,
1504 Count, LCtx, B, Invalidated);
1510 return StoreRef(B.asStore(), *
this);
1523SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {
1528 return UnknownVal();
1530 const SubRegion *R =
1533 return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
1550 if (L.
getAs<loc::ConcreteInt>()) {
1551 return UnknownVal();
1553 if (!L.
getAs<loc::MemRegionVal>()) {
1554 return UnknownVal();
1560 return UnknownVal();
1565 if (
const auto *TVR = dyn_cast<TypedValueRegion>(MR))
1566 T = TVR->getValueType();
1567 else if (
const auto *TR = dyn_cast<TypedRegion>(MR))
1569 else if (
const auto *SR = dyn_cast<SymbolicRegion>(MR))
1570 T = SR->getPointeeStaticType();
1572 assert(!T.
isNull() &&
"Unable to auto-detect binding type!");
1573 assert(!T->
isVoidType() &&
"Attempting to dereference a void pointer!");
1586 return UnknownVal();
1597 return getBindingForStruct(B, R);
1601 return createLazyBinding(B, R);
1605 return getBindingForArray(B, R);
1607 return UnknownVal();
1612 return UnknownVal();
1614 if (
const FieldRegion* FR = dyn_cast<FieldRegion>(R))
1615 return svalBuilder.
evalCast(getBindingForField(B, FR), T, QualType{});
1617 if (
const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
1623 return svalBuilder.
evalCast(getBindingForElement(B, ER), T, QualType{});
1626 if (
const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
1633 return svalBuilder.
evalCast(getBindingForObjCIvar(B, IVR), T, QualType{});
1636 if (
const VarRegion *VR = dyn_cast<VarRegion>(R)) {
1643 return svalBuilder.
evalCast(getBindingForVar(B, VR), T, QualType{});
1646 const SVal *
V = B.lookup(R, BindingKey::Direct);
1660 return UndefinedVal();
1670 RegionTy = TVR->getValueType();
1673 RegionTy = SR->getSymbol()->getType();
1685static std::optional<nonloc::LazyCompoundVal>
1687 const SubRegion *R,
bool AllowSubregionBindings) {
1688 std::optional<SVal>
V = B.getDefaultBinding(R);
1690 return std::nullopt;
1692 std::optional<nonloc::LazyCompoundVal> LCV =
1695 return std::nullopt;
1700 if (!RegionTy.
isNull() &&
1702 QualType SourceRegionTy = LCV->getRegion()->getValueType();
1704 return std::nullopt;
1707 if (!AllowSubregionBindings) {
1714 return std::nullopt;
1720std::pair<Store, const SubRegion *>
1723 const SubRegion *originalRegion) {
1724 if (originalRegion != R) {
1725 if (std::optional<nonloc::LazyCompoundVal>
V =
1727 return std::make_pair(
V->getStore(),
V->getRegion());
1730 typedef std::pair<Store, const SubRegion *> StoreRegionPair;
1731 StoreRegionPair
Result = StoreRegionPair();
1733 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
1738 Result.second = MRMgr.getElementRegionWithSuper(ER,
Result.second);
1740 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
1745 Result.second = MRMgr.getFieldRegionWithSuper(FR,
Result.second);
1747 }
else if (
const CXXBaseObjectRegion *BaseReg =
1748 dyn_cast<CXXBaseObjectRegion>(R)) {
1755 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
1767static SmallVector<uint64_t, 2>
1769 assert(CAT &&
"ConstantArrayType should not be null");
1774 }
while ((CAT = dyn_cast<ConstantArrayType>(CAT->
getElementType())));
1792static std::pair<SmallVector<SVal, 2>,
const MemRegion *>
1794 assert(ER &&
"ConstantArrayType should not be null");
1798 SValOffsets.push_back(ER->
getIndex());
1800 ER = dyn_cast<ElementRegion>(
Base);
1802 return {SValOffsets,
Base};
1826static std::optional<SVal>
1847 DstOffsets.resize(SrcOffsets.size());
1848 auto ExtentIt = ArrayExtents.begin();
1849 auto OffsetIt = DstOffsets.begin();
1851 for (
SVal V : llvm::reverse(SrcOffsets)) {
1854 const llvm::APSInt &Offset = CI->getValue();
1855 if (Offset.isNegative() || Offset.uge(*(ExtentIt++)))
1858 *(OffsetIt++) = Offset.getZExtValue();
1866 return std::nullopt;
1869std::optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer(
1871 assert(R &&
"ElementRegion should not be null");
1874 SmallVector<SVal, 2> SValOffsets;
1875 const MemRegion *
Base;
1877 const VarRegion *VR = dyn_cast<VarRegion>(Base);
1879 return std::nullopt;
1881 assert(!SValOffsets.empty() &&
"getElementRegionOffsets guarantees the "
1882 "offsets vector is not empty.");
1886 const VarDecl *VD = VR->
getDecl();
1890 return std::nullopt;
1905 return std::nullopt;
1911 return std::nullopt;
1922 if (SValOffsets.size() != Extents.size())
1923 return std::nullopt;
1925 SmallVector<uint64_t, 2> ConcreteOffsets;
1927 SValOffsets, Extents, ConcreteOffsets))
1933 if (
const auto *ILE = dyn_cast<InitListExpr>(
Init))
1934 return getSValFromInitListExpr(ILE, ConcreteOffsets, R->
getElementType());
1939 if (
const auto *SL = dyn_cast<StringLiteral>(
Init))
1940 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
1945 return std::nullopt;
1965std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
1966 const InitListExpr *ILE,
const SmallVector<uint64_t, 2> &Offsets,
1968 assert(ILE &&
"InitListExpr should not be null");
1970 for (uint64_t Offset : Offsets) {
1977 if (
const auto *SL = dyn_cast<StringLiteral>(ILE->
getInit(0)))
1978 return getSValFromStringLiteral(SL, Offset, ElemT);
1986 const Expr *E = ILE->
getInit(Offset);
1987 const auto *IL = dyn_cast<InitListExpr>(E);
2001 return std::nullopt;
2029SVal RegionStoreManager::getSValFromStringLiteral(
const StringLiteral *SL,
2032 assert(SL &&
"StringLiteral should not be null");
2048 if (
const std::optional<SVal> &ParentValue =
2049 B.getDirectBinding(BaseRegion)) {
2050 if (
SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
2053 if (ParentValue->isUndef())
2062 return std::nullopt;
2066 const ElementRegion* R) {
2068 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2074 if (
const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
2080 return UnknownVal();
2081 if (
const auto CI = R->
getIndex().
getAs<nonloc::ConcreteInt>()) {
2082 const llvm::APSInt &Idx = CI->getValue();
2084 return UndefinedVal();
2085 const StringLiteral *SL = StrR->getStringLiteral();
2086 return getSValFromStringLiteral(SL, Idx.getZExtValue(), T);
2089 if (std::optional<SVal>
V = getConstantValFromConstArrayInitializer(B, R))
2095 return UnknownVal();
2107 return UnknownVal();
2109 if (
const TypedValueRegion *baseR = dyn_cast<TypedValueRegion>(O.
getRegion()))
2113 return getBindingForFieldOrElementCommon(B, R, R->
getElementType());
2117 const FieldRegion* R) {
2120 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2124 const FieldDecl *FD = R->
getDecl();
2127 if (
const auto *VR = dyn_cast<VarRegion>(superR)) {
2128 const VarDecl *VD = VR->
getDecl();
2129 QualType RecordVarTy = VD->
getType();
2137 if (
const auto *InitList = dyn_cast<InitListExpr>(
Init)) {
2138 if (Index < InitList->getNumInits()) {
2139 if (
const Expr *FieldInit = InitList->getInit(Index))
2164 if (
const auto *Base = dyn_cast<TypedValueRegion>(R->
getBaseRegion()))
2168 return getBindingForFieldOrElementCommon(B, R, Ty);
2171std::optional<SVal> RegionStoreManager::getBindingForDerivedDefaultValue(
2173 const TypedValueRegion *R, QualType Ty) {
2175 if (
const std::optional<SVal> &D = B.getDefaultBinding(superR)) {
2191 llvm_unreachable(
"Unknown default value");
2194 return std::nullopt;
2197SVal RegionStoreManager::getLazyBinding(
const SubRegion *LazyBindingRegion,
2198 RegionBindingsRef LazyBinding) {
2200 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
2201 Result = getBindingForElement(LazyBinding, ER);
2203 Result = getBindingForField(LazyBinding,
2228 const TypedValueRegion *R,
2235 Store lazyBindingStore =
nullptr;
2236 const SubRegion *lazyBindingRegion =
nullptr;
2237 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
2238 if (lazyBindingRegion)
2239 return getLazyBinding(lazyBindingRegion,
2240 getRegionBindings(lazyBindingStore));
2244 bool hasSymbolicIndex =
false;
2260 bool hasPartialLazyBinding =
false;
2262 const SubRegion *SR = R;
2265 if (std::optional<SVal> D =
2266 getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
2267 if (D->getAs<nonloc::LazyCompoundVal>()) {
2268 hasPartialLazyBinding =
true;
2275 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(Base)) {
2276 NonLoc index = ER->getIndex();
2278 hasSymbolicIndex =
true;
2283 SR = dyn_cast<SubRegion>(Base);
2290 if (
const TypedValueRegion *typedSuperR =
2292 if (typedSuperR->getValueType()->isVectorType())
2293 return UnknownVal();
2301 if (hasSymbolicIndex)
2302 return UnknownVal();
2308 if (
const std::optional<SVal> &
V = B.getDefaultBinding(R))
2310 return UndefinedVal();
2319 const ObjCIvarRegion* R) {
2321 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2327 if (
const std::optional<SVal> &
V = B.getDefaultBinding(superR)) {
2332 return UnknownVal();
2335 return getBindingForLazySymbol(R);
2339 const VarRegion *R) {
2342 if (std::optional<SVal>
V = B.getDirectBinding(R))
2345 if (std::optional<SVal>
V = B.getDefaultBinding(R))
2349 const VarDecl *VD = R->
getDecl();
2365 return UnknownVal();
2378 if (B.isMainAnalysis())
2390 if (std::optional<SVal>
V = getBindingForDerivedDefaultValue(B, MS, R, T)) {
2391 assert(!
V->getAs<nonloc::LazyCompoundVal>());
2398 return UndefinedVal();
2401SVal RegionStoreManager::getBindingForLazySymbol(
const TypedValueRegion *R) {
2406const RegionStoreManager::SValListTy &
2407RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
2409 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.
getCVData());
2410 if (I != LazyBindingsMap.end())
2416 const SubRegion *LazyR = LCV.
getRegion();
2417 RegionBindingsRef B = getRegionBindings(LCV.
getStore());
2423 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2425 SmallVector<BindingPair, 32>
Bindings;
2428 for (SVal
V : llvm::make_second_range(
Bindings)) {
2429 if (
V.isUnknownOrUndef() ||
V.isConstant())
2432 if (
auto InnerLCV =
V.getAs<nonloc::LazyCompoundVal>()) {
2433 const SValListTy &InnerList = getInterestingValues(*InnerLCV);
2434 llvm::append_range(List, InnerList);
2440 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2444 const TypedValueRegion *R) {
2445 if (std::optional<nonloc::LazyCompoundVal>
V =
2453 const TypedValueRegion *R) {
2454 const RecordDecl *RD =
2457 return UnknownVal();
2463 return createLazyBinding(B, R);
2467 const TypedValueRegion *R) {
2469 "Only constant array types can have compound bindings.");
2471 return createLazyBinding(B, R);
2474bool RegionStoreManager::includedInBindings(
Store store,
2475 const MemRegion *region)
const {
2476 RegionBindingsRef B = getRegionBindings(store);
2480 if (B.lookup(region))
2484 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
2486 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
2488 SVal D = CI.getData();
2502StoreRef RegionStoreManager::killBinding(
Store ST, Loc L) {
2503 if (std::optional<loc::MemRegionVal> LV = L.
getAs<loc::MemRegionVal>())
2504 if (
const MemRegion* R = LV->getRegion())
2505 return StoreRef(getRegionBindings(ST)
2508 .getRootWithoutRetain(),
2511 return StoreRef(ST, *
this);
2514LimitedRegionBindingsRef
2516 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bind",
2517 [&L]() {
return locDescr(L); });
2523 auto MemRegVal = L.
getAs<loc::MemRegionVal>();
2527 const MemRegion *R = MemRegVal->getRegion();
2531 if (
const auto *SymReg = dyn_cast<SymbolicRegion>(R)) {
2532 QualType Ty = SymReg->getPointeeStaticType();
2534 Ty = StateMgr.getContext().CharTy;
2535 R = GetElementZeroRegion(SymReg, Ty);
2539 if (
const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
2542 return bindArray(B, TR,
V);
2544 return bindStruct(B, TR,
V);
2546 return bindVector(B, TR,
V);
2548 return bindAggregate(B, TR,
V);
2552 "'this' pointer is not an l-value and is not assignable");
2559 : BindingKey::Direct;
2560 return NewB.addBinding(BindingKey::Make(R, KeyKind),
V);
2563LimitedRegionBindingsRef
2565 const MemRegion *R, QualType T) {
2573 if (B.getDefaultBinding(R).has_value()) {
2600std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallArray(
2602 const ArrayType *AT, nonloc::LazyCompoundVal LCV) {
2606 auto CAT = dyn_cast<ConstantArrayType>(AT);
2610 return std::nullopt;
2614 return std::nullopt;
2618 if (ArrSize > SmallArrayLimit)
2619 return std::nullopt;
2621 LimitedRegionBindingsRef NewB = B;
2623 for (uint64_t i = 0; i < ArrSize; ++i) {
2625 const ElementRegion *SrcER =
2626 MRMgr.getElementRegion(Ty, Idx, LCV.
getRegion(), Ctx);
2627 SVal
V = getBindingForElement(getRegionBindings(LCV.
getStore()), SrcER);
2629 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2630 NewB = bind(NewB, loc::MemRegionVal(DstER),
V);
2636LimitedRegionBindingsRef
2638 const TypedValueRegion *R, SVal
Init) {
2639 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindArray",
2646 std::optional<uint64_t>
Size;
2648 if (
const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
2654 if (std::optional<loc::MemRegionVal> MRV =
Init.getAs<loc::MemRegionVal>()) {
2656 return bindAggregate(B, R,
V);
2661 if (
Init.isConstant())
2662 return bindAggregate(B, R,
Init);
2664 if (std::optional LCV =
Init.getAs<nonloc::LazyCompoundVal>()) {
2665 if (std::optional NewB = tryBindSmallArray(B, R, AT, *LCV))
2667 return bindAggregate(B, R,
Init);
2671 return bindAggregate(B, R,
Init);
2674 const nonloc::CompoundVal& CV =
Init.castAs<nonloc::CompoundVal>();
2678 LimitedRegionBindingsRef NewB = B;
2680 for (;
Size ? i < *
Size :
true; ++i, ++VI) {
2688 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2691 NewB = bindStruct(NewB, ER, *VI);
2693 NewB = bindArray(NewB, ER, *VI);
2695 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2701 if (!Size || i < *Size)
2702 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2707LimitedRegionBindingsRef
2709 const TypedValueRegion *R, SVal
V) {
2710 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindVector",
2716 const VectorType *VT = T->
castAs<VectorType>();
2720 return bindAggregate(B, R,
V);
2726 return bindAggregate(B, R, UnknownVal());
2730 nonloc::CompoundVal CV =
V.
castAs<nonloc::CompoundVal>();
2733 LimitedRegionBindingsRef NewB = B;
2735 for ( ; index != numElements ; ++index) {
2743 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2746 NewB = bindArray(NewB, ER, *VI);
2748 NewB = bindStruct(NewB, ER, *VI);
2750 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2755std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
2757 const RecordDecl *RD, nonloc::LazyCompoundVal LCV) {
2763 if (
const CXXRecordDecl *
Class = dyn_cast<CXXRecordDecl>(RD))
2764 if (
Class->getNumBases() != 0 ||
Class->getNumVBases() != 0)
2765 return std::nullopt;
2767 for (
const auto *FD : RD->
fields()) {
2773 if (Fields.size() == SmallStructLimit)
2774 return std::nullopt;
2784 return std::nullopt;
2786 Fields.push_back(FD);
2789 LimitedRegionBindingsRef NewB = B;
2791 for (
const FieldDecl *Field : Fields) {
2792 const FieldRegion *SourceFR = MRMgr.getFieldRegion(Field, LCV.
getRegion());
2793 SVal
V = getBindingForField(getRegionBindings(LCV.
getStore()), SourceFR);
2795 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
2796 NewB = bind(NewB, loc::MemRegionVal(DestFR),
V);
2802LimitedRegionBindingsRef
2804 const TypedValueRegion *R, SVal
V) {
2805 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindStruct",
2818 if (std::optional<nonloc::LazyCompoundVal> LCV =
2819 V.getAs<nonloc::LazyCompoundVal>()) {
2820 if (std::optional NewB = tryBindSmallStruct(B, R, RD, *LCV))
2822 return bindAggregate(B, R,
V);
2825 return bindAggregate(B, R,
V);
2831 return bindAggregate(B, R, UnknownVal());
2849 const nonloc::CompoundVal& CV =
V.
castAs<nonloc::CompoundVal>();
2852 LimitedRegionBindingsRef NewB = B;
2856 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
2864 assert((CRD->isAggregate() || (Ctx.
getLangOpts().ObjC && VI == VE)) &&
2865 "Non-aggregates are constructed with a constructor!");
2867 for (
const auto &B : CRD->bases()) {
2869 assert(!B.isVirtual() &&
"Aggregates cannot have virtual base classes!");
2876 QualType BTy = B.getType();
2880 assert(BRD &&
"Base classes must be C++ classes!");
2882 const CXXBaseObjectRegion *BR =
2883 MRMgr.getCXXBaseObjectRegion(BRD, R,
false);
2885 NewB = bindStruct(NewB, BR, *VI);
2902 if (FI->isUnnamedBitField())
2905 QualType FTy = FI->getType();
2906 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2909 NewB = bindArray(NewB, FR, *VI);
2911 NewB = bindStruct(NewB, FR, *VI);
2913 NewB = bind(NewB, loc::MemRegionVal(FR), *VI);
2922 NewB = NewB.
addBinding(R, BindingKey::Default,
2929LimitedRegionBindingsRef
2931 const TypedRegion *R, SVal Val) {
2932 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindAggregate",
2939 return removeSubRegionBindings(B, R).
addBinding(R, BindingKey::Default, Val);
2947class RemoveDeadBindingsWorker
2948 :
public ClusterAnalysis<RemoveDeadBindingsWorker> {
2949 SmallVector<const SymbolicRegion *, 12> Postponed;
2950 SymbolReaper &SymReaper;
2951 const StackFrameContext *CurrentLCtx;
2954 RemoveDeadBindingsWorker(RegionStoreManager &rm,
2955 ProgramStateManager &stateMgr,
2956 RegionBindingsRef
b, SymbolReaper &symReaper,
2957 const StackFrameContext *LCtx)
2958 : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr,
b),
2959 SymReaper(symReaper), CurrentLCtx(LCtx) {}
2962 void VisitAddedToCluster(
const MemRegion *baseR,
const ClusterBindings &
C);
2964 using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
2966 using ClusterAnalysis::AddToWorkList;
2968 bool AddToWorkList(
const MemRegion *R);
2970 bool UpdatePostponed();
2971 void VisitBinding(SVal
V);
2975bool RemoveDeadBindingsWorker::AddToWorkList(
const MemRegion *R) {
2977 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
2980void RemoveDeadBindingsWorker::VisitAddedToCluster(
const MemRegion *baseR,
2983 if (
const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
2984 if (SymReaper.
isLive(VR))
2985 AddToWorkList(baseR, &
C);
2990 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
2991 if (SymReaper.
isLive(SR->getSymbol()))
2992 AddToWorkList(SR, &
C);
2994 Postponed.push_back(SR);
3000 AddToWorkList(baseR, &
C);
3005 if (
const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
3006 const auto *StackReg =
3008 const StackFrameContext *RegCtx = StackReg->getStackFrame();
3010 (RegCtx == CurrentLCtx || RegCtx->
isParentOf(CurrentLCtx)))
3011 AddToWorkList(TR, &
C);
3015void RemoveDeadBindingsWorker::VisitCluster(
const MemRegion *baseR,
3022 if (
const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
3023 SymReaper.
markLive(SymR->getSymbol());
3025 for (
const auto &[Key, Val] : *
C) {
3033void RemoveDeadBindingsWorker::VisitBinding(SVal
V) {
3036 if (
auto LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
3039 for (SVal
V : RM.getInterestingValues(*LCS)) {
3040 if (
auto DepLCS =
V.getAs<nonloc::LazyCompoundVal>())
3050 if (
const MemRegion *R =
V.getAsRegion()) {
3055 if (
const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
3056 for (
auto Var : BR->referenced_vars())
3057 AddToWorkList(Var.getCapturedRegion());
3067bool RemoveDeadBindingsWorker::UpdatePostponed() {
3072 for (
const SymbolicRegion *SR : Postponed) {
3073 if (SymReaper.
isLive(SR->getSymbol())) {
3082StoreRef RegionStoreManager::removeDeadBindings(
Store store,
3083 const StackFrameContext *LCtx,
3084 SymbolReaper& SymReaper) {
3085 RegionBindingsRef B = getRegionBindings(store);
3086 RemoveDeadBindingsWorker W(*
this, StateMgr, B, SymReaper, LCtx);
3087 W.GenerateClusters();
3090 for (
const MemRegion *Reg : SymReaper.
regions()) {
3091 W.AddToWorkList(Reg);
3094 do W.RunWorkList();
while (W.UpdatePostponed());
3099 for (
const MemRegion *Base : llvm::make_first_range(B)) {
3102 if (!W.isVisited(Base))
3103 B = B.removeCluster(Base);
3106 return StoreRef(B.asStore(), *
this);
3113void RegionStoreManager::printJson(raw_ostream &Out,
Store S,
const char *NL,
3114 unsigned int Space,
bool IsDot)
const {
3115 RegionBindingsRef
Bindings = getRegionBindings(S);
3117 Indent(Out, Space, IsDot) <<
"\"store\": ";
3120 Out <<
"null," << NL;
3124 Out <<
"{ \"pointer\": \"" <<
Bindings.asStore() <<
"\", \"items\": [" << NL;
3125 Bindings.printJson(Out, NL, Space + 1, IsDot);
3126 Indent(Out, Space, IsDot) <<
"]}," << NL;
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)
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)
const LimitedRegionBindingsRef & LimitedRegionBindingsConstRef
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
A signed integer type that is the result of subtracting two pointers.
This class represents the same as RegionBindingsRef, but with a limit on the number of bindings that ...
LimitedRegionBindingsRef removeCluster(const MemRegion *BaseRegion) const
LimitedRegionBindingsRef withValuesEscaped(nonloc::CompoundVal::iterator Begin, nonloc::CompoundVal::iterator End) const
LimitedRegionBindingsRef withValuesEscaped(SVal V) const
LimitedRegionBindingsRef(RegionBindingsRef Base, SmallVectorImpl< SVal > &EscapedValuesDuringBind, std::optional< unsigned > BindingsLeft)
bool hasExhaustedBindingLimit() const
LimitedRegionBindingsRef addBinding(BindingKey K, SVal V) const
LimitedRegionBindingsRef addBinding(const MemRegion *R, BindingKey::Kind k, SVal V) const
LimitedRegionBindingsRef addWithoutDecreasingLimit(const MemRegion *BaseRegion, data_type_ref BindingKeyAndValue) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() 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.
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.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
QualType getElementType() const
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.
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.
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
bool isParentOf(const LocationContext *LC) const
const Decl * getDecl() 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.
field_iterator field_end() const
field_range fields() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
unsigned getLength() const
uint32_t getCodeUnit(size_t i) const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
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<specific type>.
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.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
QualType getCanonicalTypeInternal() const
bool isStructureOrClassType() const
bool isVectorType() const
const T * castAsCanonical() const
Return this type's canonical type cast to the specified type.
bool isRecordType() const
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.
unsigned getNumElements() const
QualType getElementType() const
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.
LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override
void dumpToStream(raw_ostream &Out) const
static bool isLocType(QualType T)
DefinedOrUnknownSVal getStaticSize(const MemRegion *MR, SValBuilder &SVB) const
MemRegion - The root abstract class for all memory regions.
virtual bool isBoundable() const
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
std::string getDescriptiveName(bool UseQuotes=true) const
Get descriptive name for memory region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getRawMemorySpace() const
Deprecated.
@ 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.
bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const
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 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.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
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.
bool scan(nonloc::LazyCompoundVal val)
SmallVector< const MemRegion *, 8 > InvalidatedRegions
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
llvm::iterator_range< symbol_iterator > symbols() const
static bool canSymbolicate(QualType T)
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
void markElementIndicesLive(const MemRegion *region)
void markLazilyCopied(const MemRegion *region)
bool isLive(SymbolRef sym)
llvm::iterator_range< RegionSetTy::const_iterator > regions() const
SymbolicRegion - A special, "non-concrete" region.
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::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
const SymExpr * SymbolRef
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
The JSON file list parser is used to communicate input to InstallAPI.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
bool isa(CodeGen::Address addr)
CFGBlock::ConstCFGElementRef ConstCFGElementRef
@ 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.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
@ Result
The result type of a method or function.
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ConceptReference *C)
Insertion operator for diagnostics.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Diagnostic wrappers for TextAPI types for error reporting.
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...