28#include "llvm/ADT/ImmutableMap.h"
29#include "llvm/ADT/STLExtras.h"
30#include "llvm/Support/TimeProfiler.h"
31#include "llvm/Support/raw_ostream.h"
53 llvm::PointerIntPair<const MemRegion *, 2> P;
58 explicit BindingKey(
const SubRegion *r,
const SubRegion *Base, Kind k)
59 : P(r, k | Symbolic), Data(reinterpret_cast<
uintptr_t>(
Base)) {
60 assert(r && Base &&
"Must have known regions.");
61 assert(getConcreteOffsetRegion() == Base &&
"Failed to store base region");
65 explicit BindingKey(
const MemRegion *r, uint64_t offset, Kind k)
66 : P(r, k), Data(offset) {
67 assert(r &&
"Must have known regions.");
68 assert(getOffset() == offset &&
"Failed to store offset");
75 bool isDirect()
const {
return P.getInt() & Direct; }
76 bool isDefault()
const {
return !isDirect(); }
77 bool hasSymbolicOffset()
const {
return P.getInt() & Symbolic; }
79 const MemRegion *
getRegion()
const {
return P.getPointer(); }
81 assert(!hasSymbolicOffset());
85 const SubRegion *getConcreteOffsetRegion()
const {
86 assert(hasSymbolicOffset());
87 return reinterpret_cast<const SubRegion *
>(
static_cast<uintptr_t>(Data));
90 const MemRegion *getBaseRegion()
const {
91 if (hasSymbolicOffset())
92 return getConcreteOffsetRegion()->getBaseRegion();
96 void Profile(llvm::FoldingSetNodeID& ID)
const {
97 ID.AddPointer(P.getOpaqueValue());
101 static BindingKey
Make(
const MemRegion *R, Kind k);
104 if (P.getOpaqueValue() <
X.P.getOpaqueValue())
106 if (P.getOpaqueValue() >
X.P.getOpaqueValue())
108 return Data <
X.Data;
112 return P.getOpaqueValue() ==
X.P.getOpaqueValue() &&
116 LLVM_DUMP_METHOD
void dump()
const;
119std::string locDescr(
Loc L) {
121 llvm::raw_string_ostream
OS(S);
127BindingKey BindingKey::Make(
const MemRegion *R, Kind k) {
128 const RegionOffset &RO =
R->getAsOffset();
136static inline raw_ostream &
operator<<(raw_ostream &Out, BindingKey K) {
137 Out <<
"\"kind\": \"" << (K.isDirect() ?
"Direct" :
"Default")
138 <<
"\", \"offset\": ";
140 if (!K.hasSymbolicOffset())
141 Out << K.getOffset();
150#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
151void BindingKey::dump()
const { llvm::errs() << *
this; }
162typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
166class RegionBindingsRef :
public llvm::ImmutableMapRef<const MemRegion *,
168 ClusterBindings::Factory *CBFactory;
182 typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
185 RegionBindingsRef(ClusterBindings::Factory &CBFactory,
186 const RegionBindings::TreeTy *T,
187 RegionBindings::TreeTy::Factory *F,
bool IsMainAnalysis)
188 : RegionBindingsRef(ParentTy(T, F), CBFactory, IsMainAnalysis) {}
190 RegionBindingsRef(
const ParentTy &P, ClusterBindings::Factory &CBFactory,
192 : ParentTy(P), CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
194 RegionBindingsRef removeCluster(
const MemRegion *BaseRegion)
const {
195 return RegionBindingsRef(ParentTy::remove(BaseRegion), *CBFactory,
199 RegionBindingsRef addBinding(BindingKey K,
SVal V)
const;
201 RegionBindingsRef addBinding(
const MemRegion *R,
202 BindingKey::Kind k,
SVal V)
const;
204 const SVal *lookup(BindingKey K)
const;
205 const SVal *lookup(
const MemRegion *R, BindingKey::Kind k)
const;
208 RegionBindingsRef removeBinding(BindingKey K);
210 RegionBindingsRef removeBinding(
const MemRegion *R,
213 RegionBindingsRef removeBinding(
const MemRegion *R) {
214 return removeBinding(R, BindingKey::Direct).
215 removeBinding(R, BindingKey::Default);
218 std::optional<SVal> getDirectBinding(
const MemRegion *R)
const;
222 std::optional<SVal> getDefaultBinding(
const MemRegion *R)
const;
225 Store asStore()
const {
226 llvm::PointerIntPair<Store, 1, bool> Ptr = {
227 asImmutableMap().getRootWithoutRetain(), IsMainAnalysis};
228 return reinterpret_cast<Store>(Ptr.getOpaqueValue());
231 bool isMainAnalysis()
const {
232 return IsMainAnalysis;
235 void printJson(raw_ostream &Out,
const char *NL =
"\n",
236 unsigned int Space = 0,
bool IsDot =
false)
const {
237 using namespace llvm;
238 DenseMap<const MemRegion *, std::string> StringifyCache;
239 auto ToString = [&StringifyCache](
const MemRegion *R) {
240 auto [Place, Inserted] = StringifyCache.try_emplace(R);
242 return Place->second;
244 raw_string_ostream
OS(Res);
251 std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;
252 using Binding = std::pair<BindingKey, SVal>;
254 const auto MemSpaceBeforeRegionName = [&ToString](
const Cluster *L,
260 return ToString(L->first) < ToString(R->first);
263 const auto SymbolicBeforeOffset = [&ToString](
const BindingKey &L,
264 const BindingKey &R) {
265 if (L.hasSymbolicOffset() && !R.hasSymbolicOffset())
267 if (!L.hasSymbolicOffset() && R.hasSymbolicOffset())
269 if (L.hasSymbolicOffset() && R.hasSymbolicOffset())
270 return ToString(L.getRegion()) < ToString(R.getRegion());
271 return L.getOffset() < R.getOffset();
274 const auto DefaultBindingBeforeDirectBindings =
275 [&SymbolicBeforeOffset](
const Binding *LPtr,
const Binding *RPtr) {
276 const BindingKey &L = LPtr->first;
277 const BindingKey &R = RPtr->first;
278 if (L.isDefault() && !R.isDefault())
280 if (!L.isDefault() && R.isDefault())
282 assert(L.isDefault() == R.isDefault());
283 return SymbolicBeforeOffset(L, R);
286 const auto AddrOf = [](
const auto &Item) {
return &Item; };
288 std::vector<const Cluster *> SortedClusters;
289 SortedClusters.reserve(std::distance(begin(), end()));
290 append_range(SortedClusters, map_range(*
this, AddrOf));
291 llvm::sort(SortedClusters, MemSpaceBeforeRegionName);
293 for (
auto [Idx,
C] : llvm::enumerate(SortedClusters)) {
296 <<
"{ \"cluster\": \"" << BaseRegion <<
"\", \"pointer\": \""
297 << (
const void *)BaseRegion <<
"\", \"items\": [" << NL;
299 std::vector<const Binding *> SortedBindings;
301 append_range(SortedBindings, map_range(
Bindings, AddrOf));
302 llvm::sort(SortedBindings, DefaultBindingBeforeDirectBindings);
305 for (
auto [Idx, B] : llvm::enumerate(SortedBindings)) {
306 const auto &[Key,
Value] = *B;
307 Indent(Out, Space, IsDot) <<
"{ " << Key <<
", \"value\": ";
308 Value.printJson(Out,
true);
310 if (Idx != SortedBindings.size() - 1)
315 Indent(Out, Space, IsDot) <<
"]}";
316 if (Idx != SortedClusters.size() - 1)
322 LLVM_DUMP_METHOD
void dump()
const { printJson(llvm::errs()); }
326 commitBindingsToCluster(
const MemRegion *BaseRegion,
337 std::optional<unsigned> BindingsLeft)
338 : RegionBindingsRef(
Base),
339 EscapedValuesDuringBind(&EscapedValuesDuringBind),
340 BindingsLeft(BindingsLeft) {}
343 return BindingsLeft.has_value() && BindingsLeft.value() == 0;
347 EscapedValuesDuringBind->push_back(
V);
354 for (
SVal V : llvm::make_range(Begin, End))
361 data_type_ref BindingKeyAndValue)
const {
363 BaseRegion, BindingKeyAndValue),
364 *EscapedValuesDuringBind, BindingsLeft};
369 RegionBindingsRef::removeCluster(BaseRegion), *EscapedValuesDuringBind,
374 std::optional<unsigned> NewBindingsLeft = BindingsLeft;
375 if (NewBindingsLeft.has_value()) {
376 assert(NewBindingsLeft.value() != 0);
377 NewBindingsLeft.value() -= 1;
381 if (NewBindingsLeft.value() == 0) {
383 K = BindingKey::Make(K.getRegion(), BindingKey::Default);
389 *EscapedValuesDuringBind, NewBindingsLeft};
399 std::optional<unsigned> BindingsLeft;
406RegionBindingsRef::getDirectBinding(
const MemRegion *R)
const {
407 const SVal *
V = lookup(R, BindingKey::Direct);
408 return V ? std::optional<SVal>(*
V) : std::nullopt;
412RegionBindingsRef::getDefaultBinding(
const MemRegion *R)
const {
413 const SVal *
V = lookup(R, BindingKey::Default);
414 return V ? std::optional<SVal>(*
V) : std::nullopt;
417RegionBindingsRef RegionBindingsRef::commitBindingsToCluster(
419 return RegionBindingsRef(ParentTy::add(BaseRegion,
Bindings), *CBFactory,
423RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K, SVal
V)
const {
424 const MemRegion *
Base = K.getBaseRegion();
428 (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
430 return commitBindingsToCluster(Base,
Bindings);
433RegionBindingsRef RegionBindingsRef::addBinding(
const MemRegion *R,
436 return addBinding(BindingKey::Make(R, k),
V);
439const SVal *RegionBindingsRef::lookup(BindingKey K)
const {
443 return Cluster->lookup(K);
446const SVal *RegionBindingsRef::lookup(
const MemRegion *R,
447 BindingKey::Kind k)
const {
448 return lookup(BindingKey::Make(R, k));
451RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
452 const MemRegion *
Base = K.getBaseRegion();
458 if (NewCluster.isEmpty())
459 return removeCluster(Base);
460 return commitBindingsToCluster(Base, NewCluster);
463RegionBindingsRef RegionBindingsRef::removeBinding(
const MemRegion *R,
465 return removeBinding(BindingKey::Make(R, k));
473class InvalidateRegionsWorker;
475class RegionStoreManager :
public StoreManager {
477 RegionBindings::Factory RBFactory;
478 mutable ClusterBindings::Factory CBFactory;
480 typedef std::vector<SVal> SValListTy;
482 typedef llvm::DenseMap<
const LazyCompoundValData *,
483 SValListTy> LazyBindingsMapTy;
484 LazyBindingsMapTy LazyBindingsMap;
494 const unsigned SmallStructLimit;
504 const unsigned SmallArrayLimit;
510 const std::optional<unsigned> RegionStoreMaxBindingFanOutPlusOne;
514 void populateWorkList(InvalidateRegionsWorker &W,
515 ArrayRef<SVal> Values,
516 InvalidatedRegions *TopLevelRegions);
518 const AnalyzerOptions &getOptions() {
519 return StateMgr.getOwningEngine().getAnalysisManager().options;
523 RegionStoreManager(ProgramStateManager &mgr)
524 : StoreManager(mgr), RBFactory(mgr.getAllocator()),
525 CBFactory(mgr.getAllocator()),
526 SmallStructLimit(getOptions().RegionStoreSmallStructLimit),
527 SmallArrayLimit(getOptions().RegionStoreSmallArrayLimit),
528 RegionStoreMaxBindingFanOutPlusOne([&]() -> std::optional<unsigned> {
529 unsigned FanOut = getOptions().RegionStoreMaxBindingFanOut;
530 assert(FanOut != std::numeric_limits<unsigned>::max());
539 LimitedRegionBindingsRef
549 SVal ArrayToPointer(Loc
Array, QualType ElementTy)
override;
553 StoreRef getInitialStore(
const StackFrame *SF)
override {
554 bool IsMainAnalysis =
false;
555 if (
const auto *FD = dyn_cast<FunctionDecl>(SF->
getDecl()))
556 IsMainAnalysis = FD->isMain() && !Ctx.getLangOpts().CPlusPlus;
557 return StoreRef(RegionBindingsRef(RegionBindingsRef::ParentTy(
558 RBFactory.getEmptyMap(), RBFactory),
559 CBFactory, IsMainAnalysis)
569 unsigned Count,
const StackFrame *SF,
571 InvalidatedRegions *Invalidated);
573 StoreRef invalidateRegions(
Store store, ArrayRef<SVal> Values,
575 const StackFrame *SF,
const CallEvent *
Call,
577 RegionAndSymbolInvalidationTraits &ITraits,
578 InvalidatedRegions *Invalidated,
579 InvalidatedRegions *InvalidatedTopLevel)
override;
581 bool scanReachableSymbols(
Store S,
const MemRegion *R,
582 ScanReachableSymbols &Callbacks)
override;
584 LimitedRegionBindingsRef
588 const ElementRegion *R);
589 std::optional<SVal> getConstantValFromInitializer(
const FieldRegion *R,
590 bool IsMainAnalysis);
592 getSValFromInitListExpr(
const InitListExpr *ILE,
593 const SmallVector<uint64_t, 2> &ConcreteOffsets,
595 SVal getSValFromStringLiteral(
const StringLiteral *SL, uint64_t Offset,
599 BindResult
Bind(
Store store, Loc LV, SVal
V)
override {
600 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
601 LimitedRegionBindingsRef BoundedBindings =
602 getRegionBindings(store, EscapedValuesDuringBind);
603 return BindResult{StoreRef(bind(BoundedBindings, LV,
V).asStore(), *
this),
604 std::move(EscapedValuesDuringBind)};
612 BindResult BindDefaultInitial(
Store store,
const MemRegion *R,
614 RegionBindingsRef B = getRegionBindings(store);
617 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
618 "Double initialization!");
619 B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
621 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this), {}};
626 BindResult BindDefaultZero(
Store store,
const MemRegion *R)
override {
636 if (
const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
637 if (BR->getDecl()->isEmpty())
638 return BindResult{StoreRef(store, *
this), {}};
640 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
641 LimitedRegionBindingsRef B =
642 getRegionBindings(store, EscapedValuesDuringBind);
643 SVal
V = svalBuilder.makeZeroVal(Ctx.CharTy);
645 B = B.
addBinding(BindingKey::Make(R, BindingKey::Default),
V);
647 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *
this),
648 std::move(EscapedValuesDuringBind)};
661 std::optional<LimitedRegionBindingsRef>
663 const RecordDecl *RD, nonloc::LazyCompoundVal LCV);
667 const TypedValueRegion *R, SVal
V);
671 const TypedValueRegion *R, SVal
V);
673 std::optional<LimitedRegionBindingsRef>
675 const ArrayType *AT, nonloc::LazyCompoundVal LCV);
678 const TypedValueRegion *R, SVal
V);
683 const TypedRegion *R, SVal DefaultVal);
688 StoreRef killBinding(
Store ST, Loc L)
override;
690 void incrementReferenceCount(
Store store)
override {
691 getRegionBindings(store).manualRetain();
697 void decrementReferenceCount(
Store store)
override {
698 getRegionBindings(store).manualRelease();
701 bool includedInBindings(
Store store,
const MemRegion *region)
const override;
716 SVal getBinding(
Store S, Loc L, QualType T)
override {
717 return getBinding(getRegionBindings(S), L, T);
720 std::optional<SVal> getDefaultBinding(
Store S,
const MemRegion *R)
override {
721 RegionBindingsRef B = getRegionBindings(S);
725 return B.getDefaultBinding(
R->getBaseRegion());
738 SVal getBindingForLazySymbol(
const TypedValueRegion *R);
741 const TypedValueRegion *R,
744 SVal getLazyBinding(
const SubRegion *LazyBindingRegion,
745 RegionBindingsRef LazyBinding);
763 const MemRegion *superR,
764 const TypedValueRegion *R, QualType Ty);
770 std::pair<Store, const SubRegion *>
772 const SubRegion *originalRegion);
784 const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);
792 StoreRef removeDeadBindings(
Store store,
const StackFrame *SF,
793 SymbolReaper &SymReaper)
override;
799 RegionBindingsRef getRegionBindings(
Store store)
const {
800 llvm::PointerIntPair<Store, 1, bool> Ptr;
801 Ptr.setFromOpaqueValue(
const_cast<void *
>(store));
803 static_cast<const RegionBindings::TreeTy *
>(Ptr.getPointer()),
804 RBFactory.getTreeFactory(), Ptr.getInt()};
807 LimitedRegionBindingsRef
808 getRegionBindings(
Store store,
809 SmallVectorImpl<SVal> &EscapedValuesDuringBind)
const {
810 return LimitedRegionBindingsRef(
811 getRegionBindings(store), EscapedValuesDuringBind,
812 RegionStoreMaxBindingFanOutPlusOne);
815 void printJson(raw_ostream &Out,
Store S,
const char *NL =
"\n",
816 unsigned int Space = 0,
bool IsDot =
false)
const override;
818 void iterBindings(
Store store, BindingsHandler& f)
override {
819 RegionBindingsRef B = getRegionBindings(store);
820 for (
const auto &[Region, Cluster] : B) {
821 for (
const auto &[Key,
Value] : Cluster) {
824 if (
const SubRegion *R = dyn_cast<SubRegion>(Key.getRegion())) {
826 if (!f.HandleBinding(*
this, store, R,
Value))
840std::unique_ptr<StoreManager>
842 return std::make_unique<RegionStoreManager>(StMgr);
852enum GlobalsFilterKind {
861template <
typename DERIVED>
862class ClusterAnalysis {
864 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
865 typedef const MemRegion * WorkListElement;
872 RegionStoreManager &RM;
887 bool includeEntireMemorySpace(
const MemRegion *Base) {
892 ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
894 : RM(rm), Ctx(StateMgr.getContext()),
895 svalBuilder(StateMgr.getSValBuilder()), B(std::move(b)) {}
897 RegionBindingsRef getRegionBindings()
const {
return B; }
899 bool isVisited(
const MemRegion *R) {
900 return Visited.count(getCluster(R));
903 void GenerateClusters() {
905 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
907 const MemRegion *
Base = RI.getKey();
910 assert(!Cluster.isEmpty() &&
"Empty clusters should be removed");
911 static_cast<DERIVED*
>(
this)->VisitAddedToCluster(Base, Cluster);
915 if (
static_cast<DERIVED*
>(
this)->includeEntireMemorySpace(Base))
916 AddToWorkList(WorkListElement(Base), &Cluster);
921 if (
C && !Visited.insert(
C).second)
927 bool AddToWorkList(
const MemRegion *R) {
928 return static_cast<DERIVED*
>(
this)->AddToWorkList(R);
932 while (!WL.empty()) {
933 WorkListElement E = WL.pop_back_val();
934 const MemRegion *BaseR = E;
936 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR, getCluster(BaseR));
940 void VisitAddedToCluster(
const MemRegion *baseR,
const ClusterBindings &
C) {}
945 static_cast<DERIVED*
>(
this)->VisitCluster(BaseR,
C);
954bool RegionStoreManager::scanReachableSymbols(
Store S,
const MemRegion *R,
955 ScanReachableSymbols &Callbacks) {
956 assert(R ==
R->getBaseRegion() &&
"Should only be called for base regions");
957 RegionBindingsRef B = getRegionBindings(S);
963 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
965 if (!Callbacks.
scan(RI.getData()))
979 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
985 if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R))
987 Fields.push_back(FR->getDecl());
994 assert(K.hasSymbolicOffset() &&
"Not implemented for concrete offset keys");
1002 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
1004 return std::equal(FieldsInBindingKey.begin() + Delta,
1005 FieldsInBindingKey.end(),
1008 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
1009 Fields.begin() - Delta);
1024 const SubRegion *Top, BindingKey TopKey,
1025 bool IncludeAllDefaultBindings) {
1027 if (TopKey.hasSymbolicOffset()) {
1029 Top = TopKey.getConcreteOffsetRegion();
1030 TopKey = BindingKey::Make(Top, BindingKey::Default);
1034 uint64_t Length = UINT64_MAX;
1036 if (std::optional<nonloc::ConcreteInt> ExtentCI =
1038 const llvm::APSInt &ExtentInt = ExtentCI->getValue();
1039 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
1042 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
1043 if (FR->getDecl()->isBitField())
1044 Length = FR->getDecl()->getBitWidthValue();
1047 for (
const auto &StoreEntry : Cluster) {
1048 BindingKey NextKey = StoreEntry.first;
1049 if (NextKey.getRegion() == TopKey.getRegion()) {
1055 if (NextKey.getOffset() > TopKey.getOffset() &&
1056 NextKey.getOffset() - TopKey.getOffset() < Length) {
1061 }
else if (NextKey.getOffset() == TopKey.getOffset()) {
1068 if (IncludeAllDefaultBindings || NextKey.isDirect())
1072 }
else if (NextKey.hasSymbolicOffset()) {
1078 if (IncludeAllDefaultBindings || NextKey.isDirect())
1081 }
else if (
const SubRegion *BaseSR = dyn_cast<SubRegion>(
Base)) {
1084 if (BaseSR->isSubRegionOf(Top))
1095 const SubRegion *Top,
bool IncludeAllDefaultBindings) {
1097 BindingKey::Make(Top, BindingKey::Default),
1098 IncludeAllDefaultBindings);
1101LimitedRegionBindingsRef
1103 const SubRegion *Top) {
1104 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
1105 const MemRegion *ClusterHead = TopKey.getBaseRegion();
1107 if (Top == ClusterHead) {
1116 if (TopKey.hasSymbolicOffset()) {
1117 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1118 return B.
addBinding(Concrete, BindingKey::Default, UnknownVal());
1123 SmallVector<BindingPair, 32>
Bindings;
1128 for (BindingKey Key : llvm::make_first_range(
Bindings))
1135 if (TopKey.hasSymbolicOffset()) {
1136 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1137 Result =
Result.add(BindingKey::Make(Concrete, BindingKey::Default),
1147class InvalidateRegionsWorker :
public ClusterAnalysis<InvalidateRegionsWorker>
1151 const StackFrame *SF;
1153 RegionAndSymbolInvalidationTraits &ITraits;
1155 GlobalsFilterKind GlobalsFilter;
1157 InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
1159 unsigned count,
const StackFrame *SF,
1161 RegionAndSymbolInvalidationTraits &ITraitsIn,
1163 GlobalsFilterKind GFK)
1164 : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b), Elem(elem),
1165 Count(count), SF(SF), IS(
is), ITraits(ITraitsIn), Regions(r),
1166 GlobalsFilter(GFK) {}
1169 void VisitBinding(SVal
V);
1171 using ClusterAnalysis::AddToWorkList;
1173 bool AddToWorkList(
const MemRegion *R);
1177 bool includeEntireMemorySpace(
const MemRegion *Base);
1181 bool isInitiallyIncludedGlobalRegion(
const MemRegion *R);
1185bool InvalidateRegionsWorker::AddToWorkList(
const MemRegion *R) {
1186 bool doNotInvalidateSuperRegion = ITraits.
hasTrait(
1188 const MemRegion *BaseR = doNotInvalidateSuperRegion ?
R :
R->getBaseRegion();
1189 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
1192void InvalidateRegionsWorker::VisitBinding(SVal
V) {
1197 if (
const MemRegion *R =
V.getAsRegion()) {
1203 if (std::optional<nonloc::LazyCompoundVal> LCS =
1204 V.getAs<nonloc::LazyCompoundVal>()) {
1208 for (SVal
V : RM.getInterestingValues(*LCS))
1216void InvalidateRegionsWorker::VisitCluster(
const MemRegion *baseR,
1219 bool PreserveRegionsContents =
1224 for (SVal Val : llvm::make_second_range(*
C))
1228 if (!PreserveRegionsContents)
1232 if (
const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
1233 if (
const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
1238 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
1239 using namespace ast_matchers;
1241 const char *DeclBind =
"DeclBind";
1243 to(
varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
1245 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
1246 RD->getASTContext());
1248 for (BoundNodes &
Match : Matches) {
1249 auto *VD =
Match.getNodeAs<VarDecl>(DeclBind);
1250 const VarRegion *ToInvalidate =
1251 RM.getRegionManager().getVarRegion(VD, SF);
1252 AddToWorkList(ToInvalidate);
1260 if (
const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
1261 for (
auto Var : BR->referenced_vars()) {
1262 const VarRegion *VR = Var.getCapturedRegion();
1263 const VarDecl *VD = VR->
getDecl();
1273 SVal
V = RM.getBinding(B, loc::MemRegionVal(VR));
1274 if (std::optional<Loc> L =
V.getAs<Loc>()) {
1284 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
1285 IS.insert(SR->getSymbol());
1288 if (PreserveRegionsContents)
1293 Regions->push_back(baseR);
1298 DefinedOrUnknownSVal
V =
1310 if (isInitiallyIncludedGlobalRegion(baseR)) {
1320 DefinedOrUnknownSVal
V =
1327 bool doNotInvalidateSuperRegion = ITraits.
hasTrait(
1331 if (doNotInvalidateSuperRegion) {
1334 std::optional<uint64_t> NumElements;
1337 if (
const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
1338 NumElements = CAT->getZExtSize();
1340 goto conjure_default;
1341 QualType ElementTy = AT->getElementType();
1349 AddToWorkList(SuperR);
1350 goto conjure_default;
1354 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
1355 bool UpperOverflow = UpperOffset < LowerOffset;
1360 goto conjure_default;
1364 goto conjure_default;
1366 for (
const auto &[BK,
V] : *
C) {
1367 std::optional<uint64_t> ROffset =
1368 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
1373 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
1375 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
1376 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
1377 B = B.removeBinding(BK);
1380 const MemRegion *
R =
V.getAsRegion();
1381 if (isa_and_nonnull<SymbolicRegion>(R))
1389 baseR, Elem, SF, AT->getElementType(), Count);
1394 DefinedOrUnknownSVal
V =
1400bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
1401 const MemRegion *R) {
1402 switch (GlobalsFilter) {
1405 case GFK_SystemOnly:
1411 llvm_unreachable(
"unknown globals filter");
1414bool InvalidateRegionsWorker::includeEntireMemorySpace(
const MemRegion *Base) {
1415 if (isInitiallyIncludedGlobalRegion(Base))
1418 const MemSpaceRegion *MemSpace =
Base->getRawMemorySpace();
1423RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
1425 const StackFrame *SF, RegionBindingsRef B,
1426 InvalidatedRegions *Invalidated) {
1429 const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
1431 (
const void *)GS, Elem, SF,
1434 B = B.removeBinding(GS)
1435 .addBinding(BindingKey::Make(GS, BindingKey::Default),
V);
1440 Invalidated->push_back(GS);
1445void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
1446 ArrayRef<SVal> Values,
1447 InvalidatedRegions *TopLevelRegions) {
1448 for (SVal
V : Values) {
1449 if (
auto LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
1450 for (SVal S : getInterestingValues(*LCS))
1451 if (
const MemRegion *R = S.getAsRegion())
1457 if (
const MemRegion *R =
V.getAsRegion()) {
1458 if (TopLevelRegions)
1459 TopLevelRegions->push_back(R);
1466StoreRef RegionStoreManager::invalidateRegions(
1469 RegionAndSymbolInvalidationTraits &ITraits,
1470 InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
1471 GlobalsFilterKind GlobalsFilter;
1473 if (
Call->isInSystemHeader())
1474 GlobalsFilter = GFK_SystemOnly;
1476 GlobalsFilter = GFK_All;
1478 GlobalsFilter = GFK_None;
1481 RegionBindingsRef B = getRegionBindings(store);
1482 InvalidateRegionsWorker W(*
this, StateMgr, B, Elem, Count, SF, IS, ITraits,
1483 Invalidated, GlobalsFilter);
1486 W.GenerateClusters();
1489 populateWorkList(W, Values, TopLevelRegions);
1494 B = W.getRegionBindings();
1500 switch (GlobalsFilter) {
1502 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, Elem,
1503 Count, SF, B, Invalidated);
1505 case GFK_SystemOnly:
1506 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, Elem,
1507 Count, SF, B, Invalidated);
1513 return StoreRef(B.asStore(), *
this);
1526SVal RegionStoreManager::ArrayToPointer(Loc
Array, QualType T) {
1531 return UnknownVal();
1533 const SubRegion *
R =
1536 return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
1553 if (L.
getAs<loc::ConcreteInt>()) {
1554 return UnknownVal();
1556 if (!L.
getAs<loc::MemRegionVal>()) {
1557 return UnknownVal();
1563 return UnknownVal();
1568 if (
const auto *TVR = dyn_cast<TypedValueRegion>(MR))
1569 T = TVR->getValueType();
1570 else if (
const auto *TR = dyn_cast<TypedRegion>(MR))
1572 else if (
const auto *SR = dyn_cast<SymbolicRegion>(MR))
1573 T = SR->getPointeeStaticType();
1575 assert(!T.
isNull() &&
"Unable to auto-detect binding type!");
1576 assert(!T->
isVoidType() &&
"Attempting to dereference a void pointer!");
1584 QualType RTy =
R->getValueType();
1589 return UnknownVal();
1600 return getBindingForStruct(B, R);
1604 return createLazyBinding(B, R);
1608 return getBindingForArray(B, R);
1610 return UnknownVal();
1615 return UnknownVal();
1617 if (
const FieldRegion* FR = dyn_cast<FieldRegion>(R))
1618 return svalBuilder.
evalCast(getBindingForField(B, FR), T, QualType{});
1620 if (
const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
1626 return svalBuilder.
evalCast(getBindingForElement(B, ER), T, QualType{});
1629 if (
const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
1636 return svalBuilder.
evalCast(getBindingForObjCIvar(B, IVR), T, QualType{});
1639 if (
const VarRegion *VR = dyn_cast<VarRegion>(R)) {
1646 return svalBuilder.
evalCast(getBindingForVar(B, VR), T, QualType{});
1649 const SVal *
V = B.lookup(R, BindingKey::Direct);
1663 return UndefinedVal();
1673 RegionTy = TVR->getValueType();
1676 RegionTy = SR->getSymbol()->getType();
1688static std::optional<nonloc::LazyCompoundVal>
1690 const SubRegion *R,
bool AllowSubregionBindings) {
1691 std::optional<SVal>
V = B.getDefaultBinding(R);
1693 return std::nullopt;
1695 std::optional<nonloc::LazyCompoundVal> LCV =
1698 return std::nullopt;
1703 if (!RegionTy.
isNull() &&
1705 QualType SourceRegionTy = LCV->getRegion()->getValueType();
1707 return std::nullopt;
1710 if (!AllowSubregionBindings) {
1717 return std::nullopt;
1723std::pair<Store, const SubRegion *>
1726 const SubRegion *originalRegion) {
1727 if (originalRegion != R) {
1728 if (std::optional<nonloc::LazyCompoundVal>
V =
1730 return std::make_pair(
V->getStore(),
V->getRegion());
1733 typedef std::pair<Store, const SubRegion *> StoreRegionPair;
1734 StoreRegionPair
Result = StoreRegionPair();
1736 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
1741 Result.second = MRMgr.getElementRegionWithSuper(ER,
Result.second);
1743 }
else if (
const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
1748 Result.second = MRMgr.getFieldRegionWithSuper(FR,
Result.second);
1750 }
else if (
const CXXBaseObjectRegion *BaseReg =
1751 dyn_cast<CXXBaseObjectRegion>(R)) {
1758 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
1770static SmallVector<uint64_t, 2>
1772 assert(CAT &&
"ConstantArrayType should not be null");
1777 }
while ((CAT = dyn_cast<ConstantArrayType>(CAT->
getElementType())));
1795static std::pair<SmallVector<SVal, 2>,
const MemRegion *>
1797 assert(ER &&
"ConstantArrayType should not be null");
1801 SValOffsets.push_back(ER->
getIndex());
1803 ER = dyn_cast<ElementRegion>(
Base);
1805 return {SValOffsets,
Base};
1831static std::optional<SVal>
1837 int64_t FlatOffset = 0;
1838 auto ExtentIt = ArrayExtents.begin();
1839 for (
SVal V : llvm::reverse(SrcOffsets)) {
1843 FlatOffset = FlatOffset *
static_cast<int64_t
>(*(ExtentIt++)) +
1844 CI->getValue()->getExtValue();
1847 int64_t TotalSize = 1;
1848 for (uint64_t E : ArrayExtents)
1849 TotalSize *=
static_cast<int64_t
>(E);
1851 if (FlatOffset < 0 || FlatOffset >= TotalSize)
1854 DstOffsets.resize(ArrayExtents.size());
1855 uint64_t Remaining =
static_cast<uint64_t
>(FlatOffset);
1856 for (
int I = DstOffsets.size() - 1; I >= 0; --I) {
1857 DstOffsets[I] = Remaining % ArrayExtents[I];
1858 Remaining /= ArrayExtents[I];
1861 return std::nullopt;
1864std::optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer(
1866 assert(R &&
"ElementRegion should not be null");
1869 SmallVector<SVal, 2> SValOffsets;
1870 const MemRegion *
Base;
1872 const VarRegion *VR = dyn_cast<VarRegion>(Base);
1874 return std::nullopt;
1876 assert(!SValOffsets.empty() &&
"getElementRegionOffsets guarantees the "
1877 "offsets vector is not empty.");
1881 const VarDecl *VD = VR->
getDecl();
1883 !
R->getElementType().isConstQualified() &&
1885 return std::nullopt;
1900 return std::nullopt;
1906 return std::nullopt;
1917 if (SValOffsets.size() != Extents.size())
1918 return std::nullopt;
1920 SmallVector<uint64_t, 2> ConcreteOffsets;
1922 SValOffsets, Extents, ConcreteOffsets))
1928 if (
const auto *ILE = dyn_cast<InitListExpr>(
Init))
1929 return getSValFromInitListExpr(ILE, ConcreteOffsets,
R->getElementType());
1934 if (
const auto *SL = dyn_cast<StringLiteral>(
Init))
1935 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
1936 R->getElementType());
1940 return std::nullopt;
1960std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
1961 const InitListExpr *ILE,
const SmallVector<uint64_t, 2> &Offsets,
1963 assert(ILE &&
"InitListExpr should not be null");
1965 for (uint64_t Offset : Offsets) {
1972 if (
const auto *SL = dyn_cast<StringLiteral>(ILE->
getInit(0)))
1973 return getSValFromStringLiteral(SL, Offset, ElemT);
1981 const Expr *E = ILE->
getInit(Offset);
1982 const auto *IL = dyn_cast<InitListExpr>(E);
1996 return std::nullopt;
2024SVal RegionStoreManager::getSValFromStringLiteral(
const StringLiteral *SL,
2027 assert(SL &&
"StringLiteral should not be null");
2043 if (
const std::optional<SVal> &ParentValue =
2044 B.getDirectBinding(BaseRegion)) {
2045 if (
SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
2048 if (ParentValue->isUndef())
2057 return std::nullopt;
2061 const ElementRegion* R) {
2063 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2066 const MemRegion* superR =
R->getSuperRegion();
2069 if (
const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
2075 return UnknownVal();
2076 if (
const auto CI =
R->getIndex().getAs<nonloc::ConcreteInt>()) {
2077 const llvm::APSInt &Idx = CI->getValue();
2079 return UndefinedVal();
2080 const StringLiteral *SL = StrR->getStringLiteral();
2081 return getSValFromStringLiteral(SL, Idx.getZExtValue(), T);
2084 if (std::optional<SVal>
V = getConstantValFromConstArrayInitializer(B, R))
2090 return UnknownVal();
2098 const RegionRawOffset &O =
R->getAsArrayOffset();
2102 return UnknownVal();
2104 if (
const TypedValueRegion *baseR = dyn_cast<TypedValueRegion>(O.
getRegion()))
2108 return getBindingForFieldOrElementCommon(B, R,
R->getElementType());
2112RegionStoreManager::getConstantValFromInitializer(
const FieldRegion *R,
2113 bool IsMainAnalysis) {
2114 SmallVector<const SubRegion *, 4> Path;
2115 const MemRegion *Cur =
R;
2121 return std::nullopt;
2125 const auto *VR = dyn_cast<VarRegion>(Cur);
2127 return std::nullopt;
2129 const VarDecl *VD = VR->
getDecl();
2130 QualType LeafTy =
R->getDecl()->getType();
2136 return std::nullopt;
2140 return std::nullopt;
2142 const Expr *E =
Init;
2143 for (
const SubRegion *SR : llvm::reverse(Path)) {
2149 const auto *ILE = dyn_cast<InitListExpr>(E);
2151 return std::nullopt;
2153 if (
const auto *FR = dyn_cast<FieldRegion>(SR)) {
2158 if (InitField != FR->getDecl())
2159 return std::nullopt;
2164 unsigned Idx = FR->getDecl()->getFieldIndex();
2166 return std::nullopt;
2172 if (
const auto *ER = dyn_cast<ElementRegion>(SR)) {
2173 auto CI = ER->getIndex().getAs<nonloc::ConcreteInt>();
2175 return std::nullopt;
2176 uint64_t Idx = CI->getValue()->getZExtValue();
2177 if (Idx < ILE->getNumInits())
2182 return std::nullopt;
2186 return std::nullopt;
2193 const FieldRegion* R) {
2196 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2200 if (std::optional<SVal>
V =
2201 getConstantValFromInitializer(R, B.isMainAnalysis()))
2204 QualType Ty =
R->getDecl()->getType();
2222 if (
const auto *Base = dyn_cast<TypedValueRegion>(
R->getBaseRegion()))
2226 return getBindingForFieldOrElementCommon(B, R, Ty);
2229std::optional<SVal> RegionStoreManager::getBindingForDerivedDefaultValue(
2231 const TypedValueRegion *R, QualType Ty) {
2233 if (
const std::optional<SVal> &D = B.getDefaultBinding(superR)) {
2249 llvm_unreachable(
"Unknown default value");
2252 return std::nullopt;
2255SVal RegionStoreManager::getLazyBinding(
const SubRegion *LazyBindingRegion,
2256 RegionBindingsRef LazyBinding) {
2258 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
2259 Result = getBindingForElement(LazyBinding, ER);
2261 Result = getBindingForField(LazyBinding,
2286 const TypedValueRegion *R,
2293 Store lazyBindingStore =
nullptr;
2294 const SubRegion *lazyBindingRegion =
nullptr;
2295 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
2296 if (lazyBindingRegion)
2297 return getLazyBinding(lazyBindingRegion,
2298 getRegionBindings(lazyBindingStore));
2302 bool hasSymbolicIndex =
false;
2318 bool hasPartialLazyBinding =
false;
2320 const SubRegion *SR =
R;
2323 if (std::optional<SVal> D =
2324 getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
2325 if (D->getAs<nonloc::LazyCompoundVal>()) {
2326 hasPartialLazyBinding =
true;
2333 if (
const ElementRegion *ER = dyn_cast<ElementRegion>(Base)) {
2334 NonLoc index = ER->getIndex();
2336 hasSymbolicIndex =
true;
2341 SR = dyn_cast<SubRegion>(Base);
2348 if (
const TypedValueRegion *typedSuperR =
2349 dyn_cast<TypedValueRegion>(
R->getSuperRegion())) {
2350 if (typedSuperR->getValueType()->isVectorType())
2351 return UnknownVal();
2359 if (hasSymbolicIndex)
2360 return UnknownVal();
2366 if (
const std::optional<SVal> &
V = B.getDefaultBinding(R))
2368 return UndefinedVal();
2377 const ObjCIvarRegion* R) {
2379 if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
2382 const MemRegion *superR =
R->getSuperRegion();
2385 if (
const std::optional<SVal> &
V = B.getDefaultBinding(superR)) {
2390 return UnknownVal();
2393 return getBindingForLazySymbol(R);
2397 const VarRegion *R) {
2400 if (std::optional<SVal>
V = B.getDirectBinding(R))
2403 if (std::optional<SVal>
V = B.getDefaultBinding(R))
2407 const VarDecl *VD =
R->getDecl();
2408 const MemSpaceRegion *MS =
R->getRawMemorySpace();
2423 return UnknownVal();
2436 if (B.isMainAnalysis())
2448 if (std::optional<SVal>
V = getBindingForDerivedDefaultValue(B, MS, R, T)) {
2449 assert(!
V->getAs<nonloc::LazyCompoundVal>());
2456 return UndefinedVal();
2459SVal RegionStoreManager::getBindingForLazySymbol(
const TypedValueRegion *R) {
2464const RegionStoreManager::SValListTy &
2465RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
2467 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.
getCVData());
2468 if (I != LazyBindingsMap.end())
2474 const SubRegion *LazyR = LCV.
getRegion();
2475 RegionBindingsRef B = getRegionBindings(LCV.
getStore());
2481 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2483 SmallVector<BindingPair, 32>
Bindings;
2486 for (SVal
V : llvm::make_second_range(
Bindings)) {
2487 if (
V.isUnknownOrUndef() ||
V.isConstant())
2490 if (
auto InnerLCV =
V.getAs<nonloc::LazyCompoundVal>()) {
2491 const SValListTy &InnerList = getInterestingValues(*InnerLCV);
2492 llvm::append_range(List, InnerList);
2498 return (LazyBindingsMap[LCV.
getCVData()] = std::move(List));
2502 const TypedValueRegion *R) {
2503 if (std::optional<nonloc::LazyCompoundVal>
V =
2511 const TypedValueRegion *R) {
2512 const RecordDecl *RD =
2513 R->getValueType()->castAsCanonical<RecordType>()->getDecl();
2515 return UnknownVal();
2521 return createLazyBinding(B, R);
2525 const TypedValueRegion *R) {
2527 "Only constant array types can have compound bindings.");
2529 return createLazyBinding(B, R);
2532bool RegionStoreManager::includedInBindings(
Store store,
2533 const MemRegion *region)
const {
2534 RegionBindingsRef B = getRegionBindings(store);
2538 if (B.lookup(region))
2542 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
2544 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
2546 SVal D = CI.getData();
2548 if (
R->getBaseRegion() == region)
2560StoreRef RegionStoreManager::killBinding(
Store ST, Loc L) {
2561 if (std::optional<loc::MemRegionVal> LV = L.
getAs<loc::MemRegionVal>())
2562 if (
const MemRegion* R = LV->getRegion())
2563 return StoreRef(getRegionBindings(ST)
2566 .getRootWithoutRetain(),
2569 return StoreRef(ST, *
this);
2572LimitedRegionBindingsRef
2574 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bind",
2575 [&L]() {
return locDescr(L); });
2581 auto MemRegVal = L.
getAs<loc::MemRegionVal>();
2585 const MemRegion *
R = MemRegVal->getRegion();
2589 if (
const auto *SymReg = dyn_cast<SymbolicRegion>(R)) {
2590 QualType Ty = SymReg->getPointeeStaticType();
2592 Ty = StateMgr.getContext().CharTy;
2593 R = GetElementZeroRegion(SymReg, Ty);
2597 if (
const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
2600 return bindArray(B, TR,
V);
2602 return bindStruct(B, TR,
V);
2604 return bindVector(B, TR,
V);
2606 return bindAggregate(B, TR,
V);
2610 "'this' pointer is not an l-value and is not assignable");
2617 : BindingKey::Direct;
2618 return NewB.addBinding(BindingKey::Make(R, KeyKind),
V);
2621LimitedRegionBindingsRef
2623 const MemRegion *R, QualType T) {
2659std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallArray(
2661 const ArrayType *AT, nonloc::LazyCompoundVal LCV) {
2665 auto CAT = dyn_cast<ConstantArrayType>(AT);
2669 return std::nullopt;
2673 return std::nullopt;
2677 if (ArrSize > SmallArrayLimit)
2678 return std::nullopt;
2680 LimitedRegionBindingsRef NewB = B;
2682 for (uint64_t i = 0; i < ArrSize; ++i) {
2684 const ElementRegion *SrcER =
2685 MRMgr.getElementRegion(Ty, Idx, LCV.
getRegion(), Ctx);
2686 SVal
V = getBindingForElement(getRegionBindings(LCV.
getStore()), SrcER);
2688 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2689 NewB = bind(NewB, loc::MemRegionVal(DstER),
V);
2695LimitedRegionBindingsRef
2697 const TypedValueRegion *R, SVal
Init) {
2698 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindArray",
2699 [R]() {
return R->getDescriptiveName(); });
2705 std::optional<uint64_t>
Size;
2707 if (
const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
2713 if (std::optional<loc::MemRegionVal> MRV =
Init.getAs<loc::MemRegionVal>()) {
2714 SVal
V = getBinding(B.asStore(), *MRV,
R->getValueType());
2715 return bindAggregate(B, R,
V);
2720 if (
Init.isConstant())
2721 return bindAggregate(B, R,
Init);
2723 if (std::optional LCV =
Init.getAs<nonloc::LazyCompoundVal>()) {
2724 if (std::optional NewB = tryBindSmallArray(B, R, AT, *LCV))
2726 return bindAggregate(B, R,
Init);
2730 return bindAggregate(B, R,
Init);
2733 const nonloc::CompoundVal& CV =
Init.castAs<nonloc::CompoundVal>();
2737 LimitedRegionBindingsRef NewB = B;
2739 for (;
Size ? i < *
Size :
true; ++i, ++VI) {
2747 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2750 NewB = bindStruct(NewB, ER, *VI);
2752 NewB = bindArray(NewB, ER, *VI);
2754 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2760 if (!Size || i < *Size)
2761 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2766LimitedRegionBindingsRef
2768 const TypedValueRegion *R, SVal
V) {
2769 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindVector",
2770 [R]() {
return R->getDescriptiveName(); });
2774 QualType T =
R->getValueType();
2775 const VectorType *VT = T->
castAs<VectorType>();
2779 return bindAggregate(B, R,
V);
2785 return bindAggregate(B, R, UnknownVal());
2789 nonloc::CompoundVal CV =
V.
castAs<nonloc::CompoundVal>();
2792 LimitedRegionBindingsRef NewB = B;
2794 for ( ; index != numElements ; ++index) {
2802 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2805 NewB = bindArray(NewB, ER, *VI);
2807 NewB = bindStruct(NewB, ER, *VI);
2809 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2814std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
2816 const RecordDecl *RD, nonloc::LazyCompoundVal LCV) {
2822 if (
const CXXRecordDecl *
Class = dyn_cast<CXXRecordDecl>(RD))
2823 if (
Class->getNumBases() != 0 ||
Class->getNumVBases() != 0)
2824 return std::nullopt;
2826 for (
const auto *FD : RD->
fields()) {
2827 if (FD->isUnnamedBitField())
2832 if (Fields.size() == SmallStructLimit)
2833 return std::nullopt;
2835 QualType Ty = FD->getType();
2843 return std::nullopt;
2845 Fields.push_back(FD);
2848 LimitedRegionBindingsRef NewB = B;
2850 for (
const FieldDecl *Field : Fields) {
2851 const FieldRegion *SourceFR = MRMgr.getFieldRegion(Field, LCV.
getRegion());
2852 SVal
V = getBindingForField(getRegionBindings(LCV.
getStore()), SourceFR);
2854 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
2855 NewB = bind(NewB, loc::MemRegionVal(DestFR),
V);
2861LimitedRegionBindingsRef
2863 const TypedValueRegion *R, SVal
V) {
2864 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindStruct",
2865 [R]() {
return R->getDescriptiveName(); });
2869 QualType T =
R->getValueType();
2877 if (std::optional<nonloc::LazyCompoundVal> LCV =
2878 V.getAs<nonloc::LazyCompoundVal>()) {
2879 if (std::optional NewB = tryBindSmallStruct(B, R, RD, *LCV))
2881 return bindAggregate(B, R,
V);
2884 return bindAggregate(B, R,
V);
2890 return bindAggregate(B, R, UnknownVal());
2908 const nonloc::CompoundVal& CV =
V.
castAs<nonloc::CompoundVal>();
2911 LimitedRegionBindingsRef NewB = B;
2915 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
2923 assert((CRD->isAggregate() || (Ctx.
getLangOpts().ObjC && VI == VE)) &&
2924 "Non-aggregates are constructed with a constructor!");
2926 for (
const auto &B : CRD->bases()) {
2928 assert(!B.isVirtual() &&
"Aggregates cannot have virtual base classes!");
2935 QualType BTy = B.getType();
2939 assert(BRD &&
"Base classes must be C++ classes!");
2941 const CXXBaseObjectRegion *BR =
2942 MRMgr.getCXXBaseObjectRegion(BRD, R,
false);
2944 NewB = bindStruct(NewB, BR, *VI);
2961 if (FI->isUnnamedBitField())
2964 QualType FTy = FI->getType();
2965 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2968 NewB = bindArray(NewB, FR, *VI);
2970 NewB = bindStruct(NewB, FR, *VI);
2972 NewB = bind(NewB, loc::MemRegionVal(FR), *VI);
2981 NewB = NewB.
addBinding(R, BindingKey::Default,
2988LimitedRegionBindingsRef
2990 const TypedRegion *R, SVal Val) {
2991 llvm::TimeTraceScope TimeScope(
"RegionStoreManager::bindAggregate",
2992 [R]() {
return R->getDescriptiveName(); });
2998 return removeSubRegionBindings(B, R).
addBinding(R, BindingKey::Default, Val);
3006class RemoveDeadBindingsWorker
3007 :
public ClusterAnalysis<RemoveDeadBindingsWorker> {
3008 SmallVector<const SymbolicRegion *, 12> Postponed;
3009 SymbolReaper &SymReaper;
3010 const StackFrame *CurrentSF;
3013 RemoveDeadBindingsWorker(RegionStoreManager &rm,
3014 ProgramStateManager &stateMgr, RegionBindingsRef b,
3015 SymbolReaper &symReaper,
const StackFrame *SF)
3016 : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr, b),
3017 SymReaper(symReaper), CurrentSF(SF) {}
3020 void VisitAddedToCluster(
const MemRegion *baseR,
const ClusterBindings &
C);
3022 using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
3024 using ClusterAnalysis::AddToWorkList;
3026 bool AddToWorkList(
const MemRegion *R);
3028 bool UpdatePostponed();
3029 void VisitBinding(SVal
V);
3033bool RemoveDeadBindingsWorker::AddToWorkList(
const MemRegion *R) {
3034 const MemRegion *BaseR =
R->getBaseRegion();
3035 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
3038void RemoveDeadBindingsWorker::VisitAddedToCluster(
const MemRegion *baseR,
3041 if (
const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
3042 if (SymReaper.
isLive(VR))
3043 AddToWorkList(baseR, &
C);
3048 if (
const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
3049 if (SymReaper.
isLive(SR->getSymbol()))
3050 AddToWorkList(SR, &
C);
3052 Postponed.push_back(SR);
3058 AddToWorkList(baseR, &
C);
3063 if (
const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
3064 const auto *StackReg =
3066 const StackFrame *RegSF = StackReg->getStackFrame();
3067 if (CurrentSF && (RegSF == CurrentSF || RegSF->
isParentOf(CurrentSF)))
3068 AddToWorkList(TR, &
C);
3072void RemoveDeadBindingsWorker::VisitCluster(
const MemRegion *baseR,
3079 if (
const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
3080 SymReaper.
markLive(SymR->getSymbol());
3082 for (
const auto &[Key, Val] : *
C) {
3090void RemoveDeadBindingsWorker::VisitBinding(SVal
V) {
3093 if (
auto LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
3096 for (SVal
V : RM.getInterestingValues(*LCS)) {
3097 if (
auto DepLCS =
V.getAs<nonloc::LazyCompoundVal>())
3107 if (
const MemRegion *R =
V.getAsRegion()) {
3112 if (
const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
3113 for (
auto Var : BR->referenced_vars())
3114 AddToWorkList(Var.getCapturedRegion());
3124bool RemoveDeadBindingsWorker::UpdatePostponed() {
3129 for (
const SymbolicRegion *SR : Postponed) {
3130 if (SymReaper.
isLive(SR->getSymbol())) {
3139StoreRef RegionStoreManager::removeDeadBindings(
Store store,
3140 const StackFrame *SF,
3141 SymbolReaper &SymReaper) {
3142 RegionBindingsRef B = getRegionBindings(store);
3143 RemoveDeadBindingsWorker W(*
this, StateMgr, B, SymReaper, SF);
3144 W.GenerateClusters();
3147 for (
const MemRegion *Reg : SymReaper.
regions()) {
3148 W.AddToWorkList(Reg);
3151 do W.RunWorkList();
while (W.UpdatePostponed());
3156 for (
const MemRegion *Base : llvm::make_first_range(B)) {
3159 if (!W.isVisited(Base))
3160 B = B.removeCluster(Base);
3163 return StoreRef(B.asStore(), *
this);
3170void RegionStoreManager::printJson(raw_ostream &Out,
Store S,
const char *NL,
3171 unsigned int Space,
bool IsDot)
const {
3172 RegionBindingsRef
Bindings = getRegionBindings(S);
3174 Indent(Out, Space, IsDot) <<
"\"store\": ";
3177 Out <<
"null," << NL;
3181 Out <<
"{ \"pointer\": \"" <<
Bindings.asStore() <<
"\", \"items\": [" << NL;
3182 Bindings.printJson(Out, NL, Space + 1, IsDot);
3183 Indent(Out, Space, IsDot) <<
"]}," << NL;
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Result
Implement __builtin_bit_cast and related operations.
static std::optional< SVal > convertOffsetsFromSvalToUnsigneds(const SmallVector< SVal, 2 > &SrcOffsets, const SmallVector< uint64_t, 2 > ArrayExtents, SmallVector< uint64_t, 2 > &DstOffsets)
llvm::ImmutableMap< const MemRegion *, ClusterBindings > RegionBindings
static std::optional< SVal > getDerivedSymbolForBinding(RegionBindingsConstRef B, const TypedValueRegion *BaseRegion, const TypedValueRegion *SubReg, const ASTContext &Ctx, SValBuilder &SVB)
std::pair< BindingKey, SVal > BindingPair
static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields)
SmallVector< const FieldDecl *, 8 > FieldVector
llvm::ImmutableMap< BindingKey, SVal > ClusterBindings
static bool isUnionField(const FieldRegion *FR)
const LimitedRegionBindingsRef & LimitedRegionBindingsConstRef
static void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields)
static QualType getUnderlyingType(const SubRegion *R)
llvm::ImmutableMapRef< BindingKey, SVal > ClusterBindingsRef
static SmallVector< uint64_t, 2 > getConstantArrayExtents(const ConstantArrayType *CAT)
This is a helper function for getConstantValFromConstArrayInitializer.
static std::pair< SmallVector< SVal, 2 >, const MemRegion * > getElementRegionOffsetsWithBase(const ElementRegion *ER)
This is a helper function for getConstantValFromConstArrayInitializer.
const RegionBindingsRef & RegionBindingsConstRef
static std::optional< nonloc::LazyCompoundVal > getExistingLazyBinding(SValBuilder &SVB, RegionBindingsConstRef B, const SubRegion *R, bool AllowSubregionBindings)
Checks to see if store B has a lazy binding for region R.
static void collectSubRegionBindings(SmallVectorImpl< BindingPair > &Bindings, SValBuilder &SVB, const ClusterBindings &Cluster, const SubRegion *Top, BindingKey TopKey, bool IncludeAllDefaultBindings)
Collects all bindings in Cluster that may refer to bindings within Top.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
__PTRDIFF_TYPE__ ptrdiff_t
A signed integer type that is the result of subtracting two pointers.
This class represents the same as RegionBindingsRef, but with a limit on the number of bindings that ...
LimitedRegionBindingsRef removeCluster(const MemRegion *BaseRegion) const
LimitedRegionBindingsRef withValuesEscaped(nonloc::CompoundVal::iterator Begin, nonloc::CompoundVal::iterator End) const
LimitedRegionBindingsRef withValuesEscaped(SVal V) const
LimitedRegionBindingsRef(RegionBindingsRef Base, SmallVectorImpl< SVal > &EscapedValuesDuringBind, std::optional< unsigned > BindingsLeft)
bool hasExhaustedBindingLimit() const
LimitedRegionBindingsRef addBinding(BindingKey K, SVal V) const
LimitedRegionBindingsRef addBinding(const MemRegion *R, BindingKey::Kind k, SVal V) const
LimitedRegionBindingsRef addWithoutDecreasingLimit(const MemRegion *BaseRegion, data_type_ref BindingKeyAndValue) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const LangOptions & getLangOpts() const
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
QualType getElementType() const
Represents the canonical version of C arrays with a specified constant size.
uint64_t getLimitedSize() const
Return the size zero-extended to uint64_t or UINT64_MAX if the value is larger than UINT64_MAX.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isStringLiteralInit() const
Is this an initializer for an array of characters, initialized by a string literal or an @encode?
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
unsigned getNumInits() const
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
const Expr * getInit(unsigned Init) const
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool isConstQualified() const
Determine whether this type is const-qualified.
field_iterator field_end() const
field_range fields() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
specific_decl_iterator< FieldDecl > field_iterator
field_iterator field_begin() const
bool isParentOf(const StackFrame *SF) const
const Decl * getDecl() const
unsigned getLength() const
uint32_t getCodeUnit(size_t i) const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool isVoidPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isScalarType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
QualType getCanonicalTypeInternal() const
bool isStructureOrClassType() const
bool isVectorType() const
bool isRecordType() const
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
unsigned getNumElements() const
QualType getElementType() const
ElementRegion is used to represent both array elements and casts.
LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override
void dumpToStream(raw_ostream &Out) const
static bool isLocType(QualType T)
DefinedOrUnknownSVal getStaticSize(const MemRegion *MR, SValBuilder &SVB) const
MemRegion - The root abstract class for all memory regions.
virtual bool isBoundable() const
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
@ TK_PreserveContents
Tells that a region's contents is not changed.
@ TK_DoNotInvalidateSuperRegion
@ TK_EntireMemSpace
When applied to a MemSpaceRegion, indicates the entire memory space should be invalidated.
bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const
bool hasSymbolicOffset() const
const MemRegion * getRegion() const
It might return null.
int64_t getOffset() const
const MemRegion * getRegion() const
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
NonLoc makeArrayIndex(uint64_t idx)
ASTContext & getContext()
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy)
Cast a given SVal to another SVal using given QualType's.
DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, const TypedValueRegion *region)
loc::ConcreteInt makeNullWithType(QualType type)
Create NULL pointer, with proper pointer bit-width for given address space.
std::optional< SVal > getConstantVal(const Expr *E)
Returns the value of E, if it can be determined in a non-path-sensitive manner.
NonLoc makeZeroArrayIndex()
DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region)
Make a unique symbol for value of region.
NonLoc makeLazyCompoundVal(const StoreRef &store, const TypedValueRegion *region)
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const StackFrame *SF, unsigned count)
Create a new symbol with a unique 'name'.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
bool isZeroConstant() const
bool isUnknownOrUndef() const
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
bool scan(nonloc::LazyCompoundVal val)
SmallVector< const MemRegion *, 8 > InvalidatedRegions
SubRegion - A region that subsets another larger region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
bool isSubRegionOf(const MemRegion *R) const override
Check if the region is a subregion of the given region.
MemRegionManager & getMemRegionManager() const override
llvm::iterator_range< symbol_iterator > symbols() const
static bool canSymbolicate(QualType T)
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
void markElementIndicesLive(const MemRegion *region)
void markLazilyCopied(const MemRegion *region)
bool isLive(SymbolRef sym)
llvm::iterator_range< RegionSetTy::const_iterator > regions() const
SymbolicRegion - A special, "non-concrete" region.
TypedValueRegion - An abstract class representing regions having a typed value.
virtual QualType getValueType() const =0
QualType getLocationType() const override
QualType getValueType() const override
const VarDecl * getDecl() const override=0
llvm::ImmutableList< SVal >::iterator iterator
Value representing integer constant.
While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...
LLVM_ATTRIBUTE_RETURNS_NONNULL const LazyCompoundValData * getCVData() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
This function itself is immaterial.
const void * getStore() const
It might return null.
Defines the clang::TargetInfo interface.
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, DeclRefExpr > declRefExpr
Matches expressions that refer to declarations.
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< Stmt > StatementMatcher
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
const SymExpr * SymbolRef
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
bool InitField(InterpState &S, CodePtr OpPC, uint32_t I)
1) Pops the value from the stack 2) Peeks a pointer from the stack 3) Pushes the value to field I of ...
The JSON file list parser is used to communicate input to InstallAPI.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
bool isa(CodeGen::Address addr)
CFGBlock::ConstCFGElementRef ConstCFGElementRef
@ Bind
'bind' clause, allowed on routine constructs.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ConceptReference *C)
Insertion operator for diagnostics.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Diagnostic wrappers for TextAPI types for error reporting.
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t