30#include "llvm/ADT/ImmutableMap.h"
31#include "llvm/ADT/STLExtras.h"
32#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 hasSymbolicOffset()
const {
return P.getInt() & Symbolic; }
77 assert(!hasSymbolicOffset());
81 const SubRegion *getConcreteOffsetRegion()
const {
82 assert(hasSymbolicOffset());
87 if (hasSymbolicOffset())
92 void Profile(llvm::FoldingSetNodeID& ID)
const {
93 ID.AddPointer(
P.getOpaqueValue());
100 if (
P.getOpaqueValue() <
X.P.getOpaqueValue())
102 if (
P.getOpaqueValue() >
X.P.getOpaqueValue())
104 return Data <
X.Data;
108 return P.getOpaqueValue() ==
X.P.getOpaqueValue() &&
112 LLVM_DUMP_METHOD
void dump()
const;
116BindingKey BindingKey::Make(
const MemRegion *R, Kind k) {
119 return BindingKey(cast<SubRegion>(R), cast<SubRegion>(RO.
getRegion()), k);
125static inline raw_ostream &
operator<<(raw_ostream &Out, BindingKey K) {
126 Out <<
"\"kind\": \"" << (K.isDirect() ?
"Direct" :
"Default")
127 <<
"\", \"offset\": ";
129 if (!K.hasSymbolicOffset())
130 Out << K.getOffset();
139#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
140void BindingKey::dump()
const { llvm::errs() << *
this; }
151typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
155class RegionBindingsRef :
public llvm::ImmutableMapRef<const MemRegion *,
157 ClusterBindings::Factory *CBFactory;
171 typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
174 RegionBindingsRef(ClusterBindings::Factory &CBFactory,
175 const RegionBindings::TreeTy *
T,
176 RegionBindings::TreeTy::Factory *F,
178 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(
T, F),
179 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
181 RegionBindingsRef(
const ParentTy &
P,
182 ClusterBindings::Factory &CBFactory,
184 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(
P),
185 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
187 RegionBindingsRef add(key_type_ref K, data_type_ref
D)
const {
188 return RegionBindingsRef(
static_cast<const ParentTy *
>(
this)->add(K,
D),
189 *CBFactory, IsMainAnalysis);
192 RegionBindingsRef remove(key_type_ref K)
const {
193 return RegionBindingsRef(
static_cast<const ParentTy *
>(
this)->remove(K),
194 *CBFactory, IsMainAnalysis);
197 RegionBindingsRef addBinding(BindingKey K,
SVal V)
const;
199 RegionBindingsRef addBinding(
const MemRegion *R,
200 BindingKey::Kind k,
SVal V)
const;
202 const SVal *lookup(BindingKey K)
const;
203 const SVal *lookup(
const MemRegion *R, BindingKey::Kind k)
const;
206 RegionBindingsRef removeBinding(BindingKey K);
208 RegionBindingsRef removeBinding(
const MemRegion *R,
211 RegionBindingsRef removeBinding(
const MemRegion *R) {
212 return removeBinding(R, BindingKey::Direct).
213 removeBinding(R, BindingKey::Default);
216 std::optional<SVal> getDirectBinding(
const MemRegion *R)
const;
220 std::optional<SVal> getDefaultBinding(
const MemRegion *R)
const;
223 Store asStore()
const {
224 llvm::PointerIntPair<Store, 1, bool> Ptr = {
225 asImmutableMap().getRootWithoutRetain(), IsMainAnalysis};
226 return reinterpret_cast<Store>(Ptr.getOpaqueValue());
229 bool isMainAnalysis()
const {
230 return IsMainAnalysis;
233 void printJson(raw_ostream &Out,
const char *NL =
"\n",
234 unsigned int Space = 0,
bool IsDot =
false)
const {
235 for (iterator I = begin(),
E = end(); I !=
E; ++I) {
237 Indent(Out, Space, IsDot)
238 <<
"{ \"cluster\": \"" << I.getKey() <<
"\", \"pointer\": \""
239 << (
const void *)I.getKey() <<
"\", \"items\": [" << NL;
243 for (ClusterBindings::iterator CI = CB.begin(), CE = CB.end(); CI != CE;
245 Indent(Out, Space, IsDot) <<
"{ " << CI.getKey() <<
", \"value\": ";
246 CI.getData().printJson(Out,
true);
248 if (std::next(CI) != CE)
254 Indent(Out, Space, IsDot) <<
"]}";
255 if (std::next(I) !=
E)
261 LLVM_DUMP_METHOD
void dump()
const { printJson(llvm::errs()); }
268RegionBindingsRef::getDirectBinding(
const MemRegion *R)
const {
269 const SVal *
V = lookup(R, BindingKey::Direct);
270 return V ? std::optional<SVal>(*
V) : std::nullopt;
274RegionBindingsRef::getDefaultBinding(
const MemRegion *R)
const {
275 const SVal *
V = lookup(R, BindingKey::Default);
276 return V ? std::optional<SVal>(*
V) :
std::nullopt;
279RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K,
SVal V)
const {
284 (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
287 return add(
Base, NewCluster);
291RegionBindingsRef RegionBindingsRef::addBinding(
const MemRegion *R,
294 return addBinding(BindingKey::Make(R, k),
V);
297const SVal *RegionBindingsRef::lookup(BindingKey K)
const {
301 return Cluster->lookup(K);
305 BindingKey::Kind k)
const {
306 return lookup(BindingKey::Make(R, k));
309RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
316 if (NewCluster.isEmpty())
318 return add(
Base, NewCluster);
321RegionBindingsRef RegionBindingsRef::removeBinding(
const MemRegion *R,
323 return removeBinding(BindingKey::Make(R, k));
331class InvalidateRegionsWorker;
335 RegionBindings::Factory RBFactory;
336 mutable ClusterBindings::Factory CBFactory;
338 typedef std::vector<SVal> SValListTy;
341 SValListTy> LazyBindingsMapTy;
342 LazyBindingsMapTy LazyBindingsMap;
352 unsigned SmallStructLimit;
362 unsigned SmallArrayLimit;
366 void populateWorkList(InvalidateRegionsWorker &W,
368 InvalidatedRegions *TopLevelRegions);
373 CBFactory(mgr.getAllocator()), SmallStructLimit(0), SmallArrayLimit(0) {
376 SmallStructLimit = Options.RegionStoreSmallStructLimit;
377 SmallArrayLimit = Options.RegionStoreSmallArrayLimit;
397 bool IsMainAnalysis =
false;
398 if (
const auto *FD = dyn_cast<FunctionDecl>(InitLoc->
getDecl()))
399 IsMainAnalysis = FD->isMain() && !Ctx.getLangOpts().CPlusPlus;
401 RegionBindingsRef::ParentTy(RBFactory.getEmptyMap(), RBFactory),
402 CBFactory, IsMainAnalysis).asStore(), *
this);
413 InvalidatedRegions *Invalidated);
417 const Expr *
E,
unsigned Count,
422 InvalidatedRegions *Invalidated,
423 InvalidatedRegions *InvalidatedTopLevel)
override;
443 return StoreRef(bind(getRegionBindings(store), LV,
V).asStore(), *
this);
452 RegionBindingsRef B = getRegionBindings(store);
455 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
456 "Double initialization!");
457 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
458 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this);
473 if (
const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
474 if (BR->getDecl()->isEmpty())
477 RegionBindingsRef B = getRegionBindings(store);
478 SVal V = svalBuilder.makeZeroVal(Ctx.CharTy);
479 B = removeSubRegionBindings(B, cast<SubRegion>(R));
480 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
481 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this);
494 std::optional<RegionBindingsRef>
506 std::optional<RegionBindingsRef>
526 getRegionBindings(store).manualRetain();
533 getRegionBindings(store).manualRelease();
556 RegionBindingsRef B = getRegionBindings(S);
580 RegionBindingsRef LazyBinding);
605 std::pair<Store, const SubRegion *>
634 RegionBindingsRef getRegionBindings(
Store store)
const {
635 llvm::PointerIntPair<Store, 1, bool> Ptr;
636 Ptr.setFromOpaqueValue(
const_cast<void *
>(store));
637 return RegionBindingsRef(
639 static_cast<const RegionBindings::TreeTy *
>(Ptr.getPointer()),
640 RBFactory.getTreeFactory(),
645 unsigned int Space = 0,
bool IsDot =
false)
const override;
648 RegionBindingsRef B = getRegionBindings(store);
649 for (
const auto &[Region, Cluster] : B) {
650 for (
const auto &[Key,
Value] : Cluster) {
653 if (
const SubRegion *R = dyn_cast<SubRegion>(Key.getRegion())) {
655 if (!f.HandleBinding(*
this, store, R,
Value))
669std::unique_ptr<StoreManager>
671 return std::make_unique<RegionStoreManager>(StMgr);
681enum GlobalsFilterKind {
690template <
typename DERIVED>
691class ClusterAnalysis {
693 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
694 typedef const MemRegion * WorkListElement;
701 RegionStoreManager &RM;
723 : RM(rm), Ctx(StateMgr.getContext()),
724 svalBuilder(StateMgr.getSValBuilder()), B(
std::move(
b)) {}
726 RegionBindingsRef getRegionBindings()
const {
return B; }
729 return Visited.count(getCluster(R));
732 void GenerateClusters() {
734 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
739 assert(!Cluster.isEmpty() &&
"Empty clusters should be removed");
740 static_cast<DERIVED*
>(
this)->VisitAddedToCluster(
Base, Cluster);
744 if (
static_cast<DERIVED*
>(
this)->includeEntireMemorySpace(
Base))
745 AddToWorkList(WorkListElement(
Base), &Cluster);
757 return static_cast<DERIVED*
>(
this)->AddToWorkList(R);
761 while (!WL.empty()) {
762 WorkListElement
E = WL.pop_back_val();
765 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR, getCluster(BaseR));
774 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR,
C);
783bool RegionStoreManager::scanReachableSymbols(
Store S,
const MemRegion *R,
785 assert(R == R->
getBaseRegion() &&
"Should only be called for base regions");
786 RegionBindingsRef B = getRegionBindings(S);
792 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
794 if (!Callbacks.
scan(RI.getData()))
808 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
814 if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R))
816 Fields.push_back(FR->getDecl());
818 R = cast<SubRegion>(R)->getSuperRegion();
823 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
831 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
833 return std::equal(FieldsInBindingKey.begin() + Delta,
834 FieldsInBindingKey.end(),
837 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
838 Fields.begin() - Delta);
854 bool IncludeAllDefaultBindings) {
856 if (TopKey.hasSymbolicOffset()) {
858 Top = TopKey.getConcreteOffsetRegion();
859 TopKey = BindingKey::Make(Top, BindingKey::Default);
863 uint64_t Length = UINT64_MAX;
865 if (std::optional<nonloc::ConcreteInt> ExtentCI =
867 const llvm::APSInt &ExtentInt = ExtentCI->getValue();
868 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
871 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
872 if (FR->getDecl()->isBitField())
873 Length = FR->getDecl()->getBitWidthValue(SVB.
getContext());
876 for (
const auto &StoreEntry : Cluster) {
877 BindingKey NextKey = StoreEntry.first;
878 if (NextKey.getRegion() == TopKey.getRegion()) {
884 if (NextKey.getOffset() > TopKey.getOffset() &&
885 NextKey.getOffset() - TopKey.getOffset() < Length) {
890 }
else if (NextKey.getOffset() == TopKey.getOffset()) {
897 if (IncludeAllDefaultBindings || NextKey.isDirect())
901 }
else if (NextKey.hasSymbolicOffset()) {
907 if (IncludeAllDefaultBindings || NextKey.isDirect())
910 }
else if (
const SubRegion *BaseSR = dyn_cast<SubRegion>(
Base)) {
913 if (BaseSR->isSubRegionOf(Top))
924 const SubRegion *Top,
bool IncludeAllDefaultBindings) {
926 BindingKey::Make(Top, BindingKey::Default),
927 IncludeAllDefaultBindings);
933 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
936 if (Top == ClusterHead) {
938 return B.remove(Top);
945 if (TopKey.hasSymbolicOffset()) {
946 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
947 return B.addBinding(Concrete, BindingKey::Default,
UnknownVal());
957 for (BindingKey Key : llvm::make_first_range(
Bindings))
958 Result = Result.remove(Key);
964 if (TopKey.hasSymbolicOffset()) {
965 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
966 Result = Result.
add(BindingKey::Make(Concrete, BindingKey::Default),
970 if (Result.isEmpty())
971 return B.remove(ClusterHead);
972 return B.add(ClusterHead, Result.asImmutableMap());
976class InvalidateRegionsWorker :
public ClusterAnalysis<InvalidateRegionsWorker>
984 GlobalsFilterKind GlobalsFilter;
986 InvalidateRegionsWorker(RegionStoreManager &rm,
989 const Expr *ex,
unsigned count,
994 GlobalsFilterKind GFK)
995 : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr,
b),
996 Ex(ex), Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
997 GlobalsFilter(GFK) {}
1000 void VisitBinding(
SVal V);
1002 using ClusterAnalysis::AddToWorkList;
1012 bool isInitiallyIncludedGlobalRegion(
const MemRegion *R);
1016bool InvalidateRegionsWorker::AddToWorkList(
const MemRegion *R) {
1017 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1020 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
1023void InvalidateRegionsWorker::VisitBinding(
SVal V) {
1034 if (std::optional<nonloc::LazyCompoundVal> LCS =
1039 for (
SVal V : RM.getInterestingValues(*LCS))
1040 if (!isa<nonloc::LazyCompoundVal>(
V))
1047void InvalidateRegionsWorker::VisitCluster(
const MemRegion *baseR,
1050 bool PreserveRegionsContents =
1051 ITraits.hasTrait(baseR,
1055 for (
SVal Val : llvm::make_second_range(*
C))
1059 if (!PreserveRegionsContents)
1060 B = B.remove(baseR);
1063 if (
const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
1064 if (
const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
1069 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
1070 using namespace ast_matchers;
1072 const char *DeclBind =
"DeclBind";
1074 to(
varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
1076 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
1077 RD->getASTContext());
1080 auto *VD = Match.getNodeAs<
VarDecl>(DeclBind);
1082 RM.getRegionManager().getVarRegion(VD, LCtx);
1083 AddToWorkList(ToInvalidate);
1092 for (
auto Var : BR->referenced_vars()) {
1093 const VarRegion *VR = Var.getCapturedRegion();
1105 if (std::optional<Loc> L =
V.getAs<
Loc>()) {
1116 IS.insert(SR->getSymbol());
1119 if (PreserveRegionsContents)
1124 Regions->push_back(baseR);
1126 if (isa<AllocaRegion, SymbolicRegion>(baseR)) {
1131 B = B.addBinding(baseR, BindingKey::Default,
V);
1141 if (isInitiallyIncludedGlobalRegion(baseR)) {
1153 B = B.addBinding(baseR, BindingKey::Default,
V);
1158 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1162 if (doNotInvalidateSuperRegion) {
1165 std::optional<uint64_t> NumElements;
1169 NumElements = CAT->getZExtSize();
1171 goto conjure_default;
1172 QualType ElementTy = AT->getElementType();
1180 AddToWorkList(SuperR);
1181 goto conjure_default;
1185 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
1186 bool UpperOverflow = UpperOffset < LowerOffset;
1191 goto conjure_default;
1195 goto conjure_default;
1197 for (
const auto &[BK,
V] : *
C) {
1198 std::optional<uint64_t> ROffset =
1199 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
1204 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
1206 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
1207 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
1208 B = B.removeBinding(BK);
1212 if (isa_and_nonnull<SymbolicRegion>(R))
1221 AT->getElementType(), Count);
1222 B = B.addBinding(baseR, BindingKey::Default,
V);
1229 B = B.addBinding(baseR, BindingKey::Direct,
V);
1232bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
1234 switch (GlobalsFilter) {
1237 case GFK_SystemOnly:
1243 llvm_unreachable(
"unknown globals filter");
1246bool InvalidateRegionsWorker::includeEntireMemorySpace(
const MemRegion *
Base) {
1247 if (isInitiallyIncludedGlobalRegion(
Base))
1251 return ITraits.hasTrait(MemSpace,
1260 RegionBindingsRef B,
1261 InvalidatedRegions *Invalidated) {
1269 B = B.removeBinding(GS)
1270 .addBinding(BindingKey::Make(GS, BindingKey::Default),
V);
1275 Invalidated->push_back(GS);
1280void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
1282 InvalidatedRegions *TopLevelRegions) {
1283 for (
SVal V : Values) {
1285 for (
SVal S : getInterestingValues(*LCS))
1286 if (
const MemRegion *R = S.getAsRegion())
1293 if (TopLevelRegions)
1294 TopLevelRegions->push_back(R);
1302RegionStoreManager::invalidateRegions(
Store store,
1304 const Expr *Ex,
unsigned Count,
1309 InvalidatedRegions *TopLevelRegions,
1310 InvalidatedRegions *Invalidated) {
1311 GlobalsFilterKind GlobalsFilter;
1313 if (
Call->isInSystemHeader())
1314 GlobalsFilter = GFK_SystemOnly;
1316 GlobalsFilter = GFK_All;
1318 GlobalsFilter = GFK_None;
1321 RegionBindingsRef B = getRegionBindings(store);
1322 InvalidateRegionsWorker W(*
this, StateMgr, B, Ex, Count, LCtx, IS, ITraits,
1323 Invalidated, GlobalsFilter);
1326 W.GenerateClusters();
1329 populateWorkList(W, Values, TopLevelRegions);
1334 B = W.getRegionBindings();
1340 switch (GlobalsFilter) {
1342 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
1343 Ex, Count, LCtx, B, Invalidated);
1345 case GFK_SystemOnly:
1346 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
1347 Ex, Count, LCtx, B, Invalidated);
1353 return StoreRef(B.asStore(), *
this);
1367 if (isa<loc::ConcreteInt>(Array))
1370 if (!isa<loc::MemRegionVal>(Array))
1384 assert(!isa<UnknownVal>(L) &&
"location unknown");
1385 assert(!isa<UndefinedVal>(L) &&
"location undefined");
1402 if (isa<BlockDataRegion>(MR)) {
1408 if (
const auto *TVR = dyn_cast<TypedValueRegion>(MR))
1409 T = TVR->getValueType();
1410 else if (
const auto *TR = dyn_cast<TypedRegion>(MR))
1412 else if (
const auto *SR = dyn_cast<SymbolicRegion>(MR))
1413 T = SR->getPointeeStaticType();
1415 assert(!
T.isNull() &&
"Unable to auto-detect binding type!");
1416 assert(!
T->
isVoidType() &&
"Attempting to dereference a void pointer!");
1418 if (!isa<TypedValueRegion>(MR))
1419 MR = GetElementZeroRegion(cast<SubRegion>(MR),
T);
1440 return getBindingForStruct(B, R);
1444 return createLazyBinding(B, R);
1448 return getBindingForArray(B, R);
1457 if (
const FieldRegion* FR = dyn_cast<FieldRegion>(R))
1479 if (
const VarRegion *VR = dyn_cast<VarRegion>(R)) {
1489 const SVal *
V = B.lookup(R, BindingKey::Direct);
1513 RegionTy = TVR->getValueType();
1516 RegionTy = SR->getSymbol()->getType();
1528static std::optional<nonloc::LazyCompoundVal>
1530 const SubRegion *R,
bool AllowSubregionBindings) {
1531 std::optional<SVal>
V = B.getDefaultBinding(R);
1533 return std::nullopt;
1535 std::optional<nonloc::LazyCompoundVal> LCV =
1538 return std::nullopt;
1543 if (!RegionTy.
isNull() &&
1545 QualType SourceRegionTy = LCV->getRegion()->getValueType();
1547 return std::nullopt;
1550 if (!AllowSubregionBindings) {
1557 return std::nullopt;
1563std::pair<Store, const SubRegion *>
1567 if (originalRegion != R) {
1568 if (std::optional<nonloc::LazyCompoundVal>
V =
1570 return std::make_pair(
V->getStore(),
V->getRegion());
1573 typedef std::pair<Store, const SubRegion *> StoreRegionPair;
1574 StoreRegionPair Result = StoreRegionPair();
1577 Result = findLazyBinding(B, cast<SubRegion>(ER->getSuperRegion()),
1581 Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);
1583 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
1584 Result = findLazyBinding(B, cast<SubRegion>(FR->getSuperRegion()),
1588 Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);
1591 dyn_cast<CXXBaseObjectRegion>(R)) {
1594 Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
1598 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
1612 assert(CAT &&
"ConstantArrayType should not be null");
1617 }
while ((CAT = dyn_cast<ConstantArrayType>(CAT->
getElementType())));
1635static std::pair<SmallVector<SVal, 2>,
const MemRegion *>
1637 assert(ER &&
"ConstantArrayType should not be null");
1641 SValOffsets.push_back(ER->
getIndex());
1643 ER = dyn_cast<ElementRegion>(
Base);
1645 return {SValOffsets,
Base};
1669static std::optional<SVal>
1690 DstOffsets.resize(SrcOffsets.size());
1691 auto ExtentIt = ArrayExtents.begin();
1692 auto OffsetIt = DstOffsets.begin();
1694 for (
SVal V : llvm::reverse(SrcOffsets)) {
1697 const llvm::APSInt &Offset = CI->getValue();
1698 if (Offset.isNegative() || Offset.uge(*(ExtentIt++)))
1701 *(OffsetIt++) = Offset.getZExtValue();
1709 return std::nullopt;
1712std::optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer(
1714 assert(R &&
"ElementRegion should not be null");
1722 return std::nullopt;
1724 assert(!SValOffsets.empty() &&
"getElementRegionOffsets guarantees the "
1725 "offsets vector is not empty.");
1733 return std::nullopt;
1748 return std::nullopt;
1754 return std::nullopt;
1765 if (SValOffsets.size() != Extents.size())
1766 return std::nullopt;
1770 SValOffsets, Extents, ConcreteOffsets))
1776 if (
const auto *ILE = dyn_cast<InitListExpr>(
Init))
1777 return getSValFromInitListExpr(ILE, ConcreteOffsets, R->
getElementType());
1782 if (
const auto *SL = dyn_cast<StringLiteral>(
Init))
1783 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
1788 return std::nullopt;
1808std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
1811 assert(ILE &&
"InitListExpr should not be null");
1813 for (uint64_t Offset : Offsets) {
1820 if (
const auto *SL = dyn_cast<StringLiteral>(ILE->
getInit(0)))
1821 return getSValFromStringLiteral(SL, Offset, ElemT);
1830 const auto *IL = dyn_cast<InitListExpr>(
E);
1844 return std::nullopt;
1875 assert(SL &&
"StringLiteral should not be null");
1891 if (
const std::optional<SVal> &ParentValue =
1892 B.getDirectBinding(BaseRegion)) {
1893 if (
SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
1896 if (ParentValue->isUndef())
1905 return std::nullopt;
1911 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
1917 if (
const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
1925 const llvm::APSInt &Idx = CI->getValue();
1929 return getSValFromStringLiteral(SL, Idx.getZExtValue(),
T);
1931 }
else if (isa<ElementRegion, VarRegion>(superR)) {
1932 if (std::optional<SVal>
V = getConstantValFromConstArrayInitializer(B, R))
1937 if (isa<CodeTextRegion>(superR))
1956 return getBindingForFieldOrElementCommon(B, R, R->
getElementType());
1963 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
1970 if (
const auto *VR = dyn_cast<VarRegion>(superR)) {
1980 if (
const auto *InitList = dyn_cast<InitListExpr>(
Init)) {
1981 if (Index < InitList->getNumInits()) {
1982 if (
const Expr *FieldInit = InitList->getInit(Index))
2011 return getBindingForFieldOrElementCommon(B, R, Ty);
2014std::optional<SVal> RegionStoreManager::getBindingForDerivedDefaultValue(
2018 if (
const std::optional<SVal> &
D = B.getDefaultBinding(superR)) {
2031 if (isa<nonloc::LazyCompoundVal, nonloc::CompoundVal>(val))
2034 llvm_unreachable(
"Unknown default value");
2037 return std::nullopt;
2040SVal RegionStoreManager::getLazyBinding(
const SubRegion *LazyBindingRegion,
2041 RegionBindingsRef LazyBinding) {
2043 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
2044 Result = getBindingForElement(LazyBinding, ER);
2046 Result = getBindingForField(LazyBinding,
2047 cast<FieldRegion>(LazyBindingRegion));
2063 if (Result.isUndef())
2078 Store lazyBindingStore =
nullptr;
2079 const SubRegion *lazyBindingRegion =
nullptr;
2080 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
2081 if (lazyBindingRegion)
2082 return getLazyBinding(lazyBindingRegion,
2083 getRegionBindings(lazyBindingStore));
2087 bool hasSymbolicIndex =
false;
2103 bool hasPartialLazyBinding =
false;
2108 if (std::optional<SVal>
D =
2109 getBindingForDerivedDefaultValue(B,
Base, R, Ty)) {
2111 hasPartialLazyBinding =
true;
2119 NonLoc index = ER->getIndex();
2121 hasSymbolicIndex =
true;
2126 SR = dyn_cast<SubRegion>(
Base);
2130 if (isa<ElementRegion>(R)) {
2135 if (typedSuperR->getValueType()->isVectorType())
2144 if (hasSymbolicIndex)
2150 if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->
getBaseRegion())) {
2151 if (
const std::optional<SVal> &
V = B.getDefaultBinding(R))
2164 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2170 if (
const std::optional<SVal> &
V = B.getDefaultBinding(superR)) {
2178 return getBindingForLazySymbol(R);
2185 if (std::optional<SVal>
V = B.getDirectBinding(R))
2188 if (std::optional<SVal>
V = B.getDefaultBinding(R))
2196 if (isa<StackArgumentsSpaceRegion>(MS))
2214 if (isa<UnknownSpaceRegion>(MS))
2217 if (isa<GlobalsSpaceRegion>(MS)) {
2221 if (B.isMainAnalysis())
2230 if (isa<StaticGlobalSpaceRegion>(MS))
2233 if (std::optional<SVal>
V = getBindingForDerivedDefaultValue(B, MS, R,
T)) {
2249const RegionStoreManager::SValListTy &
2252 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.
getCVData());
2253 if (I != LazyBindingsMap.end())
2260 RegionBindingsRef B = getRegionBindings(LCV.
getStore());
2266 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2272 if (
V.isUnknownOrUndef() ||
V.isConstant())
2276 const SValListTy &InnerList = getInterestingValues(*InnerLCV);
2277 List.insert(List.end(), InnerList.begin(), InnerList.end());
2283 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2288 if (std::optional<nonloc::LazyCompoundVal>
V =
2299 return CRD->getNumBases() == 0;
2309 return createLazyBinding(B, R);
2315 "Only constant array types can have compound bindings.");
2317 return createLazyBinding(B, R);
2320bool RegionStoreManager::includedInBindings(
Store store,
2322 RegionBindingsRef B = getRegionBindings(store);
2326 if (B.lookup(region))
2330 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
2332 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
2334 SVal D = CI.getData();
2350 if (
const MemRegion* R = LV->getRegion())
2351 return StoreRef(getRegionBindings(ST).removeBinding(R)
2353 .getRootWithoutRetain(),
2366 const MemRegion *R = MemRegVal->getRegion();
2372 return bindArray(B, TR,
V);
2374 return bindStruct(B, TR,
V);
2376 return bindVector(B, TR,
V);
2378 return bindAggregate(B, TR,
V);
2384 R = GetElementZeroRegion(SR, SR->getPointeeStaticType());
2386 assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
2387 "'this' pointer is not an l-value and is not assignable");
2390 RegionBindingsRef NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
2393 auto KeyKind = isa<nonloc::LazyCompoundVal>(
V) ? BindingKey::Default
2394 : BindingKey::Direct;
2395 return NewB.addBinding(BindingKey::Make(R, KeyKind),
V);
2422 return B.addBinding(R, BindingKey::Default,
V);
2425std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallArray(
2429 auto CAT = dyn_cast<ConstantArrayType>(AT);
2433 return std::nullopt;
2437 return std::nullopt;
2441 if (ArrSize > SmallArrayLimit)
2442 return std::nullopt;
2444 RegionBindingsRef NewB = B;
2446 for (uint64_t i = 0; i < ArrSize; ++i) {
2449 MRMgr.getElementRegion(Ty, Idx, LCV.
getRegion(), Ctx);
2450 SVal V = getBindingForElement(getRegionBindings(LCV.
getStore()), SrcER);
2452 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2466 std::optional<uint64_t>
Size;
2476 return bindAggregate(B, R,
V);
2480 if (std::optional<nonloc::LazyCompoundVal> LCV =
2482 if (std::optional<RegionBindingsRef> NewB =
2483 tryBindSmallArray(B, R, AT, *LCV))
2486 return bindAggregate(B, R,
Init);
2489 if (
Init.isUnknown())
2497 RegionBindingsRef NewB(B);
2499 for (;
Size ? i < *
Size :
true; ++i, ++VI) {
2505 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2508 NewB = bindStruct(NewB, ER, *VI);
2510 NewB = bindArray(NewB, ER, *VI);
2518 if (!Size || i < *Size)
2519 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2531 if (isa<nonloc::LazyCompoundVal, nonloc::SymbolVal>(
V))
2532 return bindAggregate(B, R,
V);
2537 if (!isa<nonloc::CompoundVal>(
V)) {
2545 RegionBindingsRef NewB(B);
2547 for ( ; index != numElements ; ++index) {
2552 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2555 NewB = bindArray(NewB, ER, *VI);
2557 NewB = bindStruct(NewB, ER, *VI);
2564std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
2569 if (
const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
2570 if (
Class->getNumBases() != 0 ||
Class->getNumVBases() != 0)
2571 return std::nullopt;
2573 for (
const auto *FD : RD->
fields()) {
2579 if (Fields.size() == SmallStructLimit)
2580 return std::nullopt;
2590 return std::nullopt;
2592 Fields.push_back(FD);
2595 RegionBindingsRef NewB = B;
2599 SVal V = getBindingForField(getRegionBindings(LCV.
getStore()), SourceFR);
2601 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
2617 if (!RD->isCompleteDefinition())
2621 if (std::optional<nonloc::LazyCompoundVal> LCV =
2623 if (std::optional<RegionBindingsRef> NewB =
2624 tryBindSmallStruct(B, R, RD, *LCV))
2626 return bindAggregate(B, R,
V);
2628 if (isa<nonloc::SymbolVal>(
V))
2629 return bindAggregate(B, R,
V);
2634 if (
V.isUnknown() || !isa<nonloc::CompoundVal>(
V))
2656 RegionBindingsRef NewB(B);
2660 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
2668 assert((CRD->isAggregate() || (Ctx.
getLangOpts().ObjC && VI == VE)) &&
2669 "Non-aggregates are constructed with a constructor!");
2671 for (
const auto &B : CRD->bases()) {
2673 assert(!B.isVirtual() &&
"Aggregates cannot have virtual base classes!");
2682 assert(BRD &&
"Base classes must be C++ classes!");
2685 MRMgr.getCXXBaseObjectRegion(BRD, R,
false);
2687 NewB = bindStruct(NewB, BR, *VI);
2695 for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) {
2701 if (FI->isUnnamedBitField())
2705 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2708 NewB = bindArray(NewB, FR, *VI);
2710 NewB = bindStruct(NewB, FR, *VI);
2718 NewB = NewB.addBinding(R, BindingKey::Default,
2731 return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);
2739class RemoveDeadBindingsWorker
2740 :
public ClusterAnalysis<RemoveDeadBindingsWorker> {
2746 RemoveDeadBindingsWorker(RegionStoreManager &rm,
2750 : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr,
b),
2751 SymReaper(symReaper), CurrentLCtx(LCtx) {}
2756 using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
2758 using ClusterAnalysis::AddToWorkList;
2762 bool UpdatePostponed();
2763 void VisitBinding(
SVal V);
2767bool RemoveDeadBindingsWorker::AddToWorkList(
const MemRegion *R) {
2769 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
2772void RemoveDeadBindingsWorker::VisitAddedToCluster(
const MemRegion *baseR,
2775 if (
const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
2776 if (SymReaper.isLive(VR))
2777 AddToWorkList(baseR, &
C);
2782 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
2783 if (SymReaper.isLive(SR->getSymbol()))
2784 AddToWorkList(SR, &
C);
2786 Postponed.push_back(SR);
2791 if (isa<NonStaticGlobalSpaceRegion>(baseR)) {
2792 AddToWorkList(baseR, &
C);
2797 if (
const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
2798 const auto *StackReg =
2802 (RegCtx == CurrentLCtx || RegCtx->
isParentOf(CurrentLCtx)))
2803 AddToWorkList(TR, &
C);
2807void RemoveDeadBindingsWorker::VisitCluster(
const MemRegion *baseR,
2814 if (
const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
2815 SymReaper.markLive(SymR->getSymbol());
2817 for (
const auto &[Key, Val] : *
C) {
2819 SymReaper.markElementIndicesLive(Key.getRegion());
2825void RemoveDeadBindingsWorker::VisitBinding(
SVal V) {
2829 SymReaper.markLazilyCopied(LCS->getRegion());
2831 for (
SVal V : RM.getInterestingValues(*LCS)) {
2833 SymReaper.markLazilyCopied(DepLCS->getRegion());
2844 SymReaper.markLive(R);
2848 for (
auto Var : BR->referenced_vars())
2849 AddToWorkList(Var.getCapturedRegion());
2856 SymReaper.markLive(Sym);
2859bool RemoveDeadBindingsWorker::UpdatePostponed() {
2865 if (SymReaper.isLive(SR->getSymbol())) {
2877 RegionBindingsRef B = getRegionBindings(store);
2878 RemoveDeadBindingsWorker W(*
this, StateMgr, B, SymReaper, LCtx);
2879 W.GenerateClusters();
2883 W.AddToWorkList(Reg);
2886 do W.RunWorkList();
while (W.UpdatePostponed());
2894 if (!W.isVisited(
Base))
2898 return StoreRef(B.asStore(), *
this);
2905void RegionStoreManager::printJson(raw_ostream &Out,
Store S,
const char *NL,
2906 unsigned int Space,
bool IsDot)
const {
2907 RegionBindingsRef
Bindings = getRegionBindings(S);
2909 Indent(Out, Space, IsDot) <<
"\"store\": ";
2912 Out <<
"null," << NL;
2916 Out <<
"{ \"pointer\": \"" <<
Bindings.asStore() <<
"\", \"items\": [" << NL;
2917 Bindings.printJson(Out, NL, Space + 1, IsDot);
2918 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)
static bool isRecordEmpty(const RecordDecl *RD)
SmallVector< const FieldDecl *, 8 > FieldVector
llvm::ImmutableMap< BindingKey, SVal > ClusterBindings
static bool isUnionField(const FieldRegion *FR)
static void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields)
static QualType getUnderlyingType(const SubRegion *R)
llvm::ImmutableMapRef< BindingKey, SVal > ClusterBindingsRef
static SmallVector< uint64_t, 2 > getConstantArrayExtents(const ConstantArrayType *CAT)
This is a helper function for getConstantValFromConstArrayInitializer.
static std::pair< SmallVector< SVal, 2 >, const MemRegion * > getElementRegionOffsetsWithBase(const ElementRegion *ER)
This is a helper function for getConstantValFromConstArrayInitializer.
const RegionBindingsRef & RegionBindingsConstRef
static std::optional< nonloc::LazyCompoundVal > getExistingLazyBinding(SValBuilder &SVB, RegionBindingsConstRef B, const SubRegion *R, bool AllowSubregionBindings)
Checks to see if store B has a lazy binding for region R.
static void collectSubRegionBindings(SmallVectorImpl< BindingPair > &Bindings, SValBuilder &SVB, const ClusterBindings &Cluster, const SubRegion *Top, BindingKey TopKey, bool IncludeAllDefaultBindings)
Collects all bindings in Cluster that may refer to bindings within Top.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
__PTRDIFF_TYPE__ ptrdiff_t
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
Stores options for the analyzer from the command line.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Represents a C++ struct/union/class.
Represents the canonical version of C arrays with a specified constant size.
uint64_t getLimitedSize() const
Return the size zero-extended to uint64_t or UINT64_MAX if the value is larger than UINT64_MAX.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
This represents one expression.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
Describes an C or C++ initializer list.
bool isStringLiteralInit() const
Is this an initializer for an array of characters, initialized by a string literal or an @encode?
unsigned getNumInits() const
const Expr * getInit(unsigned Init) const
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
bool isParentOf(const LocationContext *LC) const
const Decl * getDecl() const
const StackFrameContext * getStackFrame() const
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool isConstQualified() const
Determine whether this type is const-qualified.
Represents a struct/union/class.
field_range fields() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
It represents a stack frame of the call stack (based on CallEvent).
StringLiteral - This represents a string literal expression, e.g.
unsigned getLength() const
uint32_t getCodeUnit(size_t i) const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool isVoidPointerType() const
const T * castAs() const
Member-template castAs<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 isAnyComplexType() const
QualType getCanonicalTypeInternal() const
bool isStructureOrClassType() const
bool isVectorType() const
bool isRecordType() const
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
Maps string IDs to AST nodes matched by parts of a matcher.
AnalyzerOptions & options
BlockDataRegion - A region that represents a block instance.
CXXThisRegion - Represents the region for the implicit 'this' parameter in a call to a C++ method.
Represents an abstract call to a function or method along a particular path.
ElementRegion is used to represent both array elements and casts.
QualType getElementType() const
RegionRawOffset getAsArrayOffset() const
Compute the offset within the array. The array might also be a subobject.
AnalysisManager & getAnalysisManager()
LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override
static bool isLocType(QualType T)
DefinedOrUnknownSVal getStaticSize(const MemRegion *MR, SValBuilder &SVB) const
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() const
virtual bool isBoundable() const
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
bool hasStackNonParametersStorage() const
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
Information about invalidation for a particular region/symbol.
@ TK_PreserveContents
Tells that a region's contents is not changed.
@ TK_DoNotInvalidateSuperRegion
@ TK_EntireMemSpace
When applied to a MemSpaceRegion, indicates the entire memory space should be invalidated.
Represent a region's offset within the top level base region.
bool hasSymbolicOffset() const
const MemRegion * getRegion() const
It might return null.
int64_t getOffset() const
const MemRegion * getRegion() const
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
NonLoc makeArrayIndex(uint64_t idx)
ASTContext & getContext()
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy)
Cast a given SVal to another SVal using given QualType's.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, const TypedValueRegion *region)
loc::ConcreteInt makeNullWithType(QualType type)
Create NULL pointer, with proper pointer bit-width for given address space.
std::optional< SVal > getConstantVal(const Expr *E)
Returns the value of E, if it can be determined in a non-path-sensitive manner.
NonLoc makeZeroArrayIndex()
DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region)
Make a unique symbol for value of region.
NonLoc makeLazyCompoundVal(const StoreRef &store, const TypedValueRegion *region)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
bool isZeroConstant() const
bool isUnknownOrUndef() const
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
A utility class that visits the reachable symbols using a custom SymbolVisitor.
bool scan(nonloc::LazyCompoundVal val)
virtual bool scanReachableSymbols(Store S, const MemRegion *R, ScanReachableSymbols &Visitor)=0
Finds the transitive closure of symbols within the given region.
virtual void iterBindings(Store store, BindingsHandler &f)=0
iterBindings - Iterate over the bindings in the Store.
virtual StoreRef getInitialStore(const LocationContext *InitLoc)=0
getInitialStore - Returns the initial "empty" store representing the value bindings upon entry to an ...
virtual StoreRef BindDefaultZero(Store store, const MemRegion *R)=0
Return a store with in which all values within the given region are reset to zero.
virtual std::optional< SVal > getDefaultBinding(Store store, const MemRegion *R)=0
Return the default value bound to a region in a given store.
virtual StoreRef killBinding(Store ST, Loc L)=0
Create a new store with the specified binding removed.
virtual void decrementReferenceCount(Store store)
If the StoreManager supports it, decrement the reference count of the specified Store object.
virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx, SymbolReaper &SymReaper)=0
virtual StoreRef invalidateRegions(Store store, ArrayRef< SVal > Values, const Expr *Ex, 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 void incrementReferenceCount(Store store)
If the StoreManager supports it, increment the reference count of the specified Store object.
virtual SVal ArrayToPointer(Loc Array, QualType ElementTy)=0
ArrayToPointer - Used by ExprEngine::VistCast to handle implicit conversions between arrays and point...
virtual bool includedInBindings(Store store, const MemRegion *region) const =0
virtual SVal getBinding(Store store, Loc loc, QualType T=QualType())=0
Return the value bound to specified location in a given state.
virtual StoreRef BindDefaultInitial(Store store, const MemRegion *R, SVal V)=0
Return a store with the specified value bound to all sub-regions of the region.
virtual void printJson(raw_ostream &Out, Store S, const char *NL, unsigned int Space, bool IsDot) const =0
StringRegion - Region associated with a StringLiteral.
SubRegion - A region that subsets another larger region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
bool isSubRegionOf(const MemRegion *R) const override
Check if the region is a subregion of the given region.
MemRegionManager & getMemRegionManager() const override
static bool canSymbolicate(QualType T)
A class responsible for cleaning up unused symbols.
llvm::iterator_range< RegionSetTy::const_iterator > regions() const
SymbolicRegion - A special, "non-concrete" region.
TypedRegion - An abstract class representing regions that are typed.
TypedValueRegion - An abstract class representing regions having a typed value.
virtual QualType getValueType() const =0
QualType getLocationType() const override
QualType getValueType() const override
const VarDecl * getDecl() const override=0
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getRegion() const
Get the underlining region.
The simplest example of a concrete compound value is nonloc::CompoundVal, which represents a concrete...
llvm::ImmutableList< SVal >::iterator iterator
Value representing integer constant.
While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...
LLVM_ATTRIBUTE_RETURNS_NONNULL const LazyCompoundValData * getCVData() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
This function itself is immaterial.
const void * getStore() const
It might return null.
Defines the clang::TargetInfo interface.
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, DeclRefExpr > declRefExpr
Matches expressions that refer to declarations.
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< Stmt > StatementMatcher
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
The JSON file list parser is used to communicate input to InstallAPI.
@ Bind
'bind' clause, allowed on routine constructs.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Diagnostic wrappers for TextAPI types for error reporting.
static raw_ostream & operator<<(raw_ostream &Out, BindingKey K)
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...