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) {
2592std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallArray(
2594 const ArrayType *AT, nonloc::LazyCompoundVal LCV) {
2598 auto CAT = dyn_cast<ConstantArrayType>(AT);
2602 return std::nullopt;
2606 return std::nullopt;
2610 if (ArrSize > SmallArrayLimit)
2611 return std::nullopt;
2613 LimitedRegionBindingsRef NewB = B;
2615 for (uint64_t i = 0; i < ArrSize; ++i) {
2617 const ElementRegion *SrcER =
2618 MRMgr.getElementRegion(Ty, Idx, LCV.
getRegion(), Ctx);
2619 SVal
V = getBindingForElement(getRegionBindings(LCV.
getStore()), SrcER);
2621 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2622 NewB = bind(NewB, loc::MemRegionVal(DstER),
V);
2628LimitedRegionBindingsRef
2630 const TypedValueRegion *R, SVal
Init) {
2631 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindArray",
2638 std::optional<uint64_t>
Size;
2640 if (
const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
2646 if (std::optional<loc::MemRegionVal> MRV =
Init.getAs<loc::MemRegionVal>()) {
2648 return bindAggregate(B, R,
V);
2653 if (
Init.isConstant())
2654 return bindAggregate(B, R,
Init);
2656 if (std::optional LCV =
Init.getAs<nonloc::LazyCompoundVal>()) {
2657 if (std::optional NewB = tryBindSmallArray(B, R, AT, *LCV))
2659 return bindAggregate(B, R,
Init);
2663 return bindAggregate(B, R,
Init);
2665 if (
Init.isUnknown())
2666 return bindAggregate(B, R, UnknownVal());
2669 const nonloc::CompoundVal& CV =
Init.castAs<nonloc::CompoundVal>();
2673 LimitedRegionBindingsRef NewB = B;
2675 for (;
Size ? i < *
Size :
true; ++i, ++VI) {
2683 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2686 NewB = bindStruct(NewB, ER, *VI);
2688 NewB = bindArray(NewB, ER, *VI);
2690 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2696 if (!Size || i < *Size)
2697 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2702LimitedRegionBindingsRef
2704 const TypedValueRegion *R, SVal
V) {
2705 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindVector",
2711 const VectorType *VT =
T->
castAs<VectorType>();
2715 return bindAggregate(B, R,
V);
2721 return bindAggregate(B, R, UnknownVal());
2725 nonloc::CompoundVal CV =
V.
castAs<nonloc::CompoundVal>();
2728 LimitedRegionBindingsRef NewB = B;
2730 for ( ; index != numElements ; ++index) {
2738 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2741 NewB = bindArray(NewB, ER, *VI);
2743 NewB = bindStruct(NewB, ER, *VI);
2745 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2750std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
2752 const RecordDecl *RD, nonloc::LazyCompoundVal LCV) {
2758 if (
const CXXRecordDecl *
Class = dyn_cast<CXXRecordDecl>(RD))
2759 if (
Class->getNumBases() != 0 ||
Class->getNumVBases() != 0)
2760 return std::nullopt;
2762 for (
const auto *FD : RD->
fields()) {
2768 if (Fields.size() == SmallStructLimit)
2769 return std::nullopt;
2779 return std::nullopt;
2781 Fields.push_back(FD);
2784 LimitedRegionBindingsRef NewB = B;
2786 for (
const FieldDecl *Field : Fields) {
2787 const FieldRegion *SourceFR = MRMgr.getFieldRegion(Field, LCV.
getRegion());
2788 SVal
V = getBindingForField(getRegionBindings(LCV.
getStore()), SourceFR);
2790 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
2791 NewB = bind(NewB, loc::MemRegionVal(DestFR),
V);
2797LimitedRegionBindingsRef
2799 const TypedValueRegion *R, SVal
V) {
2800 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindStruct",
2813 if (std::optional<nonloc::LazyCompoundVal> LCV =
2814 V.getAs<nonloc::LazyCompoundVal>()) {
2815 if (std::optional NewB = tryBindSmallStruct(B, R, RD, *LCV))
2817 return bindAggregate(B, R,
V);
2820 return bindAggregate(B, R,
V);
2826 return bindAggregate(B, R, UnknownVal());
2844 const nonloc::CompoundVal& CV =
V.
castAs<nonloc::CompoundVal>();
2847 LimitedRegionBindingsRef NewB = B;
2851 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
2859 assert((CRD->isAggregate() || (Ctx.
getLangOpts().ObjC && VI == VE)) &&
2860 "Non-aggregates are constructed with a constructor!");
2862 for (
const auto &B : CRD->bases()) {
2864 assert(!B.isVirtual() &&
"Aggregates cannot have virtual base classes!");
2871 QualType BTy = B.getType();
2875 assert(BRD &&
"Base classes must be C++ classes!");
2877 const CXXBaseObjectRegion *BR =
2878 MRMgr.getCXXBaseObjectRegion(BRD, R,
false);
2880 NewB = bindStruct(NewB, BR, *VI);
2897 if (FI->isUnnamedBitField())
2900 QualType FTy = FI->getType();
2901 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2904 NewB = bindArray(NewB, FR, *VI);
2906 NewB = bindStruct(NewB, FR, *VI);
2908 NewB = bind(NewB, loc::MemRegionVal(FR), *VI);
2917 NewB = NewB.
addBinding(R, BindingKey::Default,
2924LimitedRegionBindingsRef
2926 const TypedRegion *R, SVal Val) {
2927 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindAggregate",
2934 return removeSubRegionBindings(B, R).
addBinding(R, BindingKey::Default, Val);
2942class RemoveDeadBindingsWorker
2943 :
public ClusterAnalysis<RemoveDeadBindingsWorker> {
2944 SmallVector<const SymbolicRegion *, 12> Postponed;
2945 SymbolReaper &SymReaper;
2946 const StackFrameContext *CurrentLCtx;
2949 RemoveDeadBindingsWorker(RegionStoreManager &rm,
2950 ProgramStateManager &stateMgr,
2951 RegionBindingsRef
b, SymbolReaper &symReaper,
2952 const StackFrameContext *LCtx)
2953 : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr,
b),
2954 SymReaper(symReaper), CurrentLCtx(LCtx) {}
2957 void VisitAddedToCluster(
const MemRegion *baseR,
const ClusterBindings &
C);
2959 using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
2961 using ClusterAnalysis::AddToWorkList;
2963 bool AddToWorkList(
const MemRegion *R);
2965 bool UpdatePostponed();
2966 void VisitBinding(SVal
V);
2970bool RemoveDeadBindingsWorker::AddToWorkList(
const MemRegion *R) {
2972 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
2975void RemoveDeadBindingsWorker::VisitAddedToCluster(
const MemRegion *baseR,
2978 if (
const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
2979 if (SymReaper.
isLive(VR))
2980 AddToWorkList(baseR, &
C);
2985 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
2986 if (SymReaper.
isLive(SR->getSymbol()))
2987 AddToWorkList(SR, &
C);
2989 Postponed.push_back(SR);
2995 AddToWorkList(baseR, &
C);
3000 if (
const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
3001 const auto *StackReg =
3003 const StackFrameContext *RegCtx = StackReg->getStackFrame();
3005 (RegCtx == CurrentLCtx || RegCtx->
isParentOf(CurrentLCtx)))
3006 AddToWorkList(TR, &
C);
3010void RemoveDeadBindingsWorker::VisitCluster(
const MemRegion *baseR,
3017 if (
const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
3018 SymReaper.
markLive(SymR->getSymbol());
3020 for (
const auto &[Key, Val] : *
C) {
3028void RemoveDeadBindingsWorker::VisitBinding(SVal
V) {
3031 if (
auto LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
3034 for (SVal
V : RM.getInterestingValues(*LCS)) {
3035 if (
auto DepLCS =
V.getAs<nonloc::LazyCompoundVal>())
3045 if (
const MemRegion *R =
V.getAsRegion()) {
3050 if (
const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
3051 for (
auto Var : BR->referenced_vars())
3052 AddToWorkList(Var.getCapturedRegion());
3062bool RemoveDeadBindingsWorker::UpdatePostponed() {
3067 for (
const SymbolicRegion *SR : Postponed) {
3068 if (SymReaper.
isLive(SR->getSymbol())) {
3077StoreRef RegionStoreManager::removeDeadBindings(
Store store,
3078 const StackFrameContext *LCtx,
3079 SymbolReaper& SymReaper) {
3080 RegionBindingsRef B = getRegionBindings(store);
3081 RemoveDeadBindingsWorker W(*
this, StateMgr, B, SymReaper, LCtx);
3082 W.GenerateClusters();
3085 for (
const MemRegion *Reg : SymReaper.
regions()) {
3086 W.AddToWorkList(Reg);
3089 do W.RunWorkList();
while (W.UpdatePostponed());
3094 for (
const MemRegion *Base : llvm::make_first_range(B)) {
3097 if (!W.isVisited(Base))
3098 B = B.removeCluster(Base);
3101 return StoreRef(B.asStore(), *
this);
3108void RegionStoreManager::printJson(raw_ostream &Out,
Store S,
const char *NL,
3109 unsigned int Space,
bool IsDot)
const {
3110 RegionBindingsRef
Bindings = getRegionBindings(S);
3112 Indent(Out, Space, IsDot) <<
"\"store\": ";
3115 Out <<
"null," << NL;
3119 Out <<
"{ \"pointer\": \"" <<
Bindings.asStore() <<
"\", \"items\": [" << NL;
3120 Bindings.printJson(Out, NL, Space + 1, IsDot);
3121 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 FunctionProtoType * T
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...