30#include "llvm/ADT/ImmutableMap.h"
31#include "llvm/Support/raw_ostream.h"
47 enum { Symbolic = 0x2 };
49 llvm::PointerIntPair<const MemRegion *, 2>
P;
56 assert(r &&
Base &&
"Must have known regions.");
57 assert(getConcreteOffsetRegion() ==
Base &&
"Failed to store base region");
61 explicit BindingKey(
const MemRegion *r, uint64_t offset, Kind k)
62 :
P(r, k),
Data(offset) {
63 assert(r &&
"Must have known regions.");
64 assert(getOffset() == offset &&
"Failed to store offset");
66 isa<ObjCIvarRegion, CXXDerivedObjectRegion>(r)) &&
71 bool isDirect()
const {
return P.getInt() & Direct; }
72 bool hasSymbolicOffset()
const {
return P.getInt() & Symbolic; }
74 const MemRegion *getRegion()
const {
return P.getPointer(); }
76 assert(!hasSymbolicOffset());
80 const SubRegion *getConcreteOffsetRegion()
const {
81 assert(hasSymbolicOffset());
86 if (hasSymbolicOffset())
91 void Profile(llvm::FoldingSetNodeID& ID)
const {
92 ID.AddPointer(
P.getOpaqueValue());
99 if (
P.getOpaqueValue() <
X.P.getOpaqueValue())
101 if (
P.getOpaqueValue() >
X.P.getOpaqueValue())
103 return Data <
X.Data;
107 return P.getOpaqueValue() ==
X.P.getOpaqueValue() &&
111 LLVM_DUMP_METHOD
void dump()
const;
115BindingKey BindingKey::Make(
const MemRegion *R, Kind k) {
118 return BindingKey(cast<SubRegion>(R), cast<SubRegion>(RO.
getRegion()), k);
124static inline raw_ostream &
operator<<(raw_ostream &Out, BindingKey K) {
125 Out <<
"\"kind\": \"" << (K.isDirect() ?
"Direct" :
"Default")
126 <<
"\", \"offset\": ";
128 if (!K.hasSymbolicOffset())
129 Out << K.getOffset();
138#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
139void BindingKey::dump()
const { llvm::errs() << *
this; }
150typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
154class RegionBindingsRef :
public llvm::ImmutableMapRef<const MemRegion *,
156 ClusterBindings::Factory *CBFactory;
170 typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
173 RegionBindingsRef(ClusterBindings::Factory &CBFactory,
174 const RegionBindings::TreeTy *T,
175 RegionBindings::TreeTy::Factory *F,
177 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(T, F),
178 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
180 RegionBindingsRef(
const ParentTy &
P,
181 ClusterBindings::Factory &CBFactory,
183 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(
P),
184 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
186 RegionBindingsRef add(key_type_ref K, data_type_ref D)
const {
187 return RegionBindingsRef(
static_cast<const ParentTy *
>(
this)->add(K, D),
188 *CBFactory, IsMainAnalysis);
191 RegionBindingsRef remove(key_type_ref K)
const {
192 return RegionBindingsRef(
static_cast<const ParentTy *
>(
this)->remove(K),
193 *CBFactory, IsMainAnalysis);
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 for (iterator I = begin(); I != end(); ++I) {
236 Indent(Out, Space, IsDot)
237 <<
"{ \"cluster\": \"" << I.getKey() <<
"\", \"pointer\": \""
238 << (
const void *)I.getKey() <<
"\", \"items\": [" << NL;
242 for (ClusterBindings::iterator CI = CB.begin(); CI != CB.end(); ++CI) {
243 Indent(Out, Space, IsDot) <<
"{ " << CI.getKey() <<
", \"value\": ";
244 CI.getData().printJson(Out,
true);
246 if (std::next(CI) != CB.end())
252 Indent(Out, Space, IsDot) <<
"]}";
253 if (std::next(I) != end())
259 LLVM_DUMP_METHOD
void dump()
const { printJson(llvm::errs()); }
266RegionBindingsRef::getDirectBinding(
const MemRegion *R)
const {
267 const SVal *
V = lookup(R, BindingKey::Direct);
268 return V ? std::optional<SVal>(*
V) : std::nullopt;
272RegionBindingsRef::getDefaultBinding(
const MemRegion *R)
const {
273 const SVal *
V = lookup(R, BindingKey::Default);
274 return V ? std::optional<SVal>(*
V) :
std::nullopt;
277RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K,
SVal V)
const {
282 (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
285 return add(
Base, NewCluster);
289RegionBindingsRef RegionBindingsRef::addBinding(
const MemRegion *R,
292 return addBinding(BindingKey::Make(R, k),
V);
295const SVal *RegionBindingsRef::lookup(BindingKey K)
const {
299 return Cluster->lookup(K);
303 BindingKey::Kind k)
const {
304 return lookup(BindingKey::Make(R, k));
307RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
314 if (NewCluster.isEmpty())
316 return add(
Base, NewCluster);
319RegionBindingsRef RegionBindingsRef::removeBinding(
const MemRegion *R,
321 return removeBinding(BindingKey::Make(R, k));
329class InvalidateRegionsWorker;
333 RegionBindings::Factory RBFactory;
334 mutable ClusterBindings::Factory CBFactory;
336 typedef std::vector<SVal> SValListTy;
339 SValListTy> LazyBindingsMapTy;
340 LazyBindingsMapTy LazyBindingsMap;
350 unsigned SmallStructLimit;
360 unsigned SmallArrayLimit;
364 void populateWorkList(InvalidateRegionsWorker &W,
366 InvalidatedRegions *TopLevelRegions);
371 CBFactory(mgr.getAllocator()), SmallStructLimit(0), SmallArrayLimit(0) {
374 SmallStructLimit = Options.RegionStoreSmallStructLimit;
375 SmallArrayLimit = Options.RegionStoreSmallArrayLimit;
395 bool IsMainAnalysis =
false;
396 if (
const auto *FD = dyn_cast<FunctionDecl>(InitLoc->
getDecl()))
397 IsMainAnalysis = FD->isMain() && !Ctx.getLangOpts().CPlusPlus;
399 RegionBindingsRef::ParentTy(RBFactory.getEmptyMap(), RBFactory),
400 CBFactory, IsMainAnalysis).asStore(), *
this);
411 InvalidatedRegions *Invalidated);
415 const Expr *E,
unsigned Count,
420 InvalidatedRegions *Invalidated,
421 InvalidatedRegions *InvalidatedTopLevel)
override;
441 return StoreRef(bind(getRegionBindings(store), LV,
V).asStore(), *
this);
450 RegionBindingsRef B = getRegionBindings(store);
453 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
454 "Double initialization!");
455 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
456 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this);
471 if (
const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
472 if (BR->getDecl()->isEmpty())
475 RegionBindingsRef B = getRegionBindings(store);
476 SVal V = svalBuilder.makeZeroVal(Ctx.CharTy);
477 B = removeSubRegionBindings(B, cast<SubRegion>(R));
478 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
479 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this);
492 std::optional<RegionBindingsRef>
504 std::optional<RegionBindingsRef>
524 getRegionBindings(store).manualRetain();
531 getRegionBindings(store).manualRelease();
550 return getBinding(getRegionBindings(S), L, T);
554 RegionBindingsRef B = getRegionBindings(S);
578 RegionBindingsRef LazyBinding);
603 std::pair<Store, const SubRegion *>
632 RegionBindingsRef getRegionBindings(
Store store)
const {
633 llvm::PointerIntPair<Store, 1, bool> Ptr;
634 Ptr.setFromOpaqueValue(
const_cast<void *
>(store));
635 return RegionBindingsRef(
637 static_cast<const RegionBindings::TreeTy *
>(Ptr.getPointer()),
638 RBFactory.getTreeFactory(),
643 unsigned int Space = 0,
bool IsDot =
false)
const override;
646 RegionBindingsRef B = getRegionBindings(store);
647 for (RegionBindingsRef::iterator I = B.begin(), E = B.end(); I != E; ++I) {
649 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
651 const BindingKey &K = CI.getKey();
654 if (
const SubRegion *R = dyn_cast<SubRegion>(K.getRegion())) {
656 if (!f.HandleBinding(*
this, store, R, CI.getData()))
670std::unique_ptr<StoreManager>
672 return std::make_unique<RegionStoreManager>(StMgr);
682enum GlobalsFilterKind {
691template <
typename DERIVED>
692class ClusterAnalysis {
694 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
695 typedef const MemRegion * WorkListElement;
702 RegionStoreManager &RM;
724 : RM(rm), Ctx(StateMgr.getContext()),
725 svalBuilder(StateMgr.getSValBuilder()), B(
std::move(
b)) {}
727 RegionBindingsRef getRegionBindings()
const {
return B; }
730 return Visited.count(getCluster(R));
733 void GenerateClusters() {
735 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
740 assert(!Cluster.isEmpty() &&
"Empty clusters should be removed");
741 static_cast<DERIVED*
>(
this)->VisitAddedToCluster(
Base, Cluster);
745 if (
static_cast<DERIVED*
>(
this)->includeEntireMemorySpace(
Base))
746 AddToWorkList(WorkListElement(
Base), &Cluster);
751 if (
C && !Visited.insert(
C).second)
758 return static_cast<DERIVED*
>(
this)->AddToWorkList(R);
762 while (!WL.empty()) {
763 WorkListElement E = WL.pop_back_val();
766 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR, getCluster(BaseR));
775 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR,
C);
784bool RegionStoreManager::scanReachableSymbols(
Store S,
const MemRegion *R,
786 assert(R == R->
getBaseRegion() &&
"Should only be called for base regions");
787 RegionBindingsRef B = getRegionBindings(S);
793 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
795 if (!Callbacks.
scan(RI.getData()))
809 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
815 if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R))
817 Fields.push_back(FR->getDecl());
819 R = cast<SubRegion>(R)->getSuperRegion();
824 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
832 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
834 return std::equal(FieldsInBindingKey.begin() + Delta,
835 FieldsInBindingKey.end(),
838 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
839 Fields.begin() - Delta);
855 bool IncludeAllDefaultBindings) {
857 if (TopKey.hasSymbolicOffset()) {
859 Top = TopKey.getConcreteOffsetRegion();
860 TopKey = BindingKey::Make(Top, BindingKey::Default);
864 uint64_t Length = UINT64_MAX;
866 if (std::optional<nonloc::ConcreteInt> ExtentCI =
868 const llvm::APSInt &ExtentInt = ExtentCI->getValue();
869 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
872 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
873 if (FR->getDecl()->isBitField())
874 Length = FR->getDecl()->getBitWidthValue(SVB.
getContext());
877 for (ClusterBindings::iterator I = Cluster.begin(), E = Cluster.end();
879 BindingKey NextKey = I.getKey();
880 if (NextKey.getRegion() == TopKey.getRegion()) {
886 if (NextKey.getOffset() > TopKey.getOffset() &&
887 NextKey.getOffset() - TopKey.getOffset() < Length) {
892 }
else if (NextKey.getOffset() == TopKey.getOffset()) {
899 if (IncludeAllDefaultBindings || NextKey.isDirect())
903 }
else if (NextKey.hasSymbolicOffset()) {
909 if (IncludeAllDefaultBindings || NextKey.isDirect())
912 }
else if (
const SubRegion *BaseSR = dyn_cast<SubRegion>(
Base)) {
915 if (BaseSR->isSubRegionOf(Top))
926 const SubRegion *Top,
bool IncludeAllDefaultBindings) {
928 BindingKey::Make(Top, BindingKey::Default),
929 IncludeAllDefaultBindings);
935 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
938 if (Top == ClusterHead) {
940 return B.remove(Top);
947 if (TopKey.hasSymbolicOffset()) {
948 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
949 return B.addBinding(Concrete, BindingKey::Default,
UnknownVal());
962 Result = Result.remove(I->first);
968 if (TopKey.hasSymbolicOffset()) {
969 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
970 Result = Result.
add(BindingKey::Make(Concrete, BindingKey::Default),
974 if (Result.isEmpty())
975 return B.remove(ClusterHead);
976 return B.add(ClusterHead, Result.asImmutableMap());
980class InvalidateRegionsWorker :
public ClusterAnalysis<InvalidateRegionsWorker>
988 GlobalsFilterKind GlobalsFilter;
990 InvalidateRegionsWorker(RegionStoreManager &rm,
993 const Expr *ex,
unsigned count,
998 GlobalsFilterKind GFK)
999 : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr,
b),
1000 Ex(ex), Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
1001 GlobalsFilter(GFK) {}
1004 void VisitBinding(
SVal V);
1006 using ClusterAnalysis::AddToWorkList;
1016 bool isInitiallyIncludedGlobalRegion(
const MemRegion *R);
1020bool InvalidateRegionsWorker::AddToWorkList(
const MemRegion *R) {
1021 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1024 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
1027void InvalidateRegionsWorker::VisitBinding(
SVal V) {
1038 if (std::optional<nonloc::LazyCompoundVal> LCS =
1043 for (
SVal V : RM.getInterestingValues(*LCS))
1044 if (!isa<nonloc::LazyCompoundVal>(
V))
1051void InvalidateRegionsWorker::VisitCluster(
const MemRegion *baseR,
1054 bool PreserveRegionsContents =
1055 ITraits.hasTrait(baseR,
1059 for (ClusterBindings::iterator I =
C->begin(), E =
C->end(); I != E; ++I)
1060 VisitBinding(I.getData());
1063 if (!PreserveRegionsContents)
1064 B = B.remove(baseR);
1067 if (
const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
1068 if (
const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
1073 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
1074 using namespace ast_matchers;
1076 const char *DeclBind =
"DeclBind";
1078 to(
varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
1080 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
1081 RD->getASTContext());
1084 auto *VD = Match.getNodeAs<
VarDecl>(DeclBind);
1086 RM.getRegionManager().getVarRegion(VD, LCtx);
1087 AddToWorkList(ToInvalidate);
1097 BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ;
1099 const VarRegion *VR = BI.getCapturedRegion();
1111 if (std::optional<Loc> L =
V.getAs<
Loc>()) {
1122 IS.insert(SR->getSymbol());
1125 if (PreserveRegionsContents)
1130 Regions->push_back(baseR);
1132 if (isa<AllocaRegion, SymbolicRegion>(baseR)) {
1137 B = B.addBinding(baseR, BindingKey::Default,
V);
1147 if (isInitiallyIncludedGlobalRegion(baseR)) {
1159 B = B.addBinding(baseR, BindingKey::Default,
V);
1164 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1168 if (doNotInvalidateSuperRegion) {
1171 std::optional<uint64_t> NumElements;
1175 NumElements = CAT->getSize().getZExtValue();
1177 goto conjure_default;
1178 QualType ElementTy = AT->getElementType();
1186 AddToWorkList(SuperR);
1187 goto conjure_default;
1191 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
1192 bool UpperOverflow = UpperOffset < LowerOffset;
1197 goto conjure_default;
1201 goto conjure_default;
1203 for (ClusterBindings::iterator I =
C->begin(), E =
C->end(); I != E;
1205 const BindingKey &BK = I.getKey();
1206 std::optional<uint64_t> ROffset =
1207 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
1212 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
1214 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
1215 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
1216 B = B.removeBinding(I.getKey());
1219 SVal V = I.getData();
1221 if (isa_and_nonnull<SymbolicRegion>(R))
1230 AT->getElementType(), Count);
1231 B = B.addBinding(baseR, BindingKey::Default,
V);
1238 B = B.addBinding(baseR, BindingKey::Direct,
V);
1241bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
1243 switch (GlobalsFilter) {
1246 case GFK_SystemOnly:
1252 llvm_unreachable(
"unknown globals filter");
1255bool InvalidateRegionsWorker::includeEntireMemorySpace(
const MemRegion *
Base) {
1256 if (isInitiallyIncludedGlobalRegion(
Base))
1260 return ITraits.hasTrait(MemSpace,
1269 RegionBindingsRef B,
1270 InvalidatedRegions *Invalidated) {
1278 B = B.removeBinding(GS)
1279 .addBinding(BindingKey::Make(GS, BindingKey::Default),
V);
1284 Invalidated->push_back(GS);
1289void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
1291 InvalidatedRegions *TopLevelRegions) {
1293 E = Values.end(); I != E; ++I) {
1295 if (std::optional<nonloc::LazyCompoundVal> LCS =
1298 for (
SVal S : getInterestingValues(*LCS))
1299 if (
const MemRegion *R = S.getAsRegion())
1306 if (TopLevelRegions)
1307 TopLevelRegions->push_back(R);
1315RegionStoreManager::invalidateRegions(
Store store,
1317 const Expr *Ex,
unsigned Count,
1322 InvalidatedRegions *TopLevelRegions,
1323 InvalidatedRegions *Invalidated) {
1324 GlobalsFilterKind GlobalsFilter;
1326 if (
Call->isInSystemHeader())
1327 GlobalsFilter = GFK_SystemOnly;
1329 GlobalsFilter = GFK_All;
1331 GlobalsFilter = GFK_None;
1334 RegionBindingsRef B = getRegionBindings(store);
1335 InvalidateRegionsWorker W(*
this, StateMgr, B, Ex, Count, LCtx, IS, ITraits,
1336 Invalidated, GlobalsFilter);
1339 W.GenerateClusters();
1342 populateWorkList(W, Values, TopLevelRegions);
1347 B = W.getRegionBindings();
1353 switch (GlobalsFilter) {
1355 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
1356 Ex, Count, LCtx, B, Invalidated);
1358 case GFK_SystemOnly:
1359 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
1360 Ex, Count, LCtx, B, Invalidated);
1366 return StoreRef(B.asStore(), *
this);
1380 if (isa<loc::ConcreteInt>(Array))
1383 if (!isa<loc::MemRegionVal>(Array))
1397 assert(!isa<UnknownVal>(L) &&
"location unknown");
1398 assert(!isa<UndefinedVal>(L) &&
"location undefined");
1415 if (isa<BlockDataRegion>(MR)) {
1421 if (
const auto *TVR = dyn_cast<TypedValueRegion>(MR))
1422 T = TVR->getValueType();
1423 else if (
const auto *TR = dyn_cast<TypedRegion>(MR))
1425 else if (
const auto *SR = dyn_cast<SymbolicRegion>(MR))
1426 T = SR->getPointeeStaticType();
1428 assert(!T.
isNull() &&
"Unable to auto-detect binding type!");
1429 assert(!T->
isVoidType() &&
"Attempting to dereference a void pointer!");
1431 if (!isa<TypedValueRegion>(MR))
1432 MR = GetElementZeroRegion(cast<SubRegion>(MR), T);
1453 return getBindingForStruct(B, R);
1457 return createLazyBinding(B, R);
1461 return getBindingForArray(B, R);
1470 if (
const FieldRegion* FR = dyn_cast<FieldRegion>(R))
1492 if (
const VarRegion *VR = dyn_cast<VarRegion>(R)) {
1502 const SVal *
V = B.lookup(R, BindingKey::Direct);
1526 RegionTy = TVR->getValueType();
1529 RegionTy = SR->getSymbol()->getType();
1541static std::optional<nonloc::LazyCompoundVal>
1543 const SubRegion *R,
bool AllowSubregionBindings) {
1544 std::optional<SVal>
V = B.getDefaultBinding(R);
1546 return std::nullopt;
1548 std::optional<nonloc::LazyCompoundVal> LCV =
1551 return std::nullopt;
1556 if (!RegionTy.
isNull() &&
1558 QualType SourceRegionTy = LCV->getRegion()->getValueType();
1560 return std::nullopt;
1563 if (!AllowSubregionBindings) {
1570 return std::nullopt;
1576std::pair<Store, const SubRegion *>
1580 if (originalRegion != R) {
1581 if (std::optional<nonloc::LazyCompoundVal>
V =
1583 return std::make_pair(
V->getStore(),
V->getRegion());
1586 typedef std::pair<Store, const SubRegion *> StoreRegionPair;
1587 StoreRegionPair Result = StoreRegionPair();
1590 Result = findLazyBinding(B, cast<SubRegion>(ER->getSuperRegion()),
1594 Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);
1596 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
1597 Result = findLazyBinding(B, cast<SubRegion>(FR->getSuperRegion()),
1601 Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);
1604 dyn_cast<CXXBaseObjectRegion>(R)) {
1607 Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
1611 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
1625 assert(CAT &&
"ConstantArrayType should not be null");
1629 Extents.push_back(CAT->
getSize().getZExtValue());
1630 }
while ((CAT = dyn_cast<ConstantArrayType>(CAT->
getElementType())));
1648static std::pair<SmallVector<SVal, 2>,
const MemRegion *>
1650 assert(ER &&
"ConstantArrayType should not be null");
1654 SValOffsets.push_back(ER->
getIndex());
1656 ER = dyn_cast<ElementRegion>(
Base);
1658 return {SValOffsets,
Base};
1682static std::optional<SVal>
1703 DstOffsets.resize(SrcOffsets.size());
1704 auto ExtentIt = ArrayExtents.begin();
1705 auto OffsetIt = DstOffsets.begin();
1707 for (
SVal V : llvm::reverse(SrcOffsets)) {
1710 const llvm::APSInt &
Offset = CI->getValue();
1714 *(OffsetIt++) =
Offset.getZExtValue();
1722 return std::nullopt;
1725std::optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer(
1727 assert(R &&
"ElementRegion should not be null");
1735 return std::nullopt;
1737 assert(!SValOffsets.empty() &&
"getElementRegionOffsets guarantees the "
1738 "offsets vector is not empty.");
1746 return std::nullopt;
1761 return std::nullopt;
1767 return std::nullopt;
1778 if (SValOffsets.size() != Extents.size())
1779 return std::nullopt;
1783 SValOffsets, Extents, ConcreteOffsets))
1789 if (
const auto *ILE = dyn_cast<InitListExpr>(Init))
1790 return getSValFromInitListExpr(ILE, ConcreteOffsets, R->
getElementType());
1795 if (
const auto *SL = dyn_cast<StringLiteral>(Init))
1796 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
1801 return std::nullopt;
1821std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
1824 assert(ILE &&
"InitListExpr should not be null");
1826 for (uint64_t
Offset : Offsets) {
1833 if (
const auto *SL = dyn_cast<StringLiteral>(ILE->
getInit(0)))
1834 return getSValFromStringLiteral(SL,
Offset, ElemT);
1843 const auto *IL = dyn_cast<InitListExpr>(E);
1853 "Unhandled InitListExpr sub-expressions or invalid offsets.");
1884 assert(SL &&
"StringLiteral should not be null");
1900 if (
const std::optional<SVal> &ParentValue =
1901 B.getDirectBinding(BaseRegion)) {
1902 if (
SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
1905 if (ParentValue->isUndef())
1914 return std::nullopt;
1920 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
1926 if (
const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
1934 const llvm::APSInt &Idx = CI->getValue();
1938 return getSValFromStringLiteral(SL, Idx.getZExtValue(), T);
1940 }
else if (isa<ElementRegion, VarRegion>(superR)) {
1941 if (std::optional<SVal>
V = getConstantValFromConstArrayInitializer(B, R))
1946 if (isa<CodeTextRegion>(superR))
1965 return getBindingForFieldOrElementCommon(B, R, R->
getElementType());
1972 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
1979 if (
const auto *VR = dyn_cast<VarRegion>(superR)) {
1989 if (
const auto *InitList = dyn_cast<InitListExpr>(Init)) {
1990 if (Index < InitList->getNumInits()) {
1991 if (
const Expr *FieldInit = InitList->getInit(Index))
2020 return getBindingForFieldOrElementCommon(B, R, Ty);
2023std::optional<SVal> RegionStoreManager::getBindingForDerivedDefaultValue(
2027 if (
const std::optional<SVal> &D = B.getDefaultBinding(superR)) {
2028 const SVal &val = *D;
2040 if (isa<nonloc::LazyCompoundVal, nonloc::CompoundVal>(val))
2043 llvm_unreachable(
"Unknown default value");
2046 return std::nullopt;
2049SVal RegionStoreManager::getLazyBinding(
const SubRegion *LazyBindingRegion,
2050 RegionBindingsRef LazyBinding) {
2052 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
2053 Result = getBindingForElement(LazyBinding, ER);
2055 Result = getBindingForField(LazyBinding,
2056 cast<FieldRegion>(LazyBindingRegion));
2072 if (Result.isUndef())
2087 Store lazyBindingStore =
nullptr;
2088 const SubRegion *lazyBindingRegion =
nullptr;
2089 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
2090 if (lazyBindingRegion)
2091 return getLazyBinding(lazyBindingRegion,
2092 getRegionBindings(lazyBindingStore));
2096 bool hasSymbolicIndex =
false;
2112 bool hasPartialLazyBinding =
false;
2117 if (std::optional<SVal> D =
2118 getBindingForDerivedDefaultValue(B,
Base, R, Ty)) {
2120 hasPartialLazyBinding =
true;
2128 NonLoc index = ER->getIndex();
2130 hasSymbolicIndex =
true;
2135 SR = dyn_cast<SubRegion>(
Base);
2139 if (isa<ElementRegion>(R)) {
2144 if (typedSuperR->getValueType()->isVectorType())
2153 if (hasSymbolicIndex)
2159 if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->
getBaseRegion())) {
2160 if (
const std::optional<SVal> &
V = B.getDefaultBinding(R))
2173 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2179 if (
const std::optional<SVal> &
V = B.getDefaultBinding(superR)) {
2187 return getBindingForLazySymbol(R);
2194 if (std::optional<SVal>
V = B.getDirectBinding(R))
2197 if (std::optional<SVal>
V = B.getDefaultBinding(R))
2205 if (isa<StackArgumentsSpaceRegion>(MS))
2223 if (isa<UnknownSpaceRegion>(MS))
2226 if (isa<GlobalsSpaceRegion>(MS)) {
2230 if (B.isMainAnalysis())
2239 if (isa<StaticGlobalSpaceRegion>(MS))
2242 if (std::optional<SVal>
V = getBindingForDerivedDefaultValue(B, MS, R, T)) {
2258const RegionStoreManager::SValListTy &
2261 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.
getCVData());
2262 if (I != LazyBindingsMap.end())
2269 RegionBindingsRef B = getRegionBindings(LCV.
getStore());
2275 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2284 if (
V.isUnknownOrUndef() ||
V.isConstant())
2288 const SValListTy &InnerList = getInterestingValues(*InnerLCV);
2289 List.insert(List.end(), InnerList.begin(), InnerList.end());
2295 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2300 if (std::optional<nonloc::LazyCompoundVal>
V =
2311 return CRD->getNumBases() == 0;
2321 return createLazyBinding(B, R);
2327 "Only constant array types can have compound bindings.");
2329 return createLazyBinding(B, R);
2332bool RegionStoreManager::includedInBindings(
Store store,
2334 RegionBindingsRef B = getRegionBindings(store);
2338 if (B.lookup(region))
2342 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
2344 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
2346 const SVal &D = CI.getData();
2362 if (
const MemRegion* R = LV->getRegion())
2363 return StoreRef(getRegionBindings(ST).removeBinding(R)
2365 .getRootWithoutRetain(),
2383 return bindArray(B, TR,
V);
2385 return bindStruct(B, TR,
V);
2387 return bindVector(B, TR,
V);
2389 return bindAggregate(B, TR,
V);
2395 R = GetElementZeroRegion(SR, SR->getPointeeStaticType());
2397 assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
2398 "'this' pointer is not an l-value and is not assignable");
2401 RegionBindingsRef NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
2404 auto KeyKind = isa<nonloc::LazyCompoundVal>(
V) ? BindingKey::Default
2405 : BindingKey::Direct;
2406 return NewB.addBinding(BindingKey::Make(R, KeyKind),
V);
2433 return B.addBinding(R, BindingKey::Default,
V);
2436std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallArray(
2440 auto CAT = dyn_cast<ConstantArrayType>(AT);
2444 return std::nullopt;
2448 return std::nullopt;
2452 if (ArrSize > SmallArrayLimit)
2453 return std::nullopt;
2455 RegionBindingsRef NewB = B;
2457 for (uint64_t i = 0; i < ArrSize; ++i) {
2460 MRMgr.getElementRegion(Ty, Idx, LCV.
getRegion(), Ctx);
2461 SVal V = getBindingForElement(getRegionBindings(LCV.
getStore()), SrcER);
2463 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2477 std::optional<uint64_t>
Size;
2487 return bindAggregate(B, R,
V);
2491 if (std::optional<nonloc::LazyCompoundVal> LCV =
2493 if (std::optional<RegionBindingsRef> NewB =
2494 tryBindSmallArray(B, R, AT, *LCV))
2497 return bindAggregate(B, R, Init);
2500 if (Init.isUnknown())
2508 RegionBindingsRef NewB(B);
2510 for (;
Size ? i < *
Size :
true; ++i, ++VI) {
2516 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2519 NewB = bindStruct(NewB, ER, *VI);
2521 NewB = bindArray(NewB, ER, *VI);
2529 if (!Size || i < *Size)
2530 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2542 if (isa<nonloc::LazyCompoundVal, nonloc::SymbolVal>(
V))
2543 return bindAggregate(B, R,
V);
2548 if (!isa<nonloc::CompoundVal>(
V)) {
2556 RegionBindingsRef NewB(B);
2558 for ( ; index != numElements ; ++index) {
2563 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2566 NewB = bindArray(NewB, ER, *VI);
2568 NewB = bindStruct(NewB, ER, *VI);
2575std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
2580 if (
const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
2581 if (
Class->getNumBases() != 0 ||
Class->getNumVBases() != 0)
2582 return std::nullopt;
2584 for (
const auto *FD : RD->
fields()) {
2590 if (Fields.size() == SmallStructLimit)
2591 return std::nullopt;
2601 return std::nullopt;
2603 Fields.push_back(FD);
2606 RegionBindingsRef NewB = B;
2608 for (FieldVector::iterator I = Fields.begin(), E = Fields.end(); I != E; ++I){
2610 SVal V = getBindingForField(getRegionBindings(LCV.
getStore()), SourceFR);
2612 const FieldRegion *DestFR = MRMgr.getFieldRegion(*I, R);
2628 if (!RD->isCompleteDefinition())
2632 if (std::optional<nonloc::LazyCompoundVal> LCV =
2634 if (std::optional<RegionBindingsRef> NewB =
2635 tryBindSmallStruct(B, R, RD, *LCV))
2637 return bindAggregate(B, R,
V);
2639 if (isa<nonloc::SymbolVal>(
V))
2640 return bindAggregate(B, R,
V);
2645 if (
V.isUnknown() || !isa<nonloc::CompoundVal>(
V))
2667 RegionBindingsRef NewB(B);
2671 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
2679 assert((CRD->isAggregate() || (Ctx.
getLangOpts().ObjC && VI == VE)) &&
2680 "Non-aggregates are constructed with a constructor!");
2682 for (
const auto &B : CRD->bases()) {
2684 assert(!B.isVirtual() &&
"Aggregates cannot have virtual base classes!");
2693 assert(BRD &&
"Base classes must be C++ classes!");
2696 MRMgr.getCXXBaseObjectRegion(BRD, R,
false);
2698 NewB = bindStruct(NewB, BR, *VI);
2706 for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) {
2712 if (FI->isUnnamedBitfield())
2716 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2719 NewB = bindArray(NewB, FR, *VI);
2721 NewB = bindStruct(NewB, FR, *VI);
2729 NewB = NewB.addBinding(R, BindingKey::Default,
2742 return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);
2750class RemoveDeadBindingsWorker
2751 :
public ClusterAnalysis<RemoveDeadBindingsWorker> {
2757 RemoveDeadBindingsWorker(RegionStoreManager &rm,
2761 : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr,
b),
2762 SymReaper(symReaper), CurrentLCtx(LCtx) {}
2767 using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
2769 using ClusterAnalysis::AddToWorkList;
2773 bool UpdatePostponed();
2774 void VisitBinding(
SVal V);
2778bool RemoveDeadBindingsWorker::AddToWorkList(
const MemRegion *R) {
2780 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
2783void RemoveDeadBindingsWorker::VisitAddedToCluster(
const MemRegion *baseR,
2786 if (
const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
2787 if (SymReaper.isLive(VR))
2788 AddToWorkList(baseR, &
C);
2793 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
2794 if (SymReaper.isLive(SR->getSymbol()))
2795 AddToWorkList(SR, &
C);
2797 Postponed.push_back(SR);
2802 if (isa<NonStaticGlobalSpaceRegion>(baseR)) {
2803 AddToWorkList(baseR, &
C);
2808 if (
const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
2809 const auto *StackReg =
2813 (RegCtx == CurrentLCtx || RegCtx->
isParentOf(CurrentLCtx)))
2814 AddToWorkList(TR, &
C);
2818void RemoveDeadBindingsWorker::VisitCluster(
const MemRegion *baseR,
2825 if (
const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
2826 SymReaper.markLive(SymR->getSymbol());
2828 for (ClusterBindings::iterator I =
C->begin(), E =
C->end(); I != E; ++I) {
2830 SymReaper.markElementIndicesLive(I.getKey().getRegion());
2832 VisitBinding(I.getData());
2836void RemoveDeadBindingsWorker::VisitBinding(
SVal V) {
2840 SymReaper.markLazilyCopied(LCS->getRegion());
2842 for (
SVal V : RM.getInterestingValues(*LCS)) {
2844 SymReaper.markLazilyCopied(DepLCS->getRegion());
2855 SymReaper.markLive(R);
2860 E = BR->referenced_vars_end();
2861 for ( ; I != E; ++I)
2868 for (
auto SI =
V.symbol_begin(), SE =
V.symbol_end(); SI!=SE; ++SI)
2869 SymReaper.markLive(*SI);
2872bool RemoveDeadBindingsWorker::UpdatePostponed() {
2877 for (
auto I = Postponed.begin(), E = Postponed.end(); I != E; ++I) {
2879 if (SymReaper.isLive(SR->getSymbol())) {
2892 RegionBindingsRef B = getRegionBindings(store);
2893 RemoveDeadBindingsWorker W(*
this, StateMgr, B, SymReaper, LCtx);
2894 W.GenerateClusters();
2899 W.AddToWorkList(*I);
2902 do W.RunWorkList();
while (W.UpdatePostponed());
2907 for (RegionBindingsRef::iterator I = B.begin(), E = B.end(); I != E; ++I) {
2912 if (!W.isVisited(
Base))
2916 return StoreRef(B.asStore(), *
this);
2923void RegionStoreManager::printJson(raw_ostream &Out,
Store S,
const char *NL,
2924 unsigned int Space,
bool IsDot)
const {
2925 RegionBindingsRef
Bindings = getRegionBindings(S);
2927 Indent(Out, Space, IsDot) <<
"\"store\": ";
2930 Out <<
"null," << NL;
2934 Out <<
"{ \"pointer\": \"" <<
Bindings.asStore() <<
"\", \"items\": [" << NL;
2935 Bindings.printJson(Out, NL, Space + 1, IsDot);
2936 Indent(Out, Space, IsDot) <<
"]}," << NL;
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static CompilationDatabasePluginRegistry::Add< FixedCompilationDatabasePlugin > X("fixed-compilation-database", "Reads plain-text flags file")
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
static std::optional< SVal > convertOffsetsFromSvalToUnsigneds(const SmallVector< SVal, 2 > &SrcOffsets, const SmallVector< uint64_t, 2 > ArrayExtents, SmallVector< uint64_t, 2 > &DstOffsets)
llvm::ImmutableMap< const MemRegion *, ClusterBindings > RegionBindings
static std::optional< SVal > getDerivedSymbolForBinding(RegionBindingsConstRef B, const TypedValueRegion *BaseRegion, const TypedValueRegion *SubReg, const ASTContext &Ctx, SValBuilder &SVB)
std::pair< BindingKey, SVal > BindingPair
static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields)
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
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.
const llvm::APInt & getSize() const
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...
bool isUnnamedBitfield() const
Determines whether this is an unnamed bitfield.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Describes an C or C++ initializer list.
bool isStringLiteralInit() const
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
LLVM_ATTRIBUTE_RETURNS_NONNULL const VarRegion * getCapturedRegion() const
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 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
virtual StoreRef invalidateRegions(Store store, ArrayRef< SVal > Values, const Expr *E, unsigned Count, const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits, InvalidatedRegions *InvalidatedTopLevel, InvalidatedRegions *Invalidated)=0
invalidateRegions - Clears out the specified regions from the store, marking their values as unknown.
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.
region_iterator region_begin() const
RegionSetTy::const_iterator region_iterator
region_iterator region_end() 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
const MemRegion * getRegion() const
Get the underlining region.
llvm::ImmutableList< SVal >::iterator iterator
Value representing integer constant.
LLVM_ATTRIBUTE_RETURNS_NONNULL const LazyCompoundValData * getCVData() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
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.
std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
bool Call(InterpState &S, CodePtr &PC, const Function *Func)
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ C
Languages that the frontend can parse and compile.
YAML serialization mapping.
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...
__PTRDIFF_TYPE__ ptrdiff_t
A signed integer type that is the result of subtracting two pointers.