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"
48 enum { Symbolic = 0x2 };
50 llvm::PointerIntPair<const MemRegion *, 2>
P;
57 assert(r &&
Base &&
"Must have known regions.");
58 assert(getConcreteOffsetRegion() ==
Base &&
"Failed to store base region");
62 explicit BindingKey(
const MemRegion *r, uint64_t offset, Kind k)
63 :
P(r, k),
Data(offset) {
64 assert(r &&
"Must have known regions.");
65 assert(getOffset() == offset &&
"Failed to store offset");
67 isa<ObjCIvarRegion, CXXDerivedObjectRegion>(r)) &&
72 bool isDirect()
const {
return P.getInt() &
Direct; }
73 bool isDefault()
const {
return !isDirect(); }
74 bool hasSymbolicOffset()
const {
return P.getInt() & Symbolic; }
78 assert(!hasSymbolicOffset());
82 const SubRegion *getConcreteOffsetRegion()
const {
83 assert(hasSymbolicOffset());
88 if (hasSymbolicOffset())
93 void Profile(llvm::FoldingSetNodeID& ID)
const {
94 ID.AddPointer(
P.getOpaqueValue());
101 if (
P.getOpaqueValue() <
X.P.getOpaqueValue())
103 if (
P.getOpaqueValue() >
X.P.getOpaqueValue())
105 return Data <
X.Data;
109 return P.getOpaqueValue() ==
X.P.getOpaqueValue() &&
113 LLVM_DUMP_METHOD
void dump()
const;
116std::string locDescr(
Loc L) {
118 llvm::raw_string_ostream OS(S);
124BindingKey BindingKey::Make(
const MemRegion *R, Kind k) {
127 return BindingKey(cast<SubRegion>(R), cast<SubRegion>(RO.
getRegion()), k);
133static inline raw_ostream &
operator<<(raw_ostream &Out, BindingKey K) {
134 Out <<
"\"kind\": \"" << (K.isDirect() ?
"Direct" :
"Default")
135 <<
"\", \"offset\": ";
137 if (!K.hasSymbolicOffset())
138 Out << K.getOffset();
147#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
148void BindingKey::dump()
const { llvm::errs() << *
this; }
159typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
163class RegionBindingsRef :
public llvm::ImmutableMapRef<const MemRegion *,
165 ClusterBindings::Factory *CBFactory;
179 typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
182 RegionBindingsRef(ClusterBindings::Factory &CBFactory,
183 const RegionBindings::TreeTy *
T,
184 RegionBindings::TreeTy::Factory *F,
bool IsMainAnalysis)
185 : RegionBindingsRef(ParentTy(
T, F), CBFactory, IsMainAnalysis) {}
187 RegionBindingsRef(
const ParentTy &
P, ClusterBindings::Factory &CBFactory,
189 : ParentTy(
P), CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
191 RegionBindingsRef removeCluster(
const MemRegion *BaseRegion)
const {
192 return RegionBindingsRef(ParentTy::remove(BaseRegion), *CBFactory,
196 RegionBindingsRef addBinding(BindingKey K,
SVal V)
const;
198 RegionBindingsRef addBinding(
const MemRegion *R,
199 BindingKey::Kind k,
SVal V)
const;
201 const SVal *lookup(BindingKey K)
const;
202 const SVal *lookup(
const MemRegion *R, BindingKey::Kind k)
const;
205 RegionBindingsRef removeBinding(BindingKey K);
207 RegionBindingsRef removeBinding(
const MemRegion *R,
210 RegionBindingsRef removeBinding(
const MemRegion *R) {
211 return removeBinding(R, BindingKey::Direct).
212 removeBinding(R, BindingKey::Default);
215 std::optional<SVal> getDirectBinding(
const MemRegion *R)
const;
219 std::optional<SVal> getDefaultBinding(
const MemRegion *R)
const;
222 Store asStore()
const {
223 llvm::PointerIntPair<Store, 1, bool> Ptr = {
224 asImmutableMap().getRootWithoutRetain(), IsMainAnalysis};
225 return reinterpret_cast<Store>(Ptr.getOpaqueValue());
228 bool isMainAnalysis()
const {
229 return IsMainAnalysis;
232 void printJson(raw_ostream &Out,
const char *NL =
"\n",
233 unsigned int Space = 0,
bool IsDot =
false)
const {
234 using namespace llvm;
235 DenseMap<const MemRegion *, std::string> StringifyCache;
236 auto ToString = [&StringifyCache](
const MemRegion *R) {
237 auto [Place, Inserted] = StringifyCache.try_emplace(R);
239 return Place->second;
241 raw_string_ostream OS(Res);
248 std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;
249 using Binding = std::pair<BindingKey, SVal>;
251 const auto MemSpaceBeforeRegionName = [&ToString](
const Cluster *L,
253 if (isa<MemSpaceRegion>(L->first) && !isa<MemSpaceRegion>(R->first))
255 if (!isa<MemSpaceRegion>(L->first) && isa<MemSpaceRegion>(R->first))
257 return ToString(L->first) < ToString(R->first);
260 const auto SymbolicBeforeOffset = [&ToString](
const BindingKey &L,
261 const BindingKey &R) {
262 if (L.hasSymbolicOffset() && !R.hasSymbolicOffset())
264 if (!L.hasSymbolicOffset() && R.hasSymbolicOffset())
266 if (L.hasSymbolicOffset() && R.hasSymbolicOffset())
267 return ToString(L.getRegion()) < ToString(R.getRegion());
268 return L.getOffset() < R.getOffset();
271 const auto DefaultBindingBeforeDirectBindings =
272 [&SymbolicBeforeOffset](
const Binding *LPtr,
const Binding *RPtr) {
273 const BindingKey &L = LPtr->first;
274 const BindingKey &R = RPtr->first;
275 if (L.isDefault() && !R.isDefault())
277 if (!L.isDefault() && R.isDefault())
279 assert(L.isDefault() == R.isDefault());
280 return SymbolicBeforeOffset(L, R);
283 const auto AddrOf = [](
const auto &Item) {
return &Item; };
285 std::vector<const Cluster *> SortedClusters;
286 SortedClusters.reserve(std::distance(begin(), end()));
287 append_range(SortedClusters, map_range(*
this, AddrOf));
288 llvm::sort(SortedClusters, MemSpaceBeforeRegionName);
290 for (
auto [Idx,
C] : llvm::enumerate(SortedClusters)) {
292 Indent(Out, Space, IsDot)
293 <<
"{ \"cluster\": \"" << BaseRegion <<
"\", \"pointer\": \""
294 << (
const void *)BaseRegion <<
"\", \"items\": [" << NL;
296 std::vector<const Binding *> SortedBindings;
298 append_range(SortedBindings, map_range(
Bindings, AddrOf));
299 llvm::sort(SortedBindings, DefaultBindingBeforeDirectBindings);
302 for (
auto [Idx, B] : llvm::enumerate(SortedBindings)) {
303 const auto &[Key,
Value] = *B;
304 Indent(Out, Space, IsDot) <<
"{ " << Key <<
", \"value\": ";
305 Value.printJson(Out,
true);
307 if (Idx != SortedBindings.size() - 1)
312 Indent(Out, Space, IsDot) <<
"]}";
313 if (Idx != SortedClusters.size() - 1)
319 LLVM_DUMP_METHOD
void dump()
const { printJson(llvm::errs()); }
323 commitBindingsToCluster(
const MemRegion *BaseRegion,
334 std::optional<unsigned> BindingsLeft)
335 : RegionBindingsRef(
Base),
336 EscapedValuesDuringBind(&EscapedValuesDuringBind),
337 BindingsLeft(BindingsLeft) {}
340 return BindingsLeft.has_value() && BindingsLeft.value() == 0;
344 EscapedValuesDuringBind->push_back(
V);
358 data_type_ref BindingKeyAndValue)
const {
360 BaseRegion, BindingKeyAndValue),
361 *EscapedValuesDuringBind, BindingsLeft};
366 RegionBindingsRef::removeCluster(BaseRegion), *EscapedValuesDuringBind,
371 std::optional<unsigned> NewBindingsLeft = BindingsLeft;
372 if (NewBindingsLeft.has_value()) {
373 assert(NewBindingsLeft.value() != 0);
374 NewBindingsLeft.value() -= 1;
378 if (NewBindingsLeft.value() == 0) {
380 K = BindingKey::Make(K.getRegion(), BindingKey::Default);
386 *EscapedValuesDuringBind, NewBindingsLeft};
396 std::optional<unsigned> BindingsLeft;
403RegionBindingsRef::getDirectBinding(
const MemRegion *R)
const {
404 const SVal *
V = lookup(R, BindingKey::Direct);
405 return V ? std::optional<SVal>(*
V) : std::nullopt;
409RegionBindingsRef::getDefaultBinding(
const MemRegion *R)
const {
410 const SVal *
V = lookup(R, BindingKey::Default);
411 return V ? std::optional<SVal>(*
V) :
std::nullopt;
414RegionBindingsRef RegionBindingsRef::commitBindingsToCluster(
416 return RegionBindingsRef(ParentTy::add(BaseRegion,
Bindings), *CBFactory,
420RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K,
SVal V)
const {
425 (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
430RegionBindingsRef RegionBindingsRef::addBinding(
const MemRegion *R,
433 return addBinding(BindingKey::Make(R, k),
V);
436const SVal *RegionBindingsRef::lookup(BindingKey K)
const {
440 return Cluster->lookup(K);
444 BindingKey::Kind k)
const {
445 return lookup(BindingKey::Make(R, k));
448RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
455 if (NewCluster.isEmpty())
456 return removeCluster(
Base);
457 return commitBindingsToCluster(
Base, NewCluster);
460RegionBindingsRef RegionBindingsRef::removeBinding(
const MemRegion *R,
462 return removeBinding(BindingKey::Make(R, k));
470class InvalidateRegionsWorker;
474 RegionBindings::Factory RBFactory;
475 mutable ClusterBindings::Factory CBFactory;
477 typedef std::vector<SVal> SValListTy;
480 SValListTy> LazyBindingsMapTy;
481 LazyBindingsMapTy LazyBindingsMap;
491 const unsigned SmallStructLimit;
501 const unsigned SmallArrayLimit;
507 const std::optional<unsigned> RegionStoreMaxBindingFanOutPlusOne;
511 void populateWorkList(InvalidateRegionsWorker &W,
513 InvalidatedRegions *TopLevelRegions);
516 return StateMgr.getOwningEngine().getAnalysisManager().options;
522 CBFactory(mgr.getAllocator()),
523 SmallStructLimit(getOptions().RegionStoreSmallStructLimit),
524 SmallArrayLimit(getOptions().RegionStoreSmallArrayLimit),
525 RegionStoreMaxBindingFanOutPlusOne([&]() ->
std::optional<
unsigned> {
526 unsigned FanOut = getOptions().RegionStoreMaxBindingFanOut;
527 assert(FanOut != std::numeric_limits<unsigned>::max());
551 bool IsMainAnalysis =
false;
552 if (
const auto *FD = dyn_cast<FunctionDecl>(InitLoc->
getDecl()))
553 IsMainAnalysis = FD->isMain() && !Ctx.
getLangOpts().CPlusPlus;
554 return StoreRef(RegionBindingsRef(RegionBindingsRef::ParentTy(
555 RBFactory.getEmptyMap(), RBFactory),
556 CBFactory, IsMainAnalysis)
567 RegionBindingsRef B, InvalidatedRegions *Invalidated);
574 InvalidatedRegions *Invalidated,
575 InvalidatedRegions *InvalidatedTopLevel)
override;
596 getRegionBindings(store, EscapedValuesDuringBind);
598 std::move(EscapedValuesDuringBind)};
608 RegionBindingsRef B = getRegionBindings(store);
611 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
612 "Double initialization!");
613 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
615 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this), {}};
630 if (
const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
631 if (BR->getDecl()->isEmpty())
636 getRegionBindings(store, EscapedValuesDuringBind);
638 B = removeSubRegionBindings(B, cast<SubRegion>(R));
639 B = B.
addBinding(BindingKey::Make(R, BindingKey::Default),
V);
641 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this),
642 std::move(EscapedValuesDuringBind)};
655 std::optional<LimitedRegionBindingsRef>
667 std::optional<LimitedRegionBindingsRef>
685 getRegionBindings(store).manualRetain();
692 getRegionBindings(store).manualRelease();
720 RegionBindingsRef B = getRegionBindings(S);
744 RegionBindingsRef LazyBinding);
769 std::pair<Store, const SubRegion *>
798 RegionBindingsRef getRegionBindings(
Store store)
const {
799 llvm::PointerIntPair<Store, 1, bool> Ptr;
800 Ptr.setFromOpaqueValue(
const_cast<void *
>(store));
802 static_cast<const RegionBindings::TreeTy *
>(Ptr.getPointer()),
803 RBFactory.getTreeFactory(), Ptr.getInt()};
807 getRegionBindings(
Store store,
810 getRegionBindings(store), EscapedValuesDuringBind,
811 RegionStoreMaxBindingFanOutPlusOne);
815 unsigned int Space = 0,
bool IsDot =
false)
const override;
818 RegionBindingsRef B = getRegionBindings(store);
819 for (
const auto &[Region, Cluster] : B) {
820 for (
const auto &[Key,
Value] : Cluster) {
823 if (
const SubRegion *R = dyn_cast<SubRegion>(Key.getRegion())) {
825 if (!f.HandleBinding(*
this, store, R,
Value))
839std::unique_ptr<StoreManager>
841 return std::make_unique<RegionStoreManager>(StMgr);
851enum GlobalsFilterKind {
860template <
typename DERIVED>
861class ClusterAnalysis {
863 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
864 typedef const MemRegion * WorkListElement;
871 RegionStoreManager &RM;
893 : RM(rm), Ctx(StateMgr.getContext()),
894 svalBuilder(StateMgr.getSValBuilder()), B(
std::move(
b)) {}
896 RegionBindingsRef getRegionBindings()
const {
return B; }
899 return Visited.count(getCluster(R));
902 void GenerateClusters() {
904 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
909 assert(!Cluster.isEmpty() &&
"Empty clusters should be removed");
910 static_cast<DERIVED*
>(
this)->VisitAddedToCluster(
Base, Cluster);
914 if (
static_cast<DERIVED*
>(
this)->includeEntireMemorySpace(
Base))
915 AddToWorkList(WorkListElement(
Base), &Cluster);
927 return static_cast<DERIVED*
>(
this)->AddToWorkList(R);
931 while (!WL.empty()) {
932 WorkListElement
E = WL.pop_back_val();
935 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR, getCluster(BaseR));
944 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR,
C);
953bool RegionStoreManager::scanReachableSymbols(
Store S,
const MemRegion *R,
955 assert(R == R->
getBaseRegion() &&
"Should only be called for base regions");
956 RegionBindingsRef B = getRegionBindings(S);
962 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
964 if (!Callbacks.
scan(RI.getData()))
978 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
984 if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R))
986 Fields.push_back(FR->getDecl());
988 R = cast<SubRegion>(R)->getSuperRegion();
993 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
1001 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
1003 return std::equal(FieldsInBindingKey.begin() + Delta,
1004 FieldsInBindingKey.end(),
1007 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
1008 Fields.begin() - Delta);
1023 const SubRegion *Top, BindingKey TopKey,
1024 bool IncludeAllDefaultBindings) {
1026 if (TopKey.hasSymbolicOffset()) {
1028 Top = TopKey.getConcreteOffsetRegion();
1029 TopKey = BindingKey::Make(Top, BindingKey::Default);
1033 uint64_t Length = UINT64_MAX;
1035 if (std::optional<nonloc::ConcreteInt> ExtentCI =
1037 const llvm::APSInt &ExtentInt = ExtentCI->getValue();
1038 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
1041 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
1042 if (FR->getDecl()->isBitField())
1043 Length = FR->getDecl()->getBitWidthValue();
1046 for (
const auto &StoreEntry : Cluster) {
1047 BindingKey NextKey = StoreEntry.first;
1048 if (NextKey.getRegion() == TopKey.getRegion()) {
1054 if (NextKey.getOffset() > TopKey.getOffset() &&
1055 NextKey.getOffset() - TopKey.getOffset() < Length) {
1060 }
else if (NextKey.getOffset() == TopKey.getOffset()) {
1067 if (IncludeAllDefaultBindings || NextKey.isDirect())
1071 }
else if (NextKey.hasSymbolicOffset()) {
1077 if (IncludeAllDefaultBindings || NextKey.isDirect())
1080 }
else if (
const SubRegion *BaseSR = dyn_cast<SubRegion>(
Base)) {
1083 if (BaseSR->isSubRegionOf(Top))
1094 const SubRegion *Top,
bool IncludeAllDefaultBindings) {
1096 BindingKey::Make(Top, BindingKey::Default),
1097 IncludeAllDefaultBindings);
1103 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
1106 if (Top == ClusterHead) {
1115 if (TopKey.hasSymbolicOffset()) {
1116 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1127 for (BindingKey Key : llvm::make_first_range(
Bindings))
1128 Result = Result.remove(Key);
1134 if (TopKey.hasSymbolicOffset()) {
1135 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1136 Result = Result.
add(BindingKey::Make(Concrete, BindingKey::Default),
1140 if (Result.isEmpty())
1146class InvalidateRegionsWorker :
public ClusterAnalysis<InvalidateRegionsWorker>
1154 GlobalsFilterKind GlobalsFilter;
1162 GlobalsFilterKind GFK)
1163 : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr,
b), Elem(elem),
1164 Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
1165 GlobalsFilter(GFK) {}
1168 void VisitBinding(
SVal V);
1170 using ClusterAnalysis::AddToWorkList;
1180 bool isInitiallyIncludedGlobalRegion(
const MemRegion *R);
1184bool InvalidateRegionsWorker::AddToWorkList(
const MemRegion *R) {
1185 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1188 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
1191void InvalidateRegionsWorker::VisitBinding(
SVal V) {
1202 if (std::optional<nonloc::LazyCompoundVal> LCS =
1207 for (
SVal V : RM.getInterestingValues(*LCS))
1208 if (!isa<nonloc::LazyCompoundVal>(
V))
1215void InvalidateRegionsWorker::VisitCluster(
const MemRegion *baseR,
1218 bool PreserveRegionsContents =
1219 ITraits.hasTrait(baseR,
1223 for (
SVal Val : llvm::make_second_range(*
C))
1227 if (!PreserveRegionsContents)
1231 if (
const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
1232 if (
const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
1237 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
1238 using namespace ast_matchers;
1240 const char *DeclBind =
"DeclBind";
1242 to(
varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
1244 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
1245 RD->getASTContext());
1250 RM.getRegionManager().getVarRegion(VD, LCtx);
1251 AddToWorkList(ToInvalidate);
1260 for (
auto Var : BR->referenced_vars()) {
1261 const VarRegion *VR = Var.getCapturedRegion();
1273 if (std::optional<Loc> L =
V.getAs<
Loc>()) {
1284 IS.insert(SR->getSymbol());
1287 if (PreserveRegionsContents)
1292 Regions->push_back(baseR);
1294 if (isa<AllocaRegion, SymbolicRegion>(baseR)) {
1309 if (isInitiallyIncludedGlobalRegion(baseR)) {
1326 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1330 if (doNotInvalidateSuperRegion) {
1333 std::optional<uint64_t> NumElements;
1337 NumElements = CAT->getZExtSize();
1339 goto conjure_default;
1340 QualType ElementTy = AT->getElementType();
1348 AddToWorkList(SuperR);
1349 goto conjure_default;
1353 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
1354 bool UpperOverflow = UpperOffset < LowerOffset;
1359 goto conjure_default;
1363 goto conjure_default;
1365 for (
const auto &[BK,
V] : *
C) {
1366 std::optional<uint64_t> ROffset =
1367 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
1372 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
1374 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
1375 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
1376 B = B.removeBinding(BK);
1380 if (isa_and_nonnull<SymbolicRegion>(R))
1388 baseR, Elem, LCtx, AT->getElementType(), Count);
1399bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
1401 switch (GlobalsFilter) {
1404 case GFK_SystemOnly:
1410 llvm_unreachable(
"unknown globals filter");
1413bool InvalidateRegionsWorker::includeEntireMemorySpace(
const MemRegion *
Base) {
1414 if (isInitiallyIncludedGlobalRegion(
Base))
1418 return ITraits.hasTrait(MemSpace,
1422RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
1425 InvalidatedRegions *Invalidated) {
1430 (
const void *)GS, Elem, LCtx,
1433 B = B.removeBinding(GS)
1434 .addBinding(BindingKey::Make(GS, BindingKey::Default),
V);
1439 Invalidated->push_back(GS);
1444void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
1446 InvalidatedRegions *TopLevelRegions) {
1447 for (
SVal V : Values) {
1449 for (
SVal S : getInterestingValues(*LCS))
1450 if (
const MemRegion *R = S.getAsRegion())
1457 if (TopLevelRegions)
1458 TopLevelRegions->push_back(R);
1465StoreRef RegionStoreManager::invalidateRegions(
1469 InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
1470 GlobalsFilterKind GlobalsFilter;
1472 if (
Call->isInSystemHeader())
1473 GlobalsFilter = GFK_SystemOnly;
1475 GlobalsFilter = GFK_All;
1477 GlobalsFilter = GFK_None;
1480 RegionBindingsRef B = getRegionBindings(store);
1481 InvalidateRegionsWorker W(*
this, StateMgr, B, Elem, Count, LCtx, IS, ITraits,
1482 Invalidated, GlobalsFilter);
1485 W.GenerateClusters();
1488 populateWorkList(W, Values, TopLevelRegions);
1493 B = W.getRegionBindings();
1499 switch (GlobalsFilter) {
1501 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, Elem,
1502 Count, LCtx, B, Invalidated);
1504 case GFK_SystemOnly:
1505 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, Elem,
1506 Count, LCtx, B, Invalidated);
1512 return StoreRef(B.asStore(), *
this);
1526 if (isa<loc::ConcreteInt>(Array))
1529 if (!isa<loc::MemRegionVal>(Array))
1543 assert(!isa<UnknownVal>(L) &&
"location unknown");
1544 assert(!isa<UndefinedVal>(L) &&
"location undefined");
1561 if (isa<BlockDataRegion>(MR)) {
1567 if (
const auto *TVR = dyn_cast<TypedValueRegion>(MR))
1568 T = TVR->getValueType();
1569 else if (
const auto *TR = dyn_cast<TypedRegion>(MR))
1571 else if (
const auto *SR = dyn_cast<SymbolicRegion>(MR))
1572 T = SR->getPointeeStaticType();
1574 assert(!
T.isNull() &&
"Unable to auto-detect binding type!");
1575 assert(!
T->
isVoidType() &&
"Attempting to dereference a void pointer!");
1577 if (!isa<TypedValueRegion>(MR))
1578 MR = GetElementZeroRegion(cast<SubRegion>(MR),
T);
1599 return getBindingForStruct(B, R);
1603 return createLazyBinding(B, R);
1607 return getBindingForArray(B, R);
1616 if (
const FieldRegion* FR = dyn_cast<FieldRegion>(R))
1638 if (
const VarRegion *VR = dyn_cast<VarRegion>(R)) {
1648 const SVal *
V = B.lookup(R, BindingKey::Direct);
1672 RegionTy = TVR->getValueType();
1675 RegionTy = SR->getSymbol()->getType();
1687static std::optional<nonloc::LazyCompoundVal>
1689 const SubRegion *R,
bool AllowSubregionBindings) {
1690 std::optional<SVal>
V = B.getDefaultBinding(R);
1692 return std::nullopt;
1694 std::optional<nonloc::LazyCompoundVal> LCV =
1697 return std::nullopt;
1702 if (!RegionTy.
isNull() &&
1704 QualType SourceRegionTy = LCV->getRegion()->getValueType();
1706 return std::nullopt;
1709 if (!AllowSubregionBindings) {
1716 return std::nullopt;
1722std::pair<Store, const SubRegion *>
1726 if (originalRegion != R) {
1727 if (std::optional<nonloc::LazyCompoundVal>
V =
1729 return std::make_pair(
V->getStore(),
V->getRegion());
1732 typedef std::pair<Store, const SubRegion *> StoreRegionPair;
1733 StoreRegionPair Result = StoreRegionPair();
1736 Result = findLazyBinding(B, cast<SubRegion>(ER->getSuperRegion()),
1740 Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);
1742 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
1743 Result = findLazyBinding(B, cast<SubRegion>(FR->getSuperRegion()),
1747 Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);
1750 dyn_cast<CXXBaseObjectRegion>(R)) {
1753 Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
1757 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
1771 assert(CAT &&
"ConstantArrayType should not be null");
1776 }
while ((CAT = dyn_cast<ConstantArrayType>(CAT->
getElementType())));
1794static std::pair<SmallVector<SVal, 2>,
const MemRegion *>
1796 assert(ER &&
"ConstantArrayType should not be null");
1800 SValOffsets.push_back(ER->
getIndex());
1802 ER = dyn_cast<ElementRegion>(
Base);
1804 return {SValOffsets,
Base};
1828static std::optional<SVal>
1849 DstOffsets.resize(SrcOffsets.size());
1850 auto ExtentIt = ArrayExtents.begin();
1851 auto OffsetIt = DstOffsets.begin();
1853 for (
SVal V : llvm::reverse(SrcOffsets)) {
1856 const llvm::APSInt &Offset = CI->getValue();
1857 if (Offset.isNegative() || Offset.uge(*(ExtentIt++)))
1860 *(OffsetIt++) = Offset.getZExtValue();
1868 return std::nullopt;
1871std::optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer(
1873 assert(R &&
"ElementRegion should not be null");
1881 return std::nullopt;
1883 assert(!SValOffsets.empty() &&
"getElementRegionOffsets guarantees the "
1884 "offsets vector is not empty.");
1892 return std::nullopt;
1907 return std::nullopt;
1913 return std::nullopt;
1924 if (SValOffsets.size() != Extents.size())
1925 return std::nullopt;
1929 SValOffsets, Extents, ConcreteOffsets))
1935 if (
const auto *ILE = dyn_cast<InitListExpr>(
Init))
1936 return getSValFromInitListExpr(ILE, ConcreteOffsets, R->
getElementType());
1941 if (
const auto *SL = dyn_cast<StringLiteral>(
Init))
1942 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
1947 return std::nullopt;
1967std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
1970 assert(ILE &&
"InitListExpr should not be null");
1972 for (uint64_t Offset : Offsets) {
1979 if (
const auto *SL = dyn_cast<StringLiteral>(ILE->
getInit(0)))
1980 return getSValFromStringLiteral(SL, Offset, ElemT);
1989 const auto *IL = dyn_cast<InitListExpr>(
E);
2003 return std::nullopt;
2034 assert(SL &&
"StringLiteral should not be null");
2050 if (
const std::optional<SVal> &ParentValue =
2051 B.getDirectBinding(BaseRegion)) {
2052 if (
SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
2055 if (ParentValue->isUndef())
2064 return std::nullopt;
2070 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2076 if (
const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
2084 const llvm::APSInt &Idx = CI->getValue();
2088 return getSValFromStringLiteral(SL, Idx.getZExtValue(),
T);
2090 }
else if (isa<ElementRegion, VarRegion>(superR)) {
2091 if (std::optional<SVal>
V = getConstantValFromConstArrayInitializer(B, R))
2096 if (isa<CodeTextRegion>(superR))
2115 return getBindingForFieldOrElementCommon(B, R, R->
getElementType());
2122 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2129 if (
const auto *VR = dyn_cast<VarRegion>(superR)) {
2139 if (
const auto *InitList = dyn_cast<InitListExpr>(
Init)) {
2140 if (Index < InitList->getNumInits()) {
2141 if (
const Expr *FieldInit = InitList->getInit(Index))
2170 return getBindingForFieldOrElementCommon(B, R, Ty);
2173std::optional<SVal> RegionStoreManager::getBindingForDerivedDefaultValue(
2177 if (
const std::optional<SVal> &
D = B.getDefaultBinding(superR)) {
2190 if (isa<nonloc::LazyCompoundVal, nonloc::CompoundVal>(val))
2193 llvm_unreachable(
"Unknown default value");
2196 return std::nullopt;
2199SVal RegionStoreManager::getLazyBinding(
const SubRegion *LazyBindingRegion,
2200 RegionBindingsRef LazyBinding) {
2202 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
2203 Result = getBindingForElement(LazyBinding, ER);
2205 Result = getBindingForField(LazyBinding,
2206 cast<FieldRegion>(LazyBindingRegion));
2222 if (Result.isUndef())
2237 Store lazyBindingStore =
nullptr;
2238 const SubRegion *lazyBindingRegion =
nullptr;
2239 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
2240 if (lazyBindingRegion)
2241 return getLazyBinding(lazyBindingRegion,
2242 getRegionBindings(lazyBindingStore));
2246 bool hasSymbolicIndex =
false;
2262 bool hasPartialLazyBinding =
false;
2267 if (std::optional<SVal>
D =
2268 getBindingForDerivedDefaultValue(B,
Base, R, Ty)) {
2270 hasPartialLazyBinding =
true;
2278 NonLoc index = ER->getIndex();
2280 hasSymbolicIndex =
true;
2285 SR = dyn_cast<SubRegion>(
Base);
2289 if (isa<ElementRegion>(R)) {
2294 if (typedSuperR->getValueType()->isVectorType())
2303 if (hasSymbolicIndex)
2309 if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->
getBaseRegion())) {
2310 if (
const std::optional<SVal> &
V = B.getDefaultBinding(R))
2323 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2329 if (
const std::optional<SVal> &
V = B.getDefaultBinding(superR)) {
2337 return getBindingForLazySymbol(R);
2344 if (std::optional<SVal>
V = B.getDirectBinding(R))
2347 if (std::optional<SVal>
V = B.getDefaultBinding(R))
2355 if (isa<StackArgumentsSpaceRegion>(MS))
2373 if (isa<UnknownSpaceRegion>(MS))
2376 if (isa<GlobalsSpaceRegion>(MS)) {
2380 if (B.isMainAnalysis())
2389 if (isa<StaticGlobalSpaceRegion>(MS))
2392 if (std::optional<SVal>
V = getBindingForDerivedDefaultValue(B, MS, R,
T)) {
2408const RegionStoreManager::SValListTy &
2411 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.
getCVData());
2412 if (I != LazyBindingsMap.end())
2419 RegionBindingsRef B = getRegionBindings(LCV.
getStore());
2425 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2431 if (
V.isUnknownOrUndef() ||
V.isConstant())
2435 const SValListTy &InnerList = getInterestingValues(*InnerLCV);
2436 llvm::append_range(List, InnerList);
2442 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2447 if (std::optional<nonloc::LazyCompoundVal>
V =
2468 if (std::optional<SVal> Val = getUniqueDefaultBinding(B, R))
2470 return createLazyBinding(B, R);
2476 "Only constant array types can have compound bindings.");
2478 return createLazyBinding(B, R);
2481bool RegionStoreManager::includedInBindings(
Store store,
2483 RegionBindingsRef B = getRegionBindings(store);
2487 if (B.lookup(region))
2491 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
2493 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
2495 SVal D = CI.getData();
2511 if (
const MemRegion* R = LV->getRegion())
2512 return StoreRef(getRegionBindings(ST)
2515 .getRootWithoutRetain(),
2523 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bind",
2524 [&L]() {
return locDescr(L); });
2534 const MemRegion *R = MemRegVal->getRegion();
2538 if (
const auto *SymReg = dyn_cast<SymbolicRegion>(R)) {
2539 QualType Ty = SymReg->getPointeeStaticType();
2541 Ty = StateMgr.getContext().CharTy;
2542 R = GetElementZeroRegion(SymReg, Ty);
2549 return bindArray(B, TR,
V);
2551 return bindStruct(B, TR,
V);
2553 return bindVector(B, TR,
V);
2555 return bindAggregate(B, TR,
V);
2558 assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
2559 "'this' pointer is not an l-value and is not assignable");
2562 auto NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
2565 auto KeyKind = isa<nonloc::LazyCompoundVal>(
V) ? BindingKey::Default
2566 : BindingKey::Direct;
2567 return NewB.addBinding(BindingKey::Make(R, KeyKind),
V);
2599std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallArray(
2605 auto CAT = dyn_cast<ConstantArrayType>(AT);
2609 return std::nullopt;
2613 return std::nullopt;
2617 if (ArrSize > SmallArrayLimit)
2618 return std::nullopt;
2622 for (uint64_t i = 0; i < ArrSize; ++i) {
2625 MRMgr.getElementRegion(Ty, Idx, LCV.
getRegion(), Ctx);
2626 SVal V = getBindingForElement(getRegionBindings(LCV.
getStore()), SrcER);
2628 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2638 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindArray",
2645 std::optional<uint64_t>
Size;
2655 return bindAggregate(B, R,
V);
2660 if (std::optional NewB = tryBindSmallArray(B, R, AT, *LCV))
2663 return bindAggregate(B, R,
Init);
2666 if (
Init.isUnknown())
2676 for (;
Size ? i < *
Size :
true; ++i, ++VI) {
2684 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2687 NewB = bindStruct(NewB, ER, *VI);
2689 NewB = bindArray(NewB, ER, *VI);
2697 if (!Size || i < *Size)
2698 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2706 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindVector",
2715 if (isa<nonloc::LazyCompoundVal, nonloc::SymbolVal>(
V))
2716 return bindAggregate(B, R,
V);
2721 if (!isa<nonloc::CompoundVal>(
V)) {
2731 for ( ; index != numElements ; ++index) {
2739 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2742 NewB = bindArray(NewB, ER, *VI);
2744 NewB = bindStruct(NewB, ER, *VI);
2755 return std::nullopt;
2757 const auto *Cluster = B.lookup(R);
2758 if (!Cluster || !llvm::hasSingleElement(*Cluster))
2759 return std::nullopt;
2761 const auto [Key,
Value] = *Cluster->begin();
2762 return Key.isDirect() ? std::optional<SVal>{} :
Value;
2767 auto B = getRegionBindings(LCV.
getStore());
2768 return getUniqueDefaultBinding(B, LCV.
getRegion());
2771std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
2791 if (std::optional<SVal> Val = getUniqueDefaultBinding(LCV)) {
2792 return B.
addBinding(BindingKey::Make(R, BindingKey::Default), Val.value());
2797 if (
const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
2798 if (
Class->getNumBases() != 0 ||
Class->getNumVBases() != 0)
2799 return std::nullopt;
2801 for (
const auto *FD : RD->
fields()) {
2807 if (Fields.size() == SmallStructLimit)
2808 return std::nullopt;
2818 return std::nullopt;
2820 Fields.push_back(FD);
2827 SVal V = getBindingForField(getRegionBindings(LCV.
getStore()), SourceFR);
2829 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
2839 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindStruct",
2852 if (std::optional<nonloc::LazyCompoundVal> LCV =
2854 if (std::optional NewB = tryBindSmallStruct(B, R, RD, *LCV))
2856 return bindAggregate(B, R,
V);
2858 if (isa<nonloc::SymbolVal>(
V))
2859 return bindAggregate(B, R,
V);
2864 if (
V.isUnknown() || !isa<nonloc::CompoundVal>(
V))
2890 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
2898 assert((CRD->isAggregate() || (Ctx.
getLangOpts().ObjC && VI == VE)) &&
2899 "Non-aggregates are constructed with a constructor!");
2901 for (
const auto &B : CRD->bases()) {
2903 assert(!B.isVirtual() &&
"Aggregates cannot have virtual base classes!");
2914 assert(BRD &&
"Base classes must be C++ classes!");
2917 MRMgr.getCXXBaseObjectRegion(BRD, R,
false);
2919 NewB = bindStruct(NewB, BR, *VI);
2936 if (FI->isUnnamedBitField())
2940 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2943 NewB = bindArray(NewB, FR, *VI);
2945 NewB = bindStruct(NewB, FR, *VI);
2956 NewB = NewB.
addBinding(R, BindingKey::Default,
2966 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindAggregate",
2973 return removeSubRegionBindings(B, R).
addBinding(R, BindingKey::Default, Val);
2981class RemoveDeadBindingsWorker
2982 :
public ClusterAnalysis<RemoveDeadBindingsWorker> {
2988 RemoveDeadBindingsWorker(RegionStoreManager &rm,
2992 : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr,
b),
2993 SymReaper(symReaper), CurrentLCtx(LCtx) {}
2998 using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
3000 using ClusterAnalysis::AddToWorkList;
3004 bool UpdatePostponed();
3005 void VisitBinding(
SVal V);
3009bool RemoveDeadBindingsWorker::AddToWorkList(
const MemRegion *R) {
3011 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
3014void RemoveDeadBindingsWorker::VisitAddedToCluster(
const MemRegion *baseR,
3017 if (
const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
3018 if (SymReaper.isLive(VR))
3019 AddToWorkList(baseR, &
C);
3024 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
3025 if (SymReaper.isLive(SR->getSymbol()))
3026 AddToWorkList(SR, &
C);
3028 Postponed.push_back(SR);
3033 if (isa<NonStaticGlobalSpaceRegion>(baseR)) {
3034 AddToWorkList(baseR, &
C);
3039 if (
const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
3040 const auto *StackReg =
3044 (RegCtx == CurrentLCtx || RegCtx->
isParentOf(CurrentLCtx)))
3045 AddToWorkList(TR, &
C);
3049void RemoveDeadBindingsWorker::VisitCluster(
const MemRegion *baseR,
3056 if (
const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
3057 SymReaper.markLive(SymR->getSymbol());
3059 for (
const auto &[Key, Val] : *
C) {
3061 SymReaper.markElementIndicesLive(Key.getRegion());
3067void RemoveDeadBindingsWorker::VisitBinding(
SVal V) {
3071 SymReaper.markLazilyCopied(LCS->getRegion());
3073 for (
SVal V : RM.getInterestingValues(*LCS)) {
3075 SymReaper.markLazilyCopied(DepLCS->getRegion());
3086 SymReaper.markLive(R);
3090 for (
auto Var : BR->referenced_vars())
3091 AddToWorkList(Var.getCapturedRegion());
3098 SymReaper.markLive(Sym);
3101bool RemoveDeadBindingsWorker::UpdatePostponed() {
3107 if (SymReaper.isLive(SR->getSymbol())) {
3119 RegionBindingsRef B = getRegionBindings(store);
3120 RemoveDeadBindingsWorker W(*
this, StateMgr, B, SymReaper, LCtx);
3121 W.GenerateClusters();
3125 W.AddToWorkList(Reg);
3128 do W.RunWorkList();
while (W.UpdatePostponed());
3136 if (!W.isVisited(
Base))
3137 B = B.removeCluster(
Base);
3140 return StoreRef(B.asStore(), *
this);
3147void RegionStoreManager::printJson(raw_ostream &Out,
Store S,
const char *NL,
3148 unsigned int Space,
bool IsDot)
const {
3149 RegionBindingsRef
Bindings = getRegionBindings(S);
3151 Indent(Out, Space, IsDot) <<
"\"store\": ";
3154 Out <<
"null," << NL;
3158 Out <<
"{ \"pointer\": \"" <<
Bindings.asStore() <<
"\", \"items\": [" << NL;
3159 Bindings.printJson(Out, NL, Space + 1, IsDot);
3160 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)
llvm::DenseSet< const void * > Visited
static std::optional< SVal > convertOffsetsFromSvalToUnsigneds(const SmallVector< SVal, 2 > &SrcOffsets, const SmallVector< uint64_t, 2 > ArrayExtents, SmallVector< uint64_t, 2 > &DstOffsets)
llvm::ImmutableMap< const MemRegion *, ClusterBindings > RegionBindings
static std::optional< SVal > getDerivedSymbolForBinding(RegionBindingsConstRef B, const TypedValueRegion *BaseRegion, const TypedValueRegion *SubReg, const ASTContext &Ctx, SValBuilder &SVB)
std::pair< BindingKey, SVal > BindingPair
static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields)
SmallVector< const FieldDecl *, 8 > FieldVector
llvm::ImmutableMap< BindingKey, SVal > ClusterBindings
static bool isUnionField(const FieldRegion *FR)
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
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
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
Stores options for the analyzer from the command line.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Represents a C++ struct/union/class.
Represents the canonical version of C arrays with a specified constant size.
uint64_t getLimitedSize() const
Return the size zero-extended to uint64_t or UINT64_MAX if the value is larger than UINT64_MAX.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
This represents one expression.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
Describes an C or C++ initializer list.
bool isStringLiteralInit() const
Is this an initializer for an array of characters, initialized by a string literal or an @encode?
unsigned getNumInits() const
const Expr * getInit(unsigned Init) const
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
bool isParentOf(const LocationContext *LC) const
const Decl * getDecl() const
const StackFrameContext * getStackFrame() const
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool isConstQualified() const
Determine whether this type is const-qualified.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
field_iterator field_begin() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
It represents a stack frame of the call stack (based on CallEvent).
StringLiteral - This represents a string literal expression, e.g.
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
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
Maps string IDs to AST nodes matched by parts of a matcher.
BlockDataRegion - A region that represents a block instance.
CXXThisRegion - Represents the region for the implicit 'this' parameter in a call to a C++ method.
Represents an abstract call to a function or method along a particular path.
ElementRegion is used to represent both array elements and casts.
QualType getElementType() const
RegionRawOffset getAsArrayOffset() const
Compute the offset within the array. The array might also be a subobject.
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.
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
Information about invalidation for a particular region/symbol.
@ TK_PreserveContents
Tells that a region's contents is not changed.
@ TK_DoNotInvalidateSuperRegion
@ TK_EntireMemSpace
When applied to a MemSpaceRegion, indicates the entire memory space should be invalidated.
Represent a region's offset within the top level base region.
bool hasSymbolicOffset() const
const MemRegion * getRegion() const
It might return null.
int64_t getOffset() const
const MemRegion * getRegion() const
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
NonLoc makeArrayIndex(uint64_t idx)
ASTContext & getContext()
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy)
Cast a given SVal to another SVal using given QualType's.
DefinedOrUnknownSVal 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.
A utility class that visits the reachable symbols using a custom SymbolVisitor.
bool scan(nonloc::LazyCompoundVal val)
virtual StoreRef invalidateRegions(Store store, ArrayRef< SVal > Values, ConstCFGElementRef Elem, unsigned Count, const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits, InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated)=0
invalidateRegions - Clears out the specified regions from the store, marking their values as unknown.
virtual bool scanReachableSymbols(Store S, const MemRegion *R, ScanReachableSymbols &Visitor)=0
Finds the transitive closure of symbols within the given region.
virtual void iterBindings(Store store, BindingsHandler &f)=0
iterBindings - Iterate over the bindings in the Store.
virtual BindResult BindDefaultZero(Store store, const MemRegion *R)=0
Return a store with in which all values within the given region are reset to zero.
virtual StoreRef getInitialStore(const LocationContext *InitLoc)=0
getInitialStore - Returns the initial "empty" store representing the value bindings upon entry to an ...
virtual std::optional< SVal > getDefaultBinding(Store store, const MemRegion *R)=0
Return the default value bound to a region in a given store.
virtual StoreRef killBinding(Store ST, Loc L)=0
Create a new store with the specified binding removed.
virtual void decrementReferenceCount(Store store)
If the StoreManager supports it, decrement the reference count of the specified Store object.
virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx, SymbolReaper &SymReaper)=0
virtual void incrementReferenceCount(Store store)
If the StoreManager supports it, increment the reference count of the specified Store object.
virtual SVal ArrayToPointer(Loc Array, QualType ElementTy)=0
ArrayToPointer - Used by ExprEngine::VistCast to handle implicit conversions between arrays and point...
virtual bool includedInBindings(Store store, const MemRegion *region) const =0
virtual SVal getBinding(Store store, Loc loc, QualType T=QualType())=0
Return the value bound to specified location in a given state.
virtual BindResult BindDefaultInitial(Store store, const MemRegion *R, SVal V)=0
Return a store with the specified value bound to all sub-regions of the region.
virtual void printJson(raw_ostream &Out, Store S, const char *NL, unsigned int Space, bool IsDot) const =0
StringRegion - Region associated with a StringLiteral.
SubRegion - A region that subsets another larger region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
bool isSubRegionOf(const MemRegion *R) const override
Check if the region is a subregion of the given region.
MemRegionManager & getMemRegionManager() const override
static bool canSymbolicate(QualType T)
A class responsible for cleaning up unused symbols.
llvm::iterator_range< RegionSetTy::const_iterator > regions() const
SymbolicRegion - A special, "non-concrete" region.
TypedRegion - An abstract class representing regions that are typed.
TypedValueRegion - An abstract class representing regions having a typed value.
virtual QualType getValueType() const =0
QualType getLocationType() const override
QualType getValueType() const override
const VarDecl * getDecl() const override=0
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getRegion() const
Get the underlining region.
The simplest example of a concrete compound value is nonloc::CompoundVal, which represents a concrete...
llvm::ImmutableList< SVal >::iterator iterator
Value representing integer constant.
While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...
LLVM_ATTRIBUTE_RETURNS_NONNULL const LazyCompoundValData * getCVData() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
This function itself is immaterial.
const void * getStore() const
It might return null.
Defines the clang::TargetInfo interface.
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, DeclRefExpr > declRefExpr
Matches expressions that refer to declarations.
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< Stmt > StatementMatcher
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
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.
@ Bind
'bind' clause, allowed on routine constructs.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
CFGBlock::ConstCFGElementRef ConstCFGElementRef
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Diagnostic wrappers for TextAPI types for error reporting.
static raw_ostream & operator<<(raw_ostream &Out, BindingKey K)
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...