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) {
128 const RegionOffset &RO =
R->getAsOffset();
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 StackFrame *SF)
override {
554 bool IsMainAnalysis =
false;
555 if (
const auto *FD = dyn_cast<FunctionDecl>(SF->
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 StackFrame *SF,
571 InvalidatedRegions *Invalidated);
573 StoreRef invalidateRegions(
Store store, ArrayRef<SVal> Values,
575 const StackFrame *SF,
const CallEvent *
Call,
577 RegionAndSymbolInvalidationTraits &ITraits,
578 InvalidatedRegions *Invalidated,
579 InvalidatedRegions *InvalidatedTopLevel)
override;
581 bool scanReachableSymbols(
Store S,
const MemRegion *R,
582 ScanReachableSymbols &Callbacks)
override;
584 LimitedRegionBindingsRef
588 const ElementRegion *R);
590 getSValFromInitListExpr(
const InitListExpr *ILE,
591 const SmallVector<uint64_t, 2> &ConcreteOffsets,
593 SVal getSValFromStringLiteral(
const StringLiteral *SL, uint64_t Offset,
597 BindResult
Bind(
Store store, Loc LV, SVal
V)
override {
598 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
599 LimitedRegionBindingsRef BoundedBindings =
600 getRegionBindings(store, EscapedValuesDuringBind);
601 return BindResult{StoreRef(bind(BoundedBindings, LV,
V).asStore(), *
this),
602 std::move(EscapedValuesDuringBind)};
610 BindResult BindDefaultInitial(
Store store,
const MemRegion *R,
612 RegionBindingsRef B = getRegionBindings(store);
615 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
616 "Double initialization!");
617 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
619 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this), {}};
624 BindResult BindDefaultZero(
Store store,
const MemRegion *R)
override {
634 if (
const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
635 if (BR->getDecl()->isEmpty())
636 return BindResult{StoreRef(store, *
this), {}};
638 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
639 LimitedRegionBindingsRef B =
640 getRegionBindings(store, EscapedValuesDuringBind);
641 SVal
V = svalBuilder.makeZeroVal(Ctx.CharTy);
643 B = B.
addBinding(BindingKey::Make(R, BindingKey::Default),
V);
645 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this),
646 std::move(EscapedValuesDuringBind)};
659 std::optional<LimitedRegionBindingsRef>
661 const RecordDecl *RD, nonloc::LazyCompoundVal LCV);
665 const TypedValueRegion *R, SVal
V);
669 const TypedValueRegion *R, SVal
V);
671 std::optional<LimitedRegionBindingsRef>
673 const ArrayType *AT, nonloc::LazyCompoundVal LCV);
676 const TypedValueRegion *R, SVal
V);
681 const TypedRegion *R, SVal DefaultVal);
686 StoreRef killBinding(
Store ST, Loc L)
override;
688 void incrementReferenceCount(
Store store)
override {
689 getRegionBindings(store).manualRetain();
695 void decrementReferenceCount(
Store store)
override {
696 getRegionBindings(store).manualRelease();
699 bool includedInBindings(
Store store,
const MemRegion *region)
const override;
714 SVal getBinding(
Store S, Loc L, QualType T)
override {
715 return getBinding(getRegionBindings(S), L, T);
718 std::optional<SVal> getDefaultBinding(
Store S,
const MemRegion *R)
override {
719 RegionBindingsRef B = getRegionBindings(S);
723 return B.getDefaultBinding(
R->getBaseRegion());
736 SVal getBindingForLazySymbol(
const TypedValueRegion *R);
739 const TypedValueRegion *R,
742 SVal getLazyBinding(
const SubRegion *LazyBindingRegion,
743 RegionBindingsRef LazyBinding);
761 const MemRegion *superR,
762 const TypedValueRegion *R, QualType Ty);
768 std::pair<Store, const SubRegion *>
770 const SubRegion *originalRegion);
782 const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);
790 StoreRef removeDeadBindings(
Store store,
const StackFrame *SF,
791 SymbolReaper &SymReaper)
override;
797 RegionBindingsRef getRegionBindings(
Store store)
const {
798 llvm::PointerIntPair<Store, 1, bool> Ptr;
799 Ptr.setFromOpaqueValue(
const_cast<void *
>(store));
801 static_cast<const RegionBindings::TreeTy *
>(Ptr.getPointer()),
802 RBFactory.getTreeFactory(), Ptr.getInt()};
805 LimitedRegionBindingsRef
806 getRegionBindings(
Store store,
807 SmallVectorImpl<SVal> &EscapedValuesDuringBind)
const {
808 return LimitedRegionBindingsRef(
809 getRegionBindings(store), EscapedValuesDuringBind,
810 RegionStoreMaxBindingFanOutPlusOne);
813 void printJson(raw_ostream &Out,
Store S,
const char *NL =
"\n",
814 unsigned int Space = 0,
bool IsDot =
false)
const override;
816 void iterBindings(
Store store, BindingsHandler& f)
override {
817 RegionBindingsRef B = getRegionBindings(store);
818 for (
const auto &[Region, Cluster] : B) {
819 for (
const auto &[Key,
Value] : Cluster) {
822 if (
const SubRegion *R = dyn_cast<SubRegion>(Key.getRegion())) {
824 if (!f.HandleBinding(*
this, store, R,
Value))
838std::unique_ptr<StoreManager>
840 return std::make_unique<RegionStoreManager>(StMgr);
850enum GlobalsFilterKind {
859template <
typename DERIVED>
860class ClusterAnalysis {
862 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
863 typedef const MemRegion * WorkListElement;
870 RegionStoreManager &RM;
885 bool includeEntireMemorySpace(
const MemRegion *Base) {
890 ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
892 : RM(rm), Ctx(StateMgr.getContext()),
893 svalBuilder(StateMgr.getSValBuilder()), B(std::move(
b)) {}
895 RegionBindingsRef getRegionBindings()
const {
return B; }
897 bool isVisited(
const MemRegion *R) {
898 return Visited.count(getCluster(R));
901 void GenerateClusters() {
903 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
905 const MemRegion *
Base = RI.getKey();
908 assert(!Cluster.isEmpty() &&
"Empty clusters should be removed");
909 static_cast<DERIVED*
>(
this)->VisitAddedToCluster(Base, Cluster);
913 if (
static_cast<DERIVED*
>(
this)->includeEntireMemorySpace(Base))
914 AddToWorkList(WorkListElement(Base), &Cluster);
919 if (
C && !Visited.insert(
C).second)
925 bool AddToWorkList(
const MemRegion *R) {
926 return static_cast<DERIVED*
>(
this)->AddToWorkList(R);
930 while (!WL.empty()) {
931 WorkListElement E = WL.pop_back_val();
932 const MemRegion *BaseR = E;
934 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR, getCluster(BaseR));
938 void VisitAddedToCluster(
const MemRegion *baseR,
const ClusterBindings &
C) {}
943 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR,
C);
952bool RegionStoreManager::scanReachableSymbols(
Store S,
const MemRegion *R,
953 ScanReachableSymbols &Callbacks) {
954 assert(R ==
R->getBaseRegion() &&
"Should only be called for base regions");
955 RegionBindingsRef B = getRegionBindings(S);
961 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
963 if (!Callbacks.
scan(RI.getData()))
977 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
983 if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R))
985 Fields.push_back(FR->getDecl());
992 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
1000 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
1002 return std::equal(FieldsInBindingKey.begin() + Delta,
1003 FieldsInBindingKey.end(),
1006 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
1007 Fields.begin() - Delta);
1022 const SubRegion *Top, BindingKey TopKey,
1023 bool IncludeAllDefaultBindings) {
1025 if (TopKey.hasSymbolicOffset()) {
1027 Top = TopKey.getConcreteOffsetRegion();
1028 TopKey = BindingKey::Make(Top, BindingKey::Default);
1032 uint64_t Length = UINT64_MAX;
1034 if (std::optional<nonloc::ConcreteInt> ExtentCI =
1036 const llvm::APSInt &ExtentInt = ExtentCI->getValue();
1037 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
1040 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
1041 if (FR->getDecl()->isBitField())
1042 Length = FR->getDecl()->getBitWidthValue();
1045 for (
const auto &StoreEntry : Cluster) {
1046 BindingKey NextKey = StoreEntry.first;
1047 if (NextKey.getRegion() == TopKey.getRegion()) {
1053 if (NextKey.getOffset() > TopKey.getOffset() &&
1054 NextKey.getOffset() - TopKey.getOffset() < Length) {
1059 }
else if (NextKey.getOffset() == TopKey.getOffset()) {
1066 if (IncludeAllDefaultBindings || NextKey.isDirect())
1070 }
else if (NextKey.hasSymbolicOffset()) {
1076 if (IncludeAllDefaultBindings || NextKey.isDirect())
1079 }
else if (
const SubRegion *BaseSR = dyn_cast<SubRegion>(
Base)) {
1082 if (BaseSR->isSubRegionOf(Top))
1093 const SubRegion *Top,
bool IncludeAllDefaultBindings) {
1095 BindingKey::Make(Top, BindingKey::Default),
1096 IncludeAllDefaultBindings);
1099LimitedRegionBindingsRef
1101 const SubRegion *Top) {
1102 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
1103 const MemRegion *ClusterHead = TopKey.getBaseRegion();
1105 if (Top == ClusterHead) {
1114 if (TopKey.hasSymbolicOffset()) {
1115 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1116 return B.
addBinding(Concrete, BindingKey::Default, UnknownVal());
1121 SmallVector<BindingPair, 32>
Bindings;
1126 for (BindingKey Key : llvm::make_first_range(
Bindings))
1133 if (TopKey.hasSymbolicOffset()) {
1134 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1135 Result =
Result.add(BindingKey::Make(Concrete, BindingKey::Default),
1145class InvalidateRegionsWorker :
public ClusterAnalysis<InvalidateRegionsWorker>
1149 const StackFrame *SF;
1151 RegionAndSymbolInvalidationTraits &ITraits;
1153 GlobalsFilterKind GlobalsFilter;
1155 InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
1157 unsigned count,
const StackFrame *SF,
1159 RegionAndSymbolInvalidationTraits &ITraitsIn,
1161 GlobalsFilterKind GFK)
1162 : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr,
b), Elem(elem),
1163 Count(count), SF(SF), IS(
is), ITraits(ITraitsIn), Regions(r),
1164 GlobalsFilter(GFK) {}
1167 void VisitBinding(SVal
V);
1169 using ClusterAnalysis::AddToWorkList;
1171 bool AddToWorkList(
const MemRegion *R);
1175 bool includeEntireMemorySpace(
const MemRegion *Base);
1179 bool isInitiallyIncludedGlobalRegion(
const MemRegion *R);
1183bool InvalidateRegionsWorker::AddToWorkList(
const MemRegion *R) {
1184 bool doNotInvalidateSuperRegion = ITraits.
hasTrait(
1186 const MemRegion *BaseR = doNotInvalidateSuperRegion ?
R :
R->getBaseRegion();
1187 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
1190void InvalidateRegionsWorker::VisitBinding(SVal
V) {
1195 if (
const MemRegion *R =
V.getAsRegion()) {
1201 if (std::optional<nonloc::LazyCompoundVal> LCS =
1202 V.getAs<nonloc::LazyCompoundVal>()) {
1206 for (SVal
V : RM.getInterestingValues(*LCS))
1214void InvalidateRegionsWorker::VisitCluster(
const MemRegion *baseR,
1217 bool PreserveRegionsContents =
1222 for (SVal Val : llvm::make_second_range(*
C))
1226 if (!PreserveRegionsContents)
1230 if (
const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
1231 if (
const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
1236 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
1237 using namespace ast_matchers;
1239 const char *DeclBind =
"DeclBind";
1241 to(
varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
1243 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
1244 RD->getASTContext());
1246 for (BoundNodes &
Match : Matches) {
1247 auto *VD =
Match.getNodeAs<VarDecl>(DeclBind);
1248 const VarRegion *ToInvalidate =
1249 RM.getRegionManager().getVarRegion(VD, SF);
1250 AddToWorkList(ToInvalidate);
1258 if (
const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
1259 for (
auto Var : BR->referenced_vars()) {
1260 const VarRegion *VR = Var.getCapturedRegion();
1261 const VarDecl *VD = VR->
getDecl();
1271 SVal
V = RM.getBinding(B, loc::MemRegionVal(VR));
1272 if (std::optional<Loc> L =
V.getAs<Loc>()) {
1282 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
1283 IS.insert(SR->getSymbol());
1286 if (PreserveRegionsContents)
1291 Regions->push_back(baseR);
1296 DefinedOrUnknownSVal
V =
1308 if (isInitiallyIncludedGlobalRegion(baseR)) {
1318 DefinedOrUnknownSVal
V =
1325 bool doNotInvalidateSuperRegion = ITraits.
hasTrait(
1329 if (doNotInvalidateSuperRegion) {
1332 std::optional<uint64_t> NumElements;
1335 if (
const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
1336 NumElements = CAT->getZExtSize();
1338 goto conjure_default;
1339 QualType ElementTy = AT->getElementType();
1347 AddToWorkList(SuperR);
1348 goto conjure_default;
1352 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
1353 bool UpperOverflow = UpperOffset < LowerOffset;
1358 goto conjure_default;
1362 goto conjure_default;
1364 for (
const auto &[BK,
V] : *
C) {
1365 std::optional<uint64_t> ROffset =
1366 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
1371 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
1373 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
1374 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
1375 B = B.removeBinding(BK);
1378 const MemRegion *
R =
V.getAsRegion();
1379 if (isa_and_nonnull<SymbolicRegion>(R))
1387 baseR, Elem, SF, AT->getElementType(), Count);
1392 DefinedOrUnknownSVal
V =
1398bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
1399 const MemRegion *R) {
1400 switch (GlobalsFilter) {
1403 case GFK_SystemOnly:
1409 llvm_unreachable(
"unknown globals filter");
1412bool InvalidateRegionsWorker::includeEntireMemorySpace(
const MemRegion *Base) {
1413 if (isInitiallyIncludedGlobalRegion(Base))
1416 const MemSpaceRegion *MemSpace =
Base->getRawMemorySpace();
1421RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
1423 const StackFrame *SF, RegionBindingsRef B,
1424 InvalidatedRegions *Invalidated) {
1427 const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
1429 (
const void *)GS, Elem, SF,
1432 B = B.removeBinding(GS)
1433 .addBinding(BindingKey::Make(GS, BindingKey::Default),
V);
1438 Invalidated->push_back(GS);
1443void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
1444 ArrayRef<SVal> Values,
1445 InvalidatedRegions *TopLevelRegions) {
1446 for (SVal
V : Values) {
1447 if (
auto LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
1448 for (SVal S : getInterestingValues(*LCS))
1449 if (
const MemRegion *R = S.getAsRegion())
1455 if (
const MemRegion *R =
V.getAsRegion()) {
1456 if (TopLevelRegions)
1457 TopLevelRegions->push_back(R);
1464StoreRef RegionStoreManager::invalidateRegions(
1467 RegionAndSymbolInvalidationTraits &ITraits,
1468 InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
1469 GlobalsFilterKind GlobalsFilter;
1471 if (
Call->isInSystemHeader())
1472 GlobalsFilter = GFK_SystemOnly;
1474 GlobalsFilter = GFK_All;
1476 GlobalsFilter = GFK_None;
1479 RegionBindingsRef B = getRegionBindings(store);
1480 InvalidateRegionsWorker W(*
this, StateMgr, B, Elem, Count, SF, IS, ITraits,
1481 Invalidated, GlobalsFilter);
1484 W.GenerateClusters();
1487 populateWorkList(W, Values, TopLevelRegions);
1492 B = W.getRegionBindings();
1498 switch (GlobalsFilter) {
1500 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, Elem,
1501 Count, SF, B, Invalidated);
1503 case GFK_SystemOnly:
1504 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, Elem,
1505 Count, SF, B, Invalidated);
1511 return StoreRef(B.asStore(), *
this);
1524SVal RegionStoreManager::ArrayToPointer(Loc
Array, QualType T) {
1529 return UnknownVal();
1531 const SubRegion *
R =
1534 return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
1551 if (L.
getAs<loc::ConcreteInt>()) {
1552 return UnknownVal();
1554 if (!L.
getAs<loc::MemRegionVal>()) {
1555 return UnknownVal();
1561 return UnknownVal();
1566 if (
const auto *TVR = dyn_cast<TypedValueRegion>(MR))
1567 T = TVR->getValueType();
1568 else if (
const auto *TR = dyn_cast<TypedRegion>(MR))
1570 else if (
const auto *SR = dyn_cast<SymbolicRegion>(MR))
1571 T = SR->getPointeeStaticType();
1573 assert(!T.
isNull() &&
"Unable to auto-detect binding type!");
1574 assert(!T->
isVoidType() &&
"Attempting to dereference a void pointer!");
1582 QualType RTy =
R->getValueType();
1587 return UnknownVal();
1598 return getBindingForStruct(B, R);
1602 return createLazyBinding(B, R);
1606 return getBindingForArray(B, R);
1608 return UnknownVal();
1613 return UnknownVal();
1615 if (
const FieldRegion* FR = dyn_cast<FieldRegion>(R))
1616 return svalBuilder.
evalCast(getBindingForField(B, FR), T, QualType{});
1618 if (
const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
1624 return svalBuilder.
evalCast(getBindingForElement(B, ER), T, QualType{});
1627 if (
const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
1634 return svalBuilder.
evalCast(getBindingForObjCIvar(B, IVR), T, QualType{});
1637 if (
const VarRegion *VR = dyn_cast<VarRegion>(R)) {
1644 return svalBuilder.
evalCast(getBindingForVar(B, VR), T, QualType{});
1647 const SVal *
V = B.lookup(R, BindingKey::Direct);
1661 return UndefinedVal();
1671 RegionTy = TVR->getValueType();
1674 RegionTy = SR->getSymbol()->getType();
1686static std::optional<nonloc::LazyCompoundVal>
1688 const SubRegion *R,
bool AllowSubregionBindings) {
1689 std::optional<SVal>
V = B.getDefaultBinding(R);
1691 return std::nullopt;
1693 std::optional<nonloc::LazyCompoundVal> LCV =
1696 return std::nullopt;
1701 if (!RegionTy.
isNull() &&
1703 QualType SourceRegionTy = LCV->getRegion()->getValueType();
1705 return std::nullopt;
1708 if (!AllowSubregionBindings) {
1715 return std::nullopt;
1721std::pair<Store, const SubRegion *>
1724 const SubRegion *originalRegion) {
1725 if (originalRegion != R) {
1726 if (std::optional<nonloc::LazyCompoundVal>
V =
1728 return std::make_pair(
V->getStore(),
V->getRegion());
1731 typedef std::pair<Store, const SubRegion *> StoreRegionPair;
1732 StoreRegionPair
Result = StoreRegionPair();
1734 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
1739 Result.second = MRMgr.getElementRegionWithSuper(ER,
Result.second);
1741 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
1746 Result.second = MRMgr.getFieldRegionWithSuper(FR,
Result.second);
1748 }
else if (
const CXXBaseObjectRegion *BaseReg =
1749 dyn_cast<CXXBaseObjectRegion>(R)) {
1756 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
1768static SmallVector<uint64_t, 2>
1770 assert(CAT &&
"ConstantArrayType should not be null");
1775 }
while ((CAT = dyn_cast<ConstantArrayType>(CAT->
getElementType())));
1793static std::pair<SmallVector<SVal, 2>,
const MemRegion *>
1795 assert(ER &&
"ConstantArrayType should not be null");
1799 SValOffsets.push_back(ER->
getIndex());
1801 ER = dyn_cast<ElementRegion>(
Base);
1803 return {SValOffsets,
Base};
1827static std::optional<SVal>
1848 DstOffsets.resize(SrcOffsets.size());
1849 auto ExtentIt = ArrayExtents.begin();
1850 auto OffsetIt = DstOffsets.begin();
1852 for (
SVal V : llvm::reverse(SrcOffsets)) {
1855 const llvm::APSInt &Offset = CI->getValue();
1856 if (Offset.isNegative() || Offset.uge(*(ExtentIt++)))
1859 *(OffsetIt++) = Offset.getZExtValue();
1867 return std::nullopt;
1870std::optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer(
1872 assert(R &&
"ElementRegion should not be null");
1875 SmallVector<SVal, 2> SValOffsets;
1876 const MemRegion *
Base;
1878 const VarRegion *VR = dyn_cast<VarRegion>(Base);
1880 return std::nullopt;
1882 assert(!SValOffsets.empty() &&
"getElementRegionOffsets guarantees the "
1883 "offsets vector is not empty.");
1887 const VarDecl *VD = VR->
getDecl();
1889 !
R->getElementType().isConstQualified() &&
1891 return std::nullopt;
1906 return std::nullopt;
1912 return std::nullopt;
1923 if (SValOffsets.size() != Extents.size())
1924 return std::nullopt;
1926 SmallVector<uint64_t, 2> ConcreteOffsets;
1928 SValOffsets, Extents, ConcreteOffsets))
1934 if (
const auto *ILE = dyn_cast<InitListExpr>(
Init))
1935 return getSValFromInitListExpr(ILE, ConcreteOffsets,
R->getElementType());
1940 if (
const auto *SL = dyn_cast<StringLiteral>(
Init))
1941 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
1942 R->getElementType());
1946 return std::nullopt;
1966std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
1967 const InitListExpr *ILE,
const SmallVector<uint64_t, 2> &Offsets,
1969 assert(ILE &&
"InitListExpr should not be null");
1971 for (uint64_t Offset : Offsets) {
1978 if (
const auto *SL = dyn_cast<StringLiteral>(ILE->
getInit(0)))
1979 return getSValFromStringLiteral(SL, Offset, ElemT);
1987 const Expr *E = ILE->
getInit(Offset);
1988 const auto *IL = dyn_cast<InitListExpr>(E);
2002 return std::nullopt;
2030SVal RegionStoreManager::getSValFromStringLiteral(
const StringLiteral *SL,
2033 assert(SL &&
"StringLiteral should not be null");
2049 if (
const std::optional<SVal> &ParentValue =
2050 B.getDirectBinding(BaseRegion)) {
2051 if (
SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
2054 if (ParentValue->isUndef())
2063 return std::nullopt;
2067 const ElementRegion* R) {
2069 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2072 const MemRegion* superR =
R->getSuperRegion();
2075 if (
const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
2081 return UnknownVal();
2082 if (
const auto CI =
R->getIndex().getAs<nonloc::ConcreteInt>()) {
2083 const llvm::APSInt &Idx = CI->getValue();
2085 return UndefinedVal();
2086 const StringLiteral *SL = StrR->getStringLiteral();
2087 return getSValFromStringLiteral(SL, Idx.getZExtValue(), T);
2090 if (std::optional<SVal>
V = getConstantValFromConstArrayInitializer(B, R))
2096 return UnknownVal();
2104 const RegionRawOffset &O =
R->getAsArrayOffset();
2108 return UnknownVal();
2110 if (
const TypedValueRegion *baseR = dyn_cast<TypedValueRegion>(O.
getRegion()))
2114 return getBindingForFieldOrElementCommon(B, R,
R->getElementType());
2118 const FieldRegion* R) {
2121 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2125 const FieldDecl *FD =
R->getDecl();
2127 const MemRegion* superR =
R->getSuperRegion();
2128 if (
const auto *VR = dyn_cast<VarRegion>(superR)) {
2129 const VarDecl *VD = VR->
getDecl();
2130 QualType RecordVarTy = VD->
getType();
2138 if (
const auto *InitList = dyn_cast<InitListExpr>(
Init)) {
2139 if (Index < InitList->getNumInits()) {
2140 if (
const Expr *FieldInit = InitList->getInit(Index))
2165 if (
const auto *Base = dyn_cast<TypedValueRegion>(
R->getBaseRegion()))
2169 return getBindingForFieldOrElementCommon(B, R, Ty);
2172std::optional<SVal> RegionStoreManager::getBindingForDerivedDefaultValue(
2174 const TypedValueRegion *R, QualType Ty) {
2176 if (
const std::optional<SVal> &D = B.getDefaultBinding(superR)) {
2192 llvm_unreachable(
"Unknown default value");
2195 return std::nullopt;
2198SVal RegionStoreManager::getLazyBinding(
const SubRegion *LazyBindingRegion,
2199 RegionBindingsRef LazyBinding) {
2201 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
2202 Result = getBindingForElement(LazyBinding, ER);
2204 Result = getBindingForField(LazyBinding,
2229 const TypedValueRegion *R,
2236 Store lazyBindingStore =
nullptr;
2237 const SubRegion *lazyBindingRegion =
nullptr;
2238 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
2239 if (lazyBindingRegion)
2240 return getLazyBinding(lazyBindingRegion,
2241 getRegionBindings(lazyBindingStore));
2245 bool hasSymbolicIndex =
false;
2261 bool hasPartialLazyBinding =
false;
2263 const SubRegion *SR =
R;
2266 if (std::optional<SVal> D =
2267 getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
2268 if (D->getAs<nonloc::LazyCompoundVal>()) {
2269 hasPartialLazyBinding =
true;
2276 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(Base)) {
2277 NonLoc index = ER->getIndex();
2279 hasSymbolicIndex =
true;
2284 SR = dyn_cast<SubRegion>(Base);
2291 if (
const TypedValueRegion *typedSuperR =
2292 dyn_cast<TypedValueRegion>(
R->getSuperRegion())) {
2293 if (typedSuperR->getValueType()->isVectorType())
2294 return UnknownVal();
2302 if (hasSymbolicIndex)
2303 return UnknownVal();
2309 if (
const std::optional<SVal> &
V = B.getDefaultBinding(R))
2311 return UndefinedVal();
2320 const ObjCIvarRegion* R) {
2322 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2325 const MemRegion *superR =
R->getSuperRegion();
2328 if (
const std::optional<SVal> &
V = B.getDefaultBinding(superR)) {
2333 return UnknownVal();
2336 return getBindingForLazySymbol(R);
2340 const VarRegion *R) {
2343 if (std::optional<SVal>
V = B.getDirectBinding(R))
2346 if (std::optional<SVal>
V = B.getDefaultBinding(R))
2350 const VarDecl *VD =
R->getDecl();
2351 const MemSpaceRegion *MS =
R->getRawMemorySpace();
2366 return UnknownVal();
2379 if (B.isMainAnalysis())
2391 if (std::optional<SVal>
V = getBindingForDerivedDefaultValue(B, MS, R, T)) {
2392 assert(!
V->getAs<nonloc::LazyCompoundVal>());
2399 return UndefinedVal();
2402SVal RegionStoreManager::getBindingForLazySymbol(
const TypedValueRegion *R) {
2407const RegionStoreManager::SValListTy &
2408RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
2410 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.
getCVData());
2411 if (I != LazyBindingsMap.end())
2417 const SubRegion *LazyR = LCV.
getRegion();
2418 RegionBindingsRef B = getRegionBindings(LCV.
getStore());
2424 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2426 SmallVector<BindingPair, 32>
Bindings;
2429 for (SVal
V : llvm::make_second_range(
Bindings)) {
2430 if (
V.isUnknownOrUndef() ||
V.isConstant())
2433 if (
auto InnerLCV =
V.getAs<nonloc::LazyCompoundVal>()) {
2434 const SValListTy &InnerList = getInterestingValues(*InnerLCV);
2435 llvm::append_range(List, InnerList);
2441 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2445 const TypedValueRegion *R) {
2446 if (std::optional<nonloc::LazyCompoundVal>
V =
2454 const TypedValueRegion *R) {
2455 const RecordDecl *RD =
2456 R->getValueType()->castAsCanonical<RecordType>()->getDecl();
2458 return UnknownVal();
2464 return createLazyBinding(B, R);
2468 const TypedValueRegion *R) {
2470 "Only constant array types can have compound bindings.");
2472 return createLazyBinding(B, R);
2475bool RegionStoreManager::includedInBindings(
Store store,
2476 const MemRegion *region)
const {
2477 RegionBindingsRef B = getRegionBindings(store);
2481 if (B.lookup(region))
2485 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
2487 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
2489 SVal D = CI.getData();
2491 if (
R->getBaseRegion() == region)
2503StoreRef RegionStoreManager::killBinding(
Store ST, Loc L) {
2504 if (std::optional<loc::MemRegionVal> LV = L.
getAs<loc::MemRegionVal>())
2505 if (
const MemRegion* R = LV->getRegion())
2506 return StoreRef(getRegionBindings(ST)
2509 .getRootWithoutRetain(),
2512 return StoreRef(ST, *
this);
2515LimitedRegionBindingsRef
2517 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bind",
2518 [&L]() {
return locDescr(L); });
2524 auto MemRegVal = L.
getAs<loc::MemRegionVal>();
2528 const MemRegion *
R = MemRegVal->getRegion();
2532 if (
const auto *SymReg = dyn_cast<SymbolicRegion>(R)) {
2533 QualType Ty = SymReg->getPointeeStaticType();
2535 Ty = StateMgr.getContext().CharTy;
2536 R = GetElementZeroRegion(SymReg, Ty);
2540 if (
const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
2543 return bindArray(B, TR,
V);
2545 return bindStruct(B, TR,
V);
2547 return bindVector(B, TR,
V);
2549 return bindAggregate(B, TR,
V);
2553 "'this' pointer is not an l-value and is not assignable");
2560 : BindingKey::Direct;
2561 return NewB.addBinding(BindingKey::Make(R, KeyKind),
V);
2564LimitedRegionBindingsRef
2566 const MemRegion *R, QualType T) {
2602std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallArray(
2604 const ArrayType *AT, nonloc::LazyCompoundVal LCV) {
2608 auto CAT = dyn_cast<ConstantArrayType>(AT);
2612 return std::nullopt;
2616 return std::nullopt;
2620 if (ArrSize > SmallArrayLimit)
2621 return std::nullopt;
2623 LimitedRegionBindingsRef NewB = B;
2625 for (uint64_t i = 0; i < ArrSize; ++i) {
2627 const ElementRegion *SrcER =
2628 MRMgr.getElementRegion(Ty, Idx, LCV.
getRegion(), Ctx);
2629 SVal
V = getBindingForElement(getRegionBindings(LCV.
getStore()), SrcER);
2631 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2632 NewB = bind(NewB, loc::MemRegionVal(DstER),
V);
2638LimitedRegionBindingsRef
2640 const TypedValueRegion *R, SVal
Init) {
2641 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindArray",
2642 [R]() {
return R->getDescriptiveName(); });
2648 std::optional<uint64_t>
Size;
2650 if (
const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
2656 if (std::optional<loc::MemRegionVal> MRV =
Init.getAs<loc::MemRegionVal>()) {
2657 SVal
V = getBinding(B.asStore(), *MRV,
R->getValueType());
2658 return bindAggregate(B, R,
V);
2663 if (
Init.isConstant())
2664 return bindAggregate(B, R,
Init);
2666 if (std::optional LCV =
Init.getAs<nonloc::LazyCompoundVal>()) {
2667 if (std::optional NewB = tryBindSmallArray(B, R, AT, *LCV))
2669 return bindAggregate(B, R,
Init);
2673 return bindAggregate(B, R,
Init);
2676 const nonloc::CompoundVal& CV =
Init.castAs<nonloc::CompoundVal>();
2680 LimitedRegionBindingsRef NewB = B;
2682 for (;
Size ? i < *
Size :
true; ++i, ++VI) {
2690 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2693 NewB = bindStruct(NewB, ER, *VI);
2695 NewB = bindArray(NewB, ER, *VI);
2697 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2703 if (!Size || i < *Size)
2704 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2709LimitedRegionBindingsRef
2711 const TypedValueRegion *R, SVal
V) {
2712 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindVector",
2713 [R]() {
return R->getDescriptiveName(); });
2717 QualType T =
R->getValueType();
2718 const VectorType *VT = T->
castAs<VectorType>();
2722 return bindAggregate(B, R,
V);
2728 return bindAggregate(B, R, UnknownVal());
2732 nonloc::CompoundVal CV =
V.
castAs<nonloc::CompoundVal>();
2735 LimitedRegionBindingsRef NewB = B;
2737 for ( ; index != numElements ; ++index) {
2745 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2748 NewB = bindArray(NewB, ER, *VI);
2750 NewB = bindStruct(NewB, ER, *VI);
2752 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2757std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
2759 const RecordDecl *RD, nonloc::LazyCompoundVal LCV) {
2765 if (
const CXXRecordDecl *
Class = dyn_cast<CXXRecordDecl>(RD))
2766 if (
Class->getNumBases() != 0 ||
Class->getNumVBases() != 0)
2767 return std::nullopt;
2769 for (
const auto *FD : RD->
fields()) {
2775 if (Fields.size() == SmallStructLimit)
2776 return std::nullopt;
2786 return std::nullopt;
2788 Fields.push_back(FD);
2791 LimitedRegionBindingsRef NewB = B;
2793 for (
const FieldDecl *Field : Fields) {
2794 const FieldRegion *SourceFR = MRMgr.getFieldRegion(Field, LCV.
getRegion());
2795 SVal
V = getBindingForField(getRegionBindings(LCV.
getStore()), SourceFR);
2797 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
2798 NewB = bind(NewB, loc::MemRegionVal(DestFR),
V);
2804LimitedRegionBindingsRef
2806 const TypedValueRegion *R, SVal
V) {
2807 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindStruct",
2808 [R]() {
return R->getDescriptiveName(); });
2812 QualType T =
R->getValueType();
2820 if (std::optional<nonloc::LazyCompoundVal> LCV =
2821 V.getAs<nonloc::LazyCompoundVal>()) {
2822 if (std::optional NewB = tryBindSmallStruct(B, R, RD, *LCV))
2824 return bindAggregate(B, R,
V);
2827 return bindAggregate(B, R,
V);
2833 return bindAggregate(B, R, UnknownVal());
2851 const nonloc::CompoundVal& CV =
V.
castAs<nonloc::CompoundVal>();
2854 LimitedRegionBindingsRef NewB = B;
2858 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
2866 assert((CRD->isAggregate() || (Ctx.
getLangOpts().ObjC && VI == VE)) &&
2867 "Non-aggregates are constructed with a constructor!");
2869 for (
const auto &B : CRD->bases()) {
2871 assert(!B.isVirtual() &&
"Aggregates cannot have virtual base classes!");
2878 QualType BTy = B.getType();
2882 assert(BRD &&
"Base classes must be C++ classes!");
2884 const CXXBaseObjectRegion *BR =
2885 MRMgr.getCXXBaseObjectRegion(BRD, R,
false);
2887 NewB = bindStruct(NewB, BR, *VI);
2904 if (FI->isUnnamedBitField())
2907 QualType FTy = FI->getType();
2908 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2911 NewB = bindArray(NewB, FR, *VI);
2913 NewB = bindStruct(NewB, FR, *VI);
2915 NewB = bind(NewB, loc::MemRegionVal(FR), *VI);
2924 NewB = NewB.
addBinding(R, BindingKey::Default,
2931LimitedRegionBindingsRef
2933 const TypedRegion *R, SVal Val) {
2934 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindAggregate",
2935 [R]() {
return R->getDescriptiveName(); });
2941 return removeSubRegionBindings(B, R).
addBinding(R, BindingKey::Default, Val);
2949class RemoveDeadBindingsWorker
2950 :
public ClusterAnalysis<RemoveDeadBindingsWorker> {
2951 SmallVector<const SymbolicRegion *, 12> Postponed;
2952 SymbolReaper &SymReaper;
2953 const StackFrame *CurrentSF;
2956 RemoveDeadBindingsWorker(RegionStoreManager &rm,
2957 ProgramStateManager &stateMgr, RegionBindingsRef
b,
2958 SymbolReaper &symReaper,
const StackFrame *SF)
2959 : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr,
b),
2960 SymReaper(symReaper), CurrentSF(SF) {}
2963 void VisitAddedToCluster(
const MemRegion *baseR,
const ClusterBindings &
C);
2965 using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
2967 using ClusterAnalysis::AddToWorkList;
2969 bool AddToWorkList(
const MemRegion *R);
2971 bool UpdatePostponed();
2972 void VisitBinding(SVal
V);
2976bool RemoveDeadBindingsWorker::AddToWorkList(
const MemRegion *R) {
2977 const MemRegion *BaseR =
R->getBaseRegion();
2978 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
2981void RemoveDeadBindingsWorker::VisitAddedToCluster(
const MemRegion *baseR,
2984 if (
const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
2985 if (SymReaper.
isLive(VR))
2986 AddToWorkList(baseR, &
C);
2991 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
2992 if (SymReaper.
isLive(SR->getSymbol()))
2993 AddToWorkList(SR, &
C);
2995 Postponed.push_back(SR);
3001 AddToWorkList(baseR, &
C);
3006 if (
const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
3007 const auto *StackReg =
3009 const StackFrame *RegSF = StackReg->getStackFrame();
3010 if (CurrentSF && (RegSF == CurrentSF || RegSF->
isParentOf(CurrentSF)))
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 StackFrame *SF,
3084 SymbolReaper &SymReaper) {
3085 RegionBindingsRef B = getRegionBindings(store);
3086 RemoveDeadBindingsWorker W(*
this, StateMgr, B, SymReaper, SF);
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)
Result
Implement __builtin_bit_cast and related operations.
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
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
bool isParentOf(const StackFrame *SF) const
const Decl * getDecl() 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.
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
QualType getCanonicalTypeInternal() const
bool isStructureOrClassType() const
bool isVectorType() const
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.
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.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
@ 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.
NonLoc makeZeroArrayIndex()
DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region)
Make a unique symbol for value of region.
NonLoc makeLazyCompoundVal(const StoreRef &store, const TypedValueRegion *region)
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const StackFrame *SF, unsigned count)
Create a new symbol with a unique 'name'.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
bool 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)
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...