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 isDefault()
const {
return !isDirect(); }
74 bool hasSymbolicOffset()
const {
return P.getInt() & Symbolic; }
78 assert(!hasSymbolicOffset());
82 const SubRegion *getConcreteOffsetRegion()
const {
83 assert(hasSymbolicOffset());
88 if (hasSymbolicOffset())
93 void Profile(llvm::FoldingSetNodeID& ID)
const {
94 ID.AddPointer(
P.getOpaqueValue());
101 if (
P.getOpaqueValue() <
X.P.getOpaqueValue())
103 if (
P.getOpaqueValue() >
X.P.getOpaqueValue())
105 return Data <
X.Data;
109 return P.getOpaqueValue() ==
X.P.getOpaqueValue() &&
113 LLVM_DUMP_METHOD
void dump()
const;
117BindingKey BindingKey::Make(
const MemRegion *R, Kind k) {
120 return BindingKey(cast<SubRegion>(R), cast<SubRegion>(RO.
getRegion()), k);
126static inline raw_ostream &
operator<<(raw_ostream &Out, BindingKey K) {
127 Out <<
"\"kind\": \"" << (K.isDirect() ?
"Direct" :
"Default")
128 <<
"\", \"offset\": ";
130 if (!K.hasSymbolicOffset())
131 Out << K.getOffset();
140#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
141void BindingKey::dump()
const { llvm::errs() << *
this; }
152typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
156class RegionBindingsRef :
public llvm::ImmutableMapRef<const MemRegion *,
158 ClusterBindings::Factory *CBFactory;
172 typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
175 RegionBindingsRef(ClusterBindings::Factory &CBFactory,
176 const RegionBindings::TreeTy *
T,
177 RegionBindings::TreeTy::Factory *F,
179 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(
T, F),
180 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
182 RegionBindingsRef(
const ParentTy &
P,
183 ClusterBindings::Factory &CBFactory,
185 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(
P),
186 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
188 RegionBindingsRef add(key_type_ref K, data_type_ref
D)
const {
189 return RegionBindingsRef(
static_cast<const ParentTy *
>(
this)->add(K,
D),
190 *CBFactory, IsMainAnalysis);
193 RegionBindingsRef remove(key_type_ref K)
const {
194 return RegionBindingsRef(
static_cast<const ParentTy *
>(
this)->remove(K),
195 *CBFactory, IsMainAnalysis);
198 RegionBindingsRef addBinding(BindingKey K,
SVal V)
const;
200 RegionBindingsRef addBinding(
const MemRegion *R,
201 BindingKey::Kind k,
SVal V)
const;
203 const SVal *lookup(BindingKey K)
const;
204 const SVal *lookup(
const MemRegion *R, BindingKey::Kind k)
const;
207 RegionBindingsRef removeBinding(BindingKey K);
209 RegionBindingsRef removeBinding(
const MemRegion *R,
212 RegionBindingsRef removeBinding(
const MemRegion *R) {
213 return removeBinding(R, BindingKey::Direct).
214 removeBinding(R, BindingKey::Default);
217 std::optional<SVal> getDirectBinding(
const MemRegion *R)
const;
221 std::optional<SVal> getDefaultBinding(
const MemRegion *R)
const;
224 Store asStore()
const {
225 llvm::PointerIntPair<Store, 1, bool> Ptr = {
226 asImmutableMap().getRootWithoutRetain(), IsMainAnalysis};
227 return reinterpret_cast<Store>(Ptr.getOpaqueValue());
230 bool isMainAnalysis()
const {
231 return IsMainAnalysis;
234 void printJson(raw_ostream &Out,
const char *NL =
"\n",
235 unsigned int Space = 0,
bool IsDot =
false)
const {
236 using namespace llvm;
237 DenseMap<const MemRegion *, std::string> StringifyCache;
238 auto ToString = [&StringifyCache](
const MemRegion *R) {
239 auto [Place, Inserted] = StringifyCache.try_emplace(R);
241 return Place->second;
243 raw_string_ostream OS(Res);
250 std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;
251 using Binding = std::pair<BindingKey, SVal>;
253 const auto MemSpaceBeforeRegionName = [&ToString](
const Cluster *L,
255 if (isa<MemSpaceRegion>(L->first) && !isa<MemSpaceRegion>(R->first))
257 if (!isa<MemSpaceRegion>(L->first) && isa<MemSpaceRegion>(R->first))
259 return ToString(L->first) < ToString(R->first);
262 const auto SymbolicBeforeOffset = [&ToString](
const BindingKey &L,
263 const BindingKey &R) {
264 if (L.hasSymbolicOffset() && !R.hasSymbolicOffset())
266 if (!L.hasSymbolicOffset() && R.hasSymbolicOffset())
268 if (L.hasSymbolicOffset() && R.hasSymbolicOffset())
269 return ToString(L.getRegion()) < ToString(R.getRegion());
270 return L.getOffset() < R.getOffset();
273 const auto DefaultBindingBeforeDirectBindings =
274 [&SymbolicBeforeOffset](
const Binding *LPtr,
const Binding *RPtr) {
275 const BindingKey &L = LPtr->first;
276 const BindingKey &R = RPtr->first;
277 if (L.isDefault() && !R.isDefault())
279 if (!L.isDefault() && R.isDefault())
281 assert(L.isDefault() == R.isDefault());
282 return SymbolicBeforeOffset(L, R);
285 const auto AddrOf = [](
const auto &Item) {
return &Item; };
287 std::vector<const Cluster *> SortedClusters;
288 SortedClusters.reserve(std::distance(begin(), end()));
289 append_range(SortedClusters, map_range(*
this, AddrOf));
290 llvm::sort(SortedClusters, MemSpaceBeforeRegionName);
292 for (
auto [Idx,
C] : llvm::enumerate(SortedClusters)) {
294 Indent(Out, Space, IsDot)
295 <<
"{ \"cluster\": \"" << BaseRegion <<
"\", \"pointer\": \""
296 << (
const void *)BaseRegion <<
"\", \"items\": [" << NL;
298 std::vector<const Binding *> SortedBindings;
300 append_range(SortedBindings, map_range(
Bindings, AddrOf));
301 llvm::sort(SortedBindings, DefaultBindingBeforeDirectBindings);
304 for (
auto [Idx, B] : llvm::enumerate(SortedBindings)) {
305 const auto &[Key,
Value] = *B;
306 Indent(Out, Space, IsDot) <<
"{ " << Key <<
", \"value\": ";
307 Value.printJson(Out,
true);
309 if (Idx != SortedBindings.size() - 1)
314 Indent(Out, Space, IsDot) <<
"]}";
315 if (Idx != SortedClusters.size() - 1)
321 LLVM_DUMP_METHOD
void dump()
const { printJson(llvm::errs()); }
328RegionBindingsRef::getDirectBinding(
const MemRegion *R)
const {
329 const SVal *
V = lookup(R, BindingKey::Direct);
330 return V ? std::optional<SVal>(*
V) : std::nullopt;
334RegionBindingsRef::getDefaultBinding(
const MemRegion *R)
const {
335 const SVal *
V = lookup(R, BindingKey::Default);
336 return V ? std::optional<SVal>(*
V) :
std::nullopt;
339RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K,
SVal V)
const {
344 (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
347 return add(
Base, NewCluster);
351RegionBindingsRef RegionBindingsRef::addBinding(
const MemRegion *R,
354 return addBinding(BindingKey::Make(R, k),
V);
357const SVal *RegionBindingsRef::lookup(BindingKey K)
const {
361 return Cluster->lookup(K);
365 BindingKey::Kind k)
const {
366 return lookup(BindingKey::Make(R, k));
369RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
376 if (NewCluster.isEmpty())
378 return add(
Base, NewCluster);
381RegionBindingsRef RegionBindingsRef::removeBinding(
const MemRegion *R,
383 return removeBinding(BindingKey::Make(R, k));
391class InvalidateRegionsWorker;
395 RegionBindings::Factory RBFactory;
396 mutable ClusterBindings::Factory CBFactory;
398 typedef std::vector<SVal> SValListTy;
401 SValListTy> LazyBindingsMapTy;
402 LazyBindingsMapTy LazyBindingsMap;
412 unsigned SmallStructLimit;
422 unsigned SmallArrayLimit;
426 void populateWorkList(InvalidateRegionsWorker &W,
428 InvalidatedRegions *TopLevelRegions);
433 CBFactory(mgr.getAllocator()), SmallStructLimit(0), SmallArrayLimit(0) {
436 SmallStructLimit = Options.RegionStoreSmallStructLimit;
437 SmallArrayLimit = Options.RegionStoreSmallArrayLimit;
457 bool IsMainAnalysis =
false;
458 if (
const auto *FD = dyn_cast<FunctionDecl>(InitLoc->
getDecl()))
459 IsMainAnalysis = FD->isMain() && !Ctx.getLangOpts().CPlusPlus;
461 RegionBindingsRef::ParentTy(RBFactory.getEmptyMap(), RBFactory),
462 CBFactory, IsMainAnalysis).asStore(), *
this);
472 InvalidatedRegions *Invalidated);
478 InvalidatedRegions *Invalidated,
479 InvalidatedRegions *InvalidatedTopLevel)
override;
499 return StoreRef(bind(getRegionBindings(store), LV,
V).asStore(), *
this);
508 RegionBindingsRef B = getRegionBindings(store);
511 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
512 "Double initialization!");
513 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
514 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this);
529 if (
const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
530 if (BR->getDecl()->isEmpty())
533 RegionBindingsRef B = getRegionBindings(store);
534 SVal V = svalBuilder.makeZeroVal(Ctx.CharTy);
535 B = removeSubRegionBindings(B, cast<SubRegion>(R));
536 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
537 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this);
550 std::optional<RegionBindingsRef>
562 std::optional<RegionBindingsRef>
582 getRegionBindings(store).manualRetain();
589 getRegionBindings(store).manualRelease();
617 RegionBindingsRef B = getRegionBindings(S);
641 RegionBindingsRef LazyBinding);
666 std::pair<Store, const SubRegion *>
695 RegionBindingsRef getRegionBindings(
Store store)
const {
696 llvm::PointerIntPair<Store, 1, bool> Ptr;
697 Ptr.setFromOpaqueValue(
const_cast<void *
>(store));
698 return RegionBindingsRef(
700 static_cast<const RegionBindings::TreeTy *
>(Ptr.getPointer()),
701 RBFactory.getTreeFactory(),
706 unsigned int Space = 0,
bool IsDot =
false)
const override;
709 RegionBindingsRef B = getRegionBindings(store);
710 for (
const auto &[Region, Cluster] : B) {
711 for (
const auto &[Key,
Value] : Cluster) {
714 if (
const SubRegion *R = dyn_cast<SubRegion>(Key.getRegion())) {
716 if (!f.HandleBinding(*
this, store, R,
Value))
730std::unique_ptr<StoreManager>
732 return std::make_unique<RegionStoreManager>(StMgr);
742enum GlobalsFilterKind {
751template <
typename DERIVED>
752class ClusterAnalysis {
754 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
755 typedef const MemRegion * WorkListElement;
762 RegionStoreManager &RM;
784 : RM(rm), Ctx(StateMgr.getContext()),
785 svalBuilder(StateMgr.getSValBuilder()), B(
std::move(
b)) {}
787 RegionBindingsRef getRegionBindings()
const {
return B; }
790 return Visited.count(getCluster(R));
793 void GenerateClusters() {
795 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
800 assert(!Cluster.isEmpty() &&
"Empty clusters should be removed");
801 static_cast<DERIVED*
>(
this)->VisitAddedToCluster(
Base, Cluster);
805 if (
static_cast<DERIVED*
>(
this)->includeEntireMemorySpace(
Base))
806 AddToWorkList(WorkListElement(
Base), &Cluster);
818 return static_cast<DERIVED*
>(
this)->AddToWorkList(R);
822 while (!WL.empty()) {
823 WorkListElement
E = WL.pop_back_val();
826 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR, getCluster(BaseR));
835 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR,
C);
844bool RegionStoreManager::scanReachableSymbols(
Store S,
const MemRegion *R,
846 assert(R == R->
getBaseRegion() &&
"Should only be called for base regions");
847 RegionBindingsRef B = getRegionBindings(S);
853 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
855 if (!Callbacks.
scan(RI.getData()))
869 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
875 if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R))
877 Fields.push_back(FR->getDecl());
879 R = cast<SubRegion>(R)->getSuperRegion();
884 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
892 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
894 return std::equal(FieldsInBindingKey.begin() + Delta,
895 FieldsInBindingKey.end(),
898 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
899 Fields.begin() - Delta);
915 bool IncludeAllDefaultBindings) {
917 if (TopKey.hasSymbolicOffset()) {
919 Top = TopKey.getConcreteOffsetRegion();
920 TopKey = BindingKey::Make(Top, BindingKey::Default);
924 uint64_t Length = UINT64_MAX;
926 if (std::optional<nonloc::ConcreteInt> ExtentCI =
928 const llvm::APSInt &ExtentInt = ExtentCI->getValue();
929 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
932 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
933 if (FR->getDecl()->isBitField())
934 Length = FR->getDecl()->getBitWidthValue(SVB.
getContext());
937 for (
const auto &StoreEntry : Cluster) {
938 BindingKey NextKey = StoreEntry.first;
939 if (NextKey.getRegion() == TopKey.getRegion()) {
945 if (NextKey.getOffset() > TopKey.getOffset() &&
946 NextKey.getOffset() - TopKey.getOffset() < Length) {
951 }
else if (NextKey.getOffset() == TopKey.getOffset()) {
958 if (IncludeAllDefaultBindings || NextKey.isDirect())
962 }
else if (NextKey.hasSymbolicOffset()) {
968 if (IncludeAllDefaultBindings || NextKey.isDirect())
971 }
else if (
const SubRegion *BaseSR = dyn_cast<SubRegion>(
Base)) {
974 if (BaseSR->isSubRegionOf(Top))
985 const SubRegion *Top,
bool IncludeAllDefaultBindings) {
987 BindingKey::Make(Top, BindingKey::Default),
988 IncludeAllDefaultBindings);
994 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
997 if (Top == ClusterHead) {
999 return B.remove(Top);
1006 if (TopKey.hasSymbolicOffset()) {
1007 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1008 return B.addBinding(Concrete, BindingKey::Default,
UnknownVal());
1018 for (BindingKey Key : llvm::make_first_range(
Bindings))
1019 Result = Result.remove(Key);
1025 if (TopKey.hasSymbolicOffset()) {
1026 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1027 Result = Result.
add(BindingKey::Make(Concrete, BindingKey::Default),
1031 if (Result.isEmpty())
1032 return B.remove(ClusterHead);
1033 return B.add(ClusterHead, Result.asImmutableMap());
1037class InvalidateRegionsWorker :
public ClusterAnalysis<InvalidateRegionsWorker>
1045 GlobalsFilterKind GlobalsFilter;
1048 RegionBindingsRef
b,
const Stmt *S,
unsigned count,
1052 GlobalsFilterKind GFK)
1053 : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr,
b), S(S),
1054 Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
1055 GlobalsFilter(GFK) {}
1058 void VisitBinding(
SVal V);
1060 using ClusterAnalysis::AddToWorkList;
1070 bool isInitiallyIncludedGlobalRegion(
const MemRegion *R);
1074bool InvalidateRegionsWorker::AddToWorkList(
const MemRegion *R) {
1075 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1078 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
1081void InvalidateRegionsWorker::VisitBinding(
SVal V) {
1092 if (std::optional<nonloc::LazyCompoundVal> LCS =
1097 for (
SVal V : RM.getInterestingValues(*LCS))
1098 if (!isa<nonloc::LazyCompoundVal>(
V))
1105void InvalidateRegionsWorker::VisitCluster(
const MemRegion *baseR,
1108 bool PreserveRegionsContents =
1109 ITraits.hasTrait(baseR,
1113 for (
SVal Val : llvm::make_second_range(*
C))
1117 if (!PreserveRegionsContents)
1118 B = B.remove(baseR);
1121 if (
const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
1122 if (
const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
1127 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
1128 using namespace ast_matchers;
1130 const char *DeclBind =
"DeclBind";
1132 to(
varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
1134 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
1135 RD->getASTContext());
1138 auto *VD = Match.getNodeAs<
VarDecl>(DeclBind);
1140 RM.getRegionManager().getVarRegion(VD, LCtx);
1141 AddToWorkList(ToInvalidate);
1150 for (
auto Var : BR->referenced_vars()) {
1151 const VarRegion *VR = Var.getCapturedRegion();
1163 if (std::optional<Loc> L =
V.getAs<
Loc>()) {
1174 IS.insert(SR->getSymbol());
1177 if (PreserveRegionsContents)
1182 Regions->push_back(baseR);
1184 if (isa<AllocaRegion, SymbolicRegion>(baseR)) {
1189 B = B.addBinding(baseR, BindingKey::Default,
V);
1199 if (isInitiallyIncludedGlobalRegion(baseR)) {
1211 B = B.addBinding(baseR, BindingKey::Default,
V);
1216 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1220 if (doNotInvalidateSuperRegion) {
1223 std::optional<uint64_t> NumElements;
1227 NumElements = CAT->getZExtSize();
1229 goto conjure_default;
1230 QualType ElementTy = AT->getElementType();
1238 AddToWorkList(SuperR);
1239 goto conjure_default;
1243 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
1244 bool UpperOverflow = UpperOffset < LowerOffset;
1249 goto conjure_default;
1253 goto conjure_default;
1255 for (
const auto &[BK,
V] : *
C) {
1256 std::optional<uint64_t> ROffset =
1257 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
1262 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
1264 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
1265 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
1266 B = B.removeBinding(BK);
1270 if (isa_and_nonnull<SymbolicRegion>(R))
1278 baseR, S, LCtx, AT->getElementType(), Count);
1279 B = B.addBinding(baseR, BindingKey::Default,
V);
1286 B = B.addBinding(baseR, BindingKey::Direct,
V);
1289bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
1291 switch (GlobalsFilter) {
1294 case GFK_SystemOnly:
1300 llvm_unreachable(
"unknown globals filter");
1303bool InvalidateRegionsWorker::includeEntireMemorySpace(
const MemRegion *
Base) {
1304 if (isInitiallyIncludedGlobalRegion(
Base))
1308 return ITraits.hasTrait(MemSpace,
1312RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
1315 InvalidatedRegions *Invalidated) {
1323 B = B.removeBinding(GS)
1324 .addBinding(BindingKey::Make(GS, BindingKey::Default),
V);
1329 Invalidated->push_back(GS);
1334void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
1336 InvalidatedRegions *TopLevelRegions) {
1337 for (
SVal V : Values) {
1339 for (
SVal S : getInterestingValues(*LCS))
1340 if (
const MemRegion *R = S.getAsRegion())
1347 if (TopLevelRegions)
1348 TopLevelRegions->push_back(R);
1355StoreRef RegionStoreManager::invalidateRegions(
1359 InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
1360 GlobalsFilterKind GlobalsFilter;
1362 if (
Call->isInSystemHeader())
1363 GlobalsFilter = GFK_SystemOnly;
1365 GlobalsFilter = GFK_All;
1367 GlobalsFilter = GFK_None;
1370 RegionBindingsRef B = getRegionBindings(store);
1371 InvalidateRegionsWorker W(*
this, StateMgr, B, S, Count, LCtx, IS, ITraits,
1372 Invalidated, GlobalsFilter);
1375 W.GenerateClusters();
1378 populateWorkList(W, Values, TopLevelRegions);
1383 B = W.getRegionBindings();
1389 switch (GlobalsFilter) {
1391 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, S,
1392 Count, LCtx, B, Invalidated);
1394 case GFK_SystemOnly:
1395 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, S, Count,
1396 LCtx, B, Invalidated);
1402 return StoreRef(B.asStore(), *
this);
1416 if (isa<loc::ConcreteInt>(Array))
1419 if (!isa<loc::MemRegionVal>(Array))
1433 assert(!isa<UnknownVal>(L) &&
"location unknown");
1434 assert(!isa<UndefinedVal>(L) &&
"location undefined");
1451 if (isa<BlockDataRegion>(MR)) {
1457 if (
const auto *TVR = dyn_cast<TypedValueRegion>(MR))
1458 T = TVR->getValueType();
1459 else if (
const auto *TR = dyn_cast<TypedRegion>(MR))
1461 else if (
const auto *SR = dyn_cast<SymbolicRegion>(MR))
1462 T = SR->getPointeeStaticType();
1464 assert(!
T.isNull() &&
"Unable to auto-detect binding type!");
1465 assert(!
T->
isVoidType() &&
"Attempting to dereference a void pointer!");
1467 if (!isa<TypedValueRegion>(MR))
1468 MR = GetElementZeroRegion(cast<SubRegion>(MR),
T);
1489 return getBindingForStruct(B, R);
1493 return createLazyBinding(B, R);
1497 return getBindingForArray(B, R);
1506 if (
const FieldRegion* FR = dyn_cast<FieldRegion>(R))
1528 if (
const VarRegion *VR = dyn_cast<VarRegion>(R)) {
1538 const SVal *
V = B.lookup(R, BindingKey::Direct);
1562 RegionTy = TVR->getValueType();
1565 RegionTy = SR->getSymbol()->getType();
1577static std::optional<nonloc::LazyCompoundVal>
1579 const SubRegion *R,
bool AllowSubregionBindings) {
1580 std::optional<SVal>
V = B.getDefaultBinding(R);
1582 return std::nullopt;
1584 std::optional<nonloc::LazyCompoundVal> LCV =
1587 return std::nullopt;
1592 if (!RegionTy.
isNull() &&
1594 QualType SourceRegionTy = LCV->getRegion()->getValueType();
1596 return std::nullopt;
1599 if (!AllowSubregionBindings) {
1606 return std::nullopt;
1612std::pair<Store, const SubRegion *>
1616 if (originalRegion != R) {
1617 if (std::optional<nonloc::LazyCompoundVal>
V =
1619 return std::make_pair(
V->getStore(),
V->getRegion());
1622 typedef std::pair<Store, const SubRegion *> StoreRegionPair;
1623 StoreRegionPair Result = StoreRegionPair();
1626 Result = findLazyBinding(B, cast<SubRegion>(ER->getSuperRegion()),
1630 Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);
1632 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
1633 Result = findLazyBinding(B, cast<SubRegion>(FR->getSuperRegion()),
1637 Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);
1640 dyn_cast<CXXBaseObjectRegion>(R)) {
1643 Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
1647 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
1661 assert(CAT &&
"ConstantArrayType should not be null");
1666 }
while ((CAT = dyn_cast<ConstantArrayType>(CAT->
getElementType())));
1684static std::pair<SmallVector<SVal, 2>,
const MemRegion *>
1686 assert(ER &&
"ConstantArrayType should not be null");
1690 SValOffsets.push_back(ER->
getIndex());
1692 ER = dyn_cast<ElementRegion>(
Base);
1694 return {SValOffsets,
Base};
1718static std::optional<SVal>
1739 DstOffsets.resize(SrcOffsets.size());
1740 auto ExtentIt = ArrayExtents.begin();
1741 auto OffsetIt = DstOffsets.begin();
1743 for (
SVal V : llvm::reverse(SrcOffsets)) {
1746 const llvm::APSInt &Offset = CI->getValue();
1747 if (Offset.isNegative() || Offset.uge(*(ExtentIt++)))
1750 *(OffsetIt++) = Offset.getZExtValue();
1758 return std::nullopt;
1761std::optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer(
1763 assert(R &&
"ElementRegion should not be null");
1771 return std::nullopt;
1773 assert(!SValOffsets.empty() &&
"getElementRegionOffsets guarantees the "
1774 "offsets vector is not empty.");
1782 return std::nullopt;
1797 return std::nullopt;
1803 return std::nullopt;
1814 if (SValOffsets.size() != Extents.size())
1815 return std::nullopt;
1819 SValOffsets, Extents, ConcreteOffsets))
1825 if (
const auto *ILE = dyn_cast<InitListExpr>(
Init))
1826 return getSValFromInitListExpr(ILE, ConcreteOffsets, R->
getElementType());
1831 if (
const auto *SL = dyn_cast<StringLiteral>(
Init))
1832 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
1837 return std::nullopt;
1857std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
1860 assert(ILE &&
"InitListExpr should not be null");
1862 for (uint64_t Offset : Offsets) {
1869 if (
const auto *SL = dyn_cast<StringLiteral>(ILE->
getInit(0)))
1870 return getSValFromStringLiteral(SL, Offset, ElemT);
1879 const auto *IL = dyn_cast<InitListExpr>(
E);
1893 return std::nullopt;
1924 assert(SL &&
"StringLiteral should not be null");
1940 if (
const std::optional<SVal> &ParentValue =
1941 B.getDirectBinding(BaseRegion)) {
1942 if (
SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
1945 if (ParentValue->isUndef())
1954 return std::nullopt;
1960 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
1966 if (
const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
1974 const llvm::APSInt &Idx = CI->getValue();
1978 return getSValFromStringLiteral(SL, Idx.getZExtValue(),
T);
1980 }
else if (isa<ElementRegion, VarRegion>(superR)) {
1981 if (std::optional<SVal>
V = getConstantValFromConstArrayInitializer(B, R))
1986 if (isa<CodeTextRegion>(superR))
2005 return getBindingForFieldOrElementCommon(B, R, R->
getElementType());
2012 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2019 if (
const auto *VR = dyn_cast<VarRegion>(superR)) {
2029 if (
const auto *InitList = dyn_cast<InitListExpr>(
Init)) {
2030 if (Index < InitList->getNumInits()) {
2031 if (
const Expr *FieldInit = InitList->getInit(Index))
2060 return getBindingForFieldOrElementCommon(B, R, Ty);
2063std::optional<SVal> RegionStoreManager::getBindingForDerivedDefaultValue(
2067 if (
const std::optional<SVal> &
D = B.getDefaultBinding(superR)) {
2080 if (isa<nonloc::LazyCompoundVal, nonloc::CompoundVal>(val))
2083 llvm_unreachable(
"Unknown default value");
2086 return std::nullopt;
2089SVal RegionStoreManager::getLazyBinding(
const SubRegion *LazyBindingRegion,
2090 RegionBindingsRef LazyBinding) {
2092 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
2093 Result = getBindingForElement(LazyBinding, ER);
2095 Result = getBindingForField(LazyBinding,
2096 cast<FieldRegion>(LazyBindingRegion));
2112 if (Result.isUndef())
2127 Store lazyBindingStore =
nullptr;
2128 const SubRegion *lazyBindingRegion =
nullptr;
2129 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
2130 if (lazyBindingRegion)
2131 return getLazyBinding(lazyBindingRegion,
2132 getRegionBindings(lazyBindingStore));
2136 bool hasSymbolicIndex =
false;
2152 bool hasPartialLazyBinding =
false;
2157 if (std::optional<SVal>
D =
2158 getBindingForDerivedDefaultValue(B,
Base, R, Ty)) {
2160 hasPartialLazyBinding =
true;
2168 NonLoc index = ER->getIndex();
2170 hasSymbolicIndex =
true;
2175 SR = dyn_cast<SubRegion>(
Base);
2179 if (isa<ElementRegion>(R)) {
2184 if (typedSuperR->getValueType()->isVectorType())
2193 if (hasSymbolicIndex)
2199 if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->
getBaseRegion())) {
2200 if (
const std::optional<SVal> &
V = B.getDefaultBinding(R))
2213 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2219 if (
const std::optional<SVal> &
V = B.getDefaultBinding(superR)) {
2227 return getBindingForLazySymbol(R);
2234 if (std::optional<SVal>
V = B.getDirectBinding(R))
2237 if (std::optional<SVal>
V = B.getDefaultBinding(R))
2245 if (isa<StackArgumentsSpaceRegion>(MS))
2263 if (isa<UnknownSpaceRegion>(MS))
2266 if (isa<GlobalsSpaceRegion>(MS)) {
2270 if (B.isMainAnalysis())
2279 if (isa<StaticGlobalSpaceRegion>(MS))
2282 if (std::optional<SVal>
V = getBindingForDerivedDefaultValue(B, MS, R,
T)) {
2298const RegionStoreManager::SValListTy &
2301 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.
getCVData());
2302 if (I != LazyBindingsMap.end())
2309 RegionBindingsRef B = getRegionBindings(LCV.
getStore());
2315 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2321 if (
V.isUnknownOrUndef() ||
V.isConstant())
2325 const SValListTy &InnerList = getInterestingValues(*InnerLCV);
2326 List.insert(List.end(), InnerList.begin(), InnerList.end());
2332 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2337 if (std::optional<nonloc::LazyCompoundVal>
V =
2357 if (std::optional<SVal> Val = getUniqueDefaultBinding(B, R))
2359 return createLazyBinding(B, R);
2365 "Only constant array types can have compound bindings.");
2367 return createLazyBinding(B, R);
2370bool RegionStoreManager::includedInBindings(
Store store,
2372 RegionBindingsRef B = getRegionBindings(store);
2376 if (B.lookup(region))
2380 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
2382 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
2384 SVal D = CI.getData();
2400 if (
const MemRegion* R = LV->getRegion())
2401 return StoreRef(getRegionBindings(ST).removeBinding(R)
2403 .getRootWithoutRetain(),
2416 const MemRegion *R = MemRegVal->getRegion();
2422 return bindArray(B, TR,
V);
2424 return bindStruct(B, TR,
V);
2426 return bindVector(B, TR,
V);
2428 return bindAggregate(B, TR,
V);
2433 if (
const auto *SymReg = dyn_cast<SymbolicRegion>(R)) {
2434 QualType Ty = SymReg->getPointeeStaticType();
2436 Ty = StateMgr.getContext().CharTy;
2437 R = GetElementZeroRegion(SymReg, Ty);
2440 assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
2441 "'this' pointer is not an l-value and is not assignable");
2444 RegionBindingsRef NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
2447 auto KeyKind = isa<nonloc::LazyCompoundVal>(
V) ? BindingKey::Default
2448 : BindingKey::Direct;
2449 return NewB.addBinding(BindingKey::Make(R, KeyKind),
V);
2476 return B.addBinding(R, BindingKey::Default,
V);
2479std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallArray(
2483 auto CAT = dyn_cast<ConstantArrayType>(AT);
2487 return std::nullopt;
2491 return std::nullopt;
2495 if (ArrSize > SmallArrayLimit)
2496 return std::nullopt;
2498 RegionBindingsRef NewB = B;
2500 for (uint64_t i = 0; i < ArrSize; ++i) {
2503 MRMgr.getElementRegion(Ty, Idx, LCV.
getRegion(), Ctx);
2504 SVal V = getBindingForElement(getRegionBindings(LCV.
getStore()), SrcER);
2506 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2520 std::optional<uint64_t>
Size;
2530 return bindAggregate(B, R,
V);
2534 if (std::optional<nonloc::LazyCompoundVal> LCV =
2536 if (std::optional<RegionBindingsRef> NewB =
2537 tryBindSmallArray(B, R, AT, *LCV))
2540 return bindAggregate(B, R,
Init);
2543 if (
Init.isUnknown())
2551 RegionBindingsRef NewB(B);
2553 for (;
Size ? i < *
Size :
true; ++i, ++VI) {
2559 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2562 NewB = bindStruct(NewB, ER, *VI);
2564 NewB = bindArray(NewB, ER, *VI);
2572 if (!Size || i < *Size)
2573 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2585 if (isa<nonloc::LazyCompoundVal, nonloc::SymbolVal>(
V))
2586 return bindAggregate(B, R,
V);
2591 if (!isa<nonloc::CompoundVal>(
V)) {
2599 RegionBindingsRef NewB(B);
2601 for ( ; index != numElements ; ++index) {
2606 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2609 NewB = bindArray(NewB, ER, *VI);
2611 NewB = bindStruct(NewB, ER, *VI);
2622 return std::nullopt;
2624 const auto *Cluster = B.lookup(R);
2625 if (!Cluster || !llvm::hasSingleElement(*Cluster))
2626 return std::nullopt;
2628 const auto [Key,
Value] = *Cluster->begin();
2629 return Key.isDirect() ? std::optional<SVal>{} :
Value;
2635 return getUniqueDefaultBinding(B, LCV.
getRegion());
2638std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
2655 if (std::optional<SVal> Val = getUniqueDefaultBinding(LCV)) {
2656 return B.addBinding(BindingKey::Make(R, BindingKey::Default), Val.value());
2661 if (
const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
2662 if (
Class->getNumBases() != 0 ||
Class->getNumVBases() != 0)
2663 return std::nullopt;
2665 for (
const auto *FD : RD->
fields()) {
2671 if (Fields.size() == SmallStructLimit)
2672 return std::nullopt;
2682 return std::nullopt;
2684 Fields.push_back(FD);
2687 RegionBindingsRef NewB = B;
2691 SVal V = getBindingForField(getRegionBindings(LCV.
getStore()), SourceFR);
2693 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
2709 if (!RD->isCompleteDefinition())
2713 if (std::optional<nonloc::LazyCompoundVal> LCV =
2715 if (std::optional<RegionBindingsRef> NewB =
2716 tryBindSmallStruct(B, R, RD, *LCV))
2718 return bindAggregate(B, R,
V);
2720 if (isa<nonloc::SymbolVal>(
V))
2721 return bindAggregate(B, R,
V);
2726 if (
V.isUnknown() || !isa<nonloc::CompoundVal>(
V))
2748 RegionBindingsRef NewB(B);
2752 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
2760 assert((CRD->isAggregate() || (Ctx.
getLangOpts().ObjC && VI == VE)) &&
2761 "Non-aggregates are constructed with a constructor!");
2763 for (
const auto &B : CRD->bases()) {
2765 assert(!B.isVirtual() &&
"Aggregates cannot have virtual base classes!");
2774 assert(BRD &&
"Base classes must be C++ classes!");
2777 MRMgr.getCXXBaseObjectRegion(BRD, R,
false);
2779 NewB = bindStruct(NewB, BR, *VI);
2787 for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) {
2793 if (FI->isUnnamedBitField())
2797 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2800 NewB = bindArray(NewB, FR, *VI);
2802 NewB = bindStruct(NewB, FR, *VI);
2810 NewB = NewB.addBinding(R, BindingKey::Default,
2823 return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);
2831class RemoveDeadBindingsWorker
2832 :
public ClusterAnalysis<RemoveDeadBindingsWorker> {
2838 RemoveDeadBindingsWorker(RegionStoreManager &rm,
2842 : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr,
b),
2843 SymReaper(symReaper), CurrentLCtx(LCtx) {}
2848 using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
2850 using ClusterAnalysis::AddToWorkList;
2854 bool UpdatePostponed();
2855 void VisitBinding(
SVal V);
2859bool RemoveDeadBindingsWorker::AddToWorkList(
const MemRegion *R) {
2861 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
2864void RemoveDeadBindingsWorker::VisitAddedToCluster(
const MemRegion *baseR,
2867 if (
const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
2868 if (SymReaper.isLive(VR))
2869 AddToWorkList(baseR, &
C);
2874 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
2875 if (SymReaper.isLive(SR->getSymbol()))
2876 AddToWorkList(SR, &
C);
2878 Postponed.push_back(SR);
2883 if (isa<NonStaticGlobalSpaceRegion>(baseR)) {
2884 AddToWorkList(baseR, &
C);
2889 if (
const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
2890 const auto *StackReg =
2894 (RegCtx == CurrentLCtx || RegCtx->
isParentOf(CurrentLCtx)))
2895 AddToWorkList(TR, &
C);
2899void RemoveDeadBindingsWorker::VisitCluster(
const MemRegion *baseR,
2906 if (
const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
2907 SymReaper.markLive(SymR->getSymbol());
2909 for (
const auto &[Key, Val] : *
C) {
2911 SymReaper.markElementIndicesLive(Key.getRegion());
2917void RemoveDeadBindingsWorker::VisitBinding(
SVal V) {
2921 SymReaper.markLazilyCopied(LCS->getRegion());
2923 for (
SVal V : RM.getInterestingValues(*LCS)) {
2925 SymReaper.markLazilyCopied(DepLCS->getRegion());
2936 SymReaper.markLive(R);
2940 for (
auto Var : BR->referenced_vars())
2941 AddToWorkList(Var.getCapturedRegion());
2948 SymReaper.markLive(Sym);
2951bool RemoveDeadBindingsWorker::UpdatePostponed() {
2957 if (SymReaper.isLive(SR->getSymbol())) {
2969 RegionBindingsRef B = getRegionBindings(store);
2970 RemoveDeadBindingsWorker W(*
this, StateMgr, B, SymReaper, LCtx);
2971 W.GenerateClusters();
2975 W.AddToWorkList(Reg);
2978 do W.RunWorkList();
while (W.UpdatePostponed());
2986 if (!W.isVisited(
Base))
2990 return StoreRef(B.asStore(), *
this);
2997void RegionStoreManager::printJson(raw_ostream &Out,
Store S,
const char *NL,
2998 unsigned int Space,
bool IsDot)
const {
2999 RegionBindingsRef
Bindings = getRegionBindings(S);
3001 Indent(Out, Space, IsDot) <<
"\"store\": ";
3004 Out <<
"null," << NL;
3008 Out <<
"{ \"pointer\": \"" <<
Bindings.asStore() <<
"\", \"items\": [" << NL;
3009 Bindings.printJson(Out, NL, Space + 1, IsDot);
3010 Indent(Out, Space, IsDot) <<
"]}," << NL;
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
llvm::DenseSet< const void * > Visited
static std::optional< SVal > convertOffsetsFromSvalToUnsigneds(const SmallVector< SVal, 2 > &SrcOffsets, const SmallVector< uint64_t, 2 > ArrayExtents, SmallVector< uint64_t, 2 > &DstOffsets)
llvm::ImmutableMap< const MemRegion *, ClusterBindings > RegionBindings
static std::optional< SVal > getDerivedSymbolForBinding(RegionBindingsConstRef B, const TypedValueRegion *BaseRegion, const TypedValueRegion *SubReg, const ASTContext &Ctx, SValBuilder &SVB)
std::pair< BindingKey, SVal > BindingPair
static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields)
SmallVector< const FieldDecl *, 8 > FieldVector
llvm::ImmutableMap< BindingKey, SVal > ClusterBindings
static bool isUnionField(const FieldRegion *FR)
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).
Stmt - This represents one statement.
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 StoreRef invalidateRegions(Store store, ArrayRef< SVal > Values, const Stmt *S, unsigned Count, const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits, InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated)=0
invalidateRegions - Clears out the specified regions from the store, marking their values as unknown.
virtual bool scanReachableSymbols(Store S, const MemRegion *R, ScanReachableSymbols &Visitor)=0
Finds the transitive closure of symbols within the given region.
virtual void iterBindings(Store store, BindingsHandler &f)=0
iterBindings - Iterate over the bindings in the Store.
virtual 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
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...