#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include <limits>
#include <optional>
#include <utility>
namespace {
class BindingKey {
public:
enum Kind {
Symbolic = 0x2,
};
private:
llvm::PointerIntPair<const MemRegion *, 2> P;
explicit BindingKey(
const SubRegion *r,
const SubRegion *
Base, Kind k)
assert(r &&
Base &&
"Must have known regions.");
assert(getConcreteOffsetRegion() ==
Base &&
"Failed to store base region");
}
explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
: P(r, k),
Data(offset) {
assert(r && "Must have known regions.");
assert(getOffset() == offset && "Failed to store offset");
assert((r == r->getBaseRegion() ||
"Not a base");
}
public:
bool isDirect()
const {
return P.getInt() &
Direct; }
bool isDefault() const { return !isDirect(); }
bool hasSymbolicOffset() const { return P.getInt() & Symbolic; }
const MemRegion *
getRegion()
const {
return P.getPointer(); }
uint64_t getOffset() const {
assert(!hasSymbolicOffset());
}
const SubRegion *getConcreteOffsetRegion() const {
assert(hasSymbolicOffset());
return reinterpret_cast<const SubRegion *
>(
static_cast<uintptr_t>(
Data));
}
const MemRegion *getBaseRegion() const {
if (hasSymbolicOffset())
return getConcreteOffsetRegion()->getBaseRegion();
}
void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddPointer(P.getOpaqueValue());
}
static BindingKey
Make(
const MemRegion *R, Kind k);
if (P.getOpaqueValue() <
X.P.getOpaqueValue())
return true;
if (P.getOpaqueValue() >
X.P.getOpaqueValue())
return false;
}
return P.getOpaqueValue() ==
X.P.getOpaqueValue() &&
}
LLVM_DUMP_METHOD
void dump()
const;
};
std::string locDescr(Loc L) {
std::string S;
llvm::raw_string_ostream OS(S);
L.dumpToStream(OS);
return OS.str();
}
}
BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
const RegionOffset &RO = R->getAsOffset();
if (RO.hasSymbolicOffset())
return BindingKey(RO.getRegion(), RO.getOffset(), k);
}
namespace llvm {
static inline raw_ostream &
operator<<(raw_ostream &Out, BindingKey K) {
Out <<
"\"kind\": \"" << (K.isDirect() ?
"Direct" :
"Default")
<< "\", \"offset\": ";
if (!K.hasSymbolicOffset())
else
}
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void BindingKey::dump() const { llvm::errs() << *this; }
#endif
typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
namespace {
class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,
ClusterBindings> {
ClusterBindings::Factory *CBFactory;
bool IsMainAnalysis;
public:
typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
ParentTy;
RegionBindingsRef(ClusterBindings::Factory &CBFactory,
const RegionBindings::TreeTy *T,
RegionBindings::TreeTy::Factory *F, bool IsMainAnalysis)
: RegionBindingsRef(ParentTy(
T, F), CBFactory, IsMainAnalysis) {}
RegionBindingsRef(const ParentTy &P, ClusterBindings::Factory &CBFactory,
bool IsMainAnalysis)
: ParentTy(P), CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
RegionBindingsRef removeCluster(const MemRegion *BaseRegion) const {
return RegionBindingsRef(ParentTy::remove(BaseRegion), *CBFactory,
IsMainAnalysis);
}
RegionBindingsRef addBinding(BindingKey K, SVal
V)
const;
RegionBindingsRef addBinding(const MemRegion *R,
BindingKey::Kind k, SVal
V)
const;
const SVal *lookup(BindingKey K) const;
const SVal *lookup(const MemRegion *R, BindingKey::Kind k) const;
RegionBindingsRef removeBinding(BindingKey K);
RegionBindingsRef removeBinding(const MemRegion *R,
BindingKey::Kind k);
RegionBindingsRef removeBinding(const MemRegion *R) {
return removeBinding(R, BindingKey::Direct).
removeBinding(R, BindingKey::Default);
}
std::optional<SVal> getDirectBinding(const MemRegion *R) const;
std::optional<SVal> getDefaultBinding(const MemRegion *R) const;
llvm::PointerIntPair<Store, 1, bool> Ptr = {
asImmutableMap().getRootWithoutRetain(), IsMainAnalysis};
return reinterpret_cast<Store>(Ptr.getOpaqueValue());
}
bool isMainAnalysis() const {
return IsMainAnalysis;
}
void printJson(raw_ostream &Out, const char *NL = "\n",
unsigned int Space = 0, bool IsDot = false) const {
using namespace llvm;
DenseMap<const MemRegion *, std::string> StringifyCache;
auto ToString = [&StringifyCache](const MemRegion *R) {
auto [Place, Inserted] = StringifyCache.try_emplace(R);
if (!Inserted)
return Place->second;
std::string Res;
raw_string_ostream
OS(Res);
Place->second = Res;
return Res;
};
using Cluster =
std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;
using Binding = std::pair<BindingKey, SVal>;
const auto MemSpaceBeforeRegionName = [&ToString](const Cluster *L,
const Cluster *R) {
if (isa<MemSpaceRegion>(L->first) && !isa<MemSpaceRegion>(R->first))
return true;
if (!isa<MemSpaceRegion>(L->first) && isa<MemSpaceRegion>(R->first))
return false;
return ToString(L->first) < ToString(R->first);
};
const auto SymbolicBeforeOffset = [&ToString](const BindingKey &L,
const BindingKey &R) {
if (L.hasSymbolicOffset() && !R.hasSymbolicOffset())
return true;
if (!L.hasSymbolicOffset() && R.hasSymbolicOffset())
return false;
if (L.hasSymbolicOffset() && R.hasSymbolicOffset())
return ToString(L.getRegion()) < ToString(R.getRegion());
return L.getOffset() < R.getOffset();
};
const auto DefaultBindingBeforeDirectBindings =
[&SymbolicBeforeOffset](const Binding *LPtr, const Binding *RPtr) {
const BindingKey &L = LPtr->first;
const BindingKey &R = RPtr->first;
if (L.isDefault() && !R.isDefault())
return true;
if (!L.isDefault() && R.isDefault())
return false;
assert(L.isDefault() == R.isDefault());
return SymbolicBeforeOffset(L, R);
};
const auto AddrOf = [](const auto &Item) { return &Item; };
std::vector<const Cluster *> SortedClusters;
SortedClusters.reserve(std::distance(begin(), end()));
append_range(SortedClusters, map_range(*this, AddrOf));
llvm::sort(SortedClusters, MemSpaceBeforeRegionName);
for (auto [Idx, C] : llvm::enumerate(SortedClusters)) {
<< "{ \"cluster\": \"" << BaseRegion << "\", \"pointer\": \""
<< (const void *)BaseRegion << "\", \"items\": [" << NL;
std::vector<const Binding *> SortedBindings;
append_range(SortedBindings, map_range(
Bindings, AddrOf));
llvm::sort(SortedBindings, DefaultBindingBeforeDirectBindings);
++Space;
for (auto [Idx, B] : llvm::enumerate(SortedBindings)) {
const auto &[Key,
Value] = *B;
Indent(Out, Space, IsDot) <<
"{ " << Key <<
", \"value\": ";
Value.printJson(Out,
true);
if (Idx != SortedBindings.size() - 1)
}
--Space;
Indent(Out, Space, IsDot) <<
"]}";
if (Idx != SortedClusters.size() - 1)
}
}
LLVM_DUMP_METHOD
void dump()
const { printJson(llvm::errs()); }
protected:
RegionBindingsRef
commitBindingsToCluster(const MemRegion *BaseRegion,
};
}
class LimitedRegionBindingsRef : public RegionBindingsRef {
public:
LimitedRegionBindingsRef(RegionBindingsRef Base,
SmallVectorImpl<SVal> &EscapedValuesDuringBind,
std::optional<unsigned> BindingsLeft)
: RegionBindingsRef(
Base),
EscapedValuesDuringBind(&EscapedValuesDuringBind),
BindingsLeft(BindingsLeft) {}
bool hasExhaustedBindingLimit() const {
return BindingsLeft.has_value() && BindingsLeft.value() == 0;
}
LimitedRegionBindingsRef withValuesEscaped(SVal
V)
const {
EscapedValuesDuringBind->push_back(
V);
return *this;
}
LimitedRegionBindingsRef
withValuesEscaped(nonloc::CompoundVal::iterator Begin,
nonloc::CompoundVal::iterator End) const {
for (SVal
V : llvm::make_range(Begin, End))
return *this;
}
LimitedRegionBindingsRef
addWithoutDecreasingLimit(const MemRegion *BaseRegion,
data_type_ref BindingKeyAndValue) const {
return LimitedRegionBindingsRef{RegionBindingsRef::commitBindingsToCluster(
BaseRegion, BindingKeyAndValue),
*EscapedValuesDuringBind, BindingsLeft};
}
LimitedRegionBindingsRef removeCluster(const MemRegion *BaseRegion) const {
return LimitedRegionBindingsRef{
RegionBindingsRef::removeCluster(BaseRegion), *EscapedValuesDuringBind,
BindingsLeft};
}
LimitedRegionBindingsRef addBinding(BindingKey K, SVal
V)
const {
std::optional<unsigned> NewBindingsLeft = BindingsLeft;
if (NewBindingsLeft.has_value()) {
assert(NewBindingsLeft.value() != 0);
NewBindingsLeft.value() -= 1;
if (NewBindingsLeft.value() == 0) {
K = BindingKey::Make(K.getRegion(), BindingKey::Default);
}
}
return LimitedRegionBindingsRef{RegionBindingsRef::addBinding(K,
V),
*EscapedValuesDuringBind, NewBindingsLeft};
}
LimitedRegionBindingsRef addBinding(const MemRegion *R, BindingKey::Kind k,
return addBinding(BindingKey::Make(R, k),
V);
}
private:
SmallVectorImpl<SVal> *EscapedValuesDuringBind;
std::optional<unsigned> BindingsLeft;
};
std::optional<SVal>
RegionBindingsRef::getDirectBinding(const MemRegion *R) const {
const SVal *
V = lookup(R, BindingKey::Direct);
return V ? std::optional<SVal>(*
V) : std::nullopt;
}
std::optional<SVal>
RegionBindingsRef::getDefaultBinding(const MemRegion *R) const {
const SVal *
V = lookup(R, BindingKey::Default);
return V ? std::optional<SVal>(*
V) : std::nullopt;
}
RegionBindingsRef RegionBindingsRef::commitBindingsToCluster(
return RegionBindingsRef(ParentTy::add(BaseRegion,
Bindings), *CBFactory,
IsMainAnalysis);
}
RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K, SVal
V)
const {
const MemRegion *
Base = K.getBaseRegion();
(ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
return commitBindingsToCluster(Base,
Bindings);
}
RegionBindingsRef RegionBindingsRef::addBinding(const MemRegion *R,
BindingKey::Kind k,
return addBinding(BindingKey::Make(R, k),
V);
}
const SVal *RegionBindingsRef::lookup(BindingKey K) const {
if (!Cluster)
return nullptr;
return Cluster->lookup(K);
}
const SVal *RegionBindingsRef::lookup(const MemRegion *R,
BindingKey::Kind k) const {
return lookup(BindingKey::Make(R, k));
}
RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
const MemRegion *
Base = K.getBaseRegion();
if (!Cluster)
return *this;
if (NewCluster.isEmpty())
return removeCluster(Base);
return commitBindingsToCluster(Base, NewCluster);
}
RegionBindingsRef RegionBindingsRef::removeBinding(const MemRegion *R,
BindingKey::Kind k){
return removeBinding(BindingKey::Make(R, k));
}
namespace {
class InvalidateRegionsWorker;
class RegionStoreManager : public StoreManager {
public:
RegionBindings::Factory RBFactory;
mutable ClusterBindings::Factory CBFactory;
typedef std::vector<SVal> SValListTy;
private:
typedef llvm::DenseMap<const LazyCompoundValData *,
SValListTy> LazyBindingsMapTy;
LazyBindingsMapTy LazyBindingsMap;
const unsigned SmallStructLimit;
const unsigned SmallArrayLimit;
const std::optional<unsigned> RegionStoreMaxBindingFanOutPlusOne;
void populateWorkList(InvalidateRegionsWorker &W,
ArrayRef<SVal> Values,
InvalidatedRegions *TopLevelRegions);
const AnalyzerOptions &getOptions() {
return StateMgr.getOwningEngine().getAnalysisManager().options;
}
public:
RegionStoreManager(ProgramStateManager &mgr)
: StoreManager(mgr), RBFactory(mgr.getAllocator()),
CBFactory(mgr.getAllocator()),
SmallStructLimit(getOptions().RegionStoreSmallStructLimit),
SmallArrayLimit(getOptions().RegionStoreSmallArrayLimit),
RegionStoreMaxBindingFanOutPlusOne([&]() -> std::optional<unsigned> {
unsigned FanOut = getOptions().RegionStoreMaxBindingFanOut;
assert(FanOut != std::numeric_limits<unsigned>::max());
if (FanOut == 0)
return std::nullopt;
return FanOut + 1 ;
}()) {}
LimitedRegionBindingsRef
QualType T);
SVal ArrayToPointer(Loc Array, QualType ElementTy) override;
StoreRef getInitialStore(const LocationContext *InitLoc) override {
bool IsMainAnalysis = false;
if (
const auto *FD = dyn_cast<FunctionDecl>(InitLoc->
getDecl()))
IsMainAnalysis = FD->isMain() && !Ctx.getLangOpts().CPlusPlus;
return StoreRef(RegionBindingsRef(RegionBindingsRef::ParentTy(
RBFactory.getEmptyMap(), RBFactory),
CBFactory, IsMainAnalysis)
.asStore(),
*this);
}
RegionBindingsRef
invalidateGlobalRegion(MemRegion::Kind K, ConstCFGElementRef Elem,
unsigned Count, const LocationContext *LCtx,
RegionBindingsRef B, InvalidatedRegions *Invalidated);
StoreRef invalidateRegions(Store store, ArrayRef<SVal> Values,
ConstCFGElementRef Elem, unsigned Count,
const LocationContext *LCtx,
const CallEvent *
Call,
InvalidatedSymbols &IS,
RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *Invalidated,
InvalidatedRegions *InvalidatedTopLevel) override;
bool scanReachableSymbols(Store S, const MemRegion *R,
ScanReachableSymbols &Callbacks) override;
LimitedRegionBindingsRef
std::optional<SVal>
const ElementRegion *R);
std::optional<SVal>
getSValFromInitListExpr(const InitListExpr *ILE,
const SmallVector<uint64_t, 2> &ConcreteOffsets,
QualType ElemT);
SVal getSValFromStringLiteral(const StringLiteral *SL, uint64_t Offset,
QualType ElemT);
public:
BindResult
Bind(Store store, Loc LV, SVal
V)
override {
llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
LimitedRegionBindingsRef BoundedBindings =
getRegionBindings(store, EscapedValuesDuringBind);
return BindResult{StoreRef(bind(BoundedBindings, LV,
V).asStore(), *
this),
std::move(EscapedValuesDuringBind)};
}
BindResult BindDefaultInitial(Store store, const MemRegion *R,
RegionBindingsRef B = getRegionBindings(store);
assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
"Double initialization!");
B = B.addBinding(BindingKey::Make(R, BindingKey::Default),
V);
return BindResult{
StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this), {}};
}
BindResult BindDefaultZero(Store store, const MemRegion *R) override {
if (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
if (BR->getDecl()->isEmpty())
return BindResult{StoreRef(store, *this), {}};
llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
LimitedRegionBindingsRef B =
getRegionBindings(store, EscapedValuesDuringBind);
SVal
V = svalBuilder.makeZeroVal(Ctx.CharTy);
B = removeSubRegionBindings(B, cast<SubRegion>(R));
B = B.
addBinding(BindingKey::Make(R, BindingKey::Default),
V);
return BindResult{
StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this),
std::move(EscapedValuesDuringBind)};
}
std::optional<LimitedRegionBindingsRef>
const RecordDecl *RD, nonloc::LazyCompoundVal LCV);
const TypedValueRegion *R, SVal
V);
const TypedValueRegion *R, SVal
V);
std::optional<LimitedRegionBindingsRef>
const ArrayType *AT, nonloc::LazyCompoundVal LCV);
const TypedValueRegion *R, SVal
V);
const TypedRegion *R, SVal DefaultVal);
StoreRef killBinding(Store ST, Loc L) override;
void incrementReferenceCount(Store store) override {
getRegionBindings(store).manualRetain();
}
void decrementReferenceCount(Store store) override {
getRegionBindings(store).manualRelease();
}
bool includedInBindings(Store store, const MemRegion *region) const override;
SVal getBinding(Store S, Loc L, QualType T) override {
return getBinding(getRegionBindings(S), L, T);
}
std::optional<SVal> getDefaultBinding(Store S, const MemRegion *R) override {
RegionBindingsRef B = getRegionBindings(S);
return B.getDefaultBinding(R->getBaseRegion());
}
SVal getBindingForLazySymbol(const TypedValueRegion *R);
const TypedValueRegion *R,
QualType Ty);
SVal getLazyBinding(const SubRegion *LazyBindingRegion,
RegionBindingsRef LazyBinding);
std::optional<SVal>
const MemRegion *superR,
const TypedValueRegion *R, QualType Ty);
std::pair<Store, const SubRegion *>
const SubRegion *originalRegion);
const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);
StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
SymbolReaper& SymReaper) override;
RegionBindingsRef getRegionBindings(Store store) const {
llvm::PointerIntPair<Store, 1, bool> Ptr;
Ptr.setFromOpaqueValue(const_cast<void *>(store));
return {CBFactory,
static_cast<const RegionBindings::TreeTy *>(Ptr.getPointer()),
RBFactory.getTreeFactory(), Ptr.getInt()};
}
LimitedRegionBindingsRef
getRegionBindings(Store store,
SmallVectorImpl<SVal> &EscapedValuesDuringBind) const {
return LimitedRegionBindingsRef(
getRegionBindings(store), EscapedValuesDuringBind,
RegionStoreMaxBindingFanOutPlusOne);
}
void printJson(raw_ostream &Out, Store S, const char *NL = "\n",
unsigned int Space = 0, bool IsDot = false) const override;
void iterBindings(Store store, BindingsHandler& f) override {
RegionBindingsRef B = getRegionBindings(store);
for (const auto &[Region, Cluster] : B) {
for (
const auto &[Key,
Value] : Cluster) {
if (!Key.isDirect())
continue;
if (const SubRegion *R = dyn_cast<SubRegion>(Key.getRegion())) {
if (!f.HandleBinding(*
this, store, R,
Value))
return;
}
}
}
}
};
}
std::unique_ptr<StoreManager>
ento::CreateRegionStoreManager(ProgramStateManager &StMgr) {
return std::make_unique<RegionStoreManager>(StMgr);
}
namespace {
enum GlobalsFilterKind {
GFK_None,
GFK_SystemOnly,
GFK_All
};
template <typename DERIVED>
class ClusterAnalysis {
protected:
typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
typedef const MemRegion * WorkListElement;
typedef SmallVector<WorkListElement, 10> WorkList;
llvm::SmallPtrSet<const ClusterBindings *, 16> Visited;
WorkList WL;
RegionStoreManager &RM;
ASTContext &Ctx;
SValBuilder &svalBuilder;
RegionBindingsRef B;
protected:
return B.lookup(R);
}
bool includeEntireMemorySpace(const MemRegion *Base) {
return false;
}
public:
ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
: RM(rm), Ctx(StateMgr.getContext()),
svalBuilder(StateMgr.getSValBuilder()), B(std::move(
b)) {}
RegionBindingsRef getRegionBindings() const { return B; }
bool isVisited(const MemRegion *R) {
return Visited.count(getCluster(R));
}
void GenerateClusters() {
for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
RI != RE; ++RI){
const MemRegion *
Base = RI.getKey();
assert(!Cluster.isEmpty() && "Empty clusters should be removed");
static_cast<DERIVED*>(this)->VisitAddedToCluster(Base, Cluster);
if (static_cast<DERIVED*>(this)->includeEntireMemorySpace(Base))
AddToWorkList(WorkListElement(Base), &Cluster);
}
}
if (C && !Visited.insert(C).second)
return false;
WL.push_back(E);
return true;
}
bool AddToWorkList(const MemRegion *R) {
return static_cast<DERIVED*>(this)->AddToWorkList(R);
}
void RunWorkList() {
while (!WL.empty()) {
WorkListElement E = WL.pop_back_val();
const MemRegion *BaseR = E;
static_cast<DERIVED*>(this)->VisitCluster(BaseR, getCluster(BaseR));
}
}
void VisitAddedToCluster(
const MemRegion *baseR,
const ClusterBindings &C) {}
bool Flag) {
static_cast<DERIVED*>(this)->VisitCluster(BaseR, C);
}
};
}
bool RegionStoreManager::scanReachableSymbols(Store S, const MemRegion *R,
ScanReachableSymbols &Callbacks) {
assert(R == R->getBaseRegion() && "Should only be called for base regions");
RegionBindingsRef B = getRegionBindings(S);
if (!Cluster)
return true;
for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
RI != RE; ++RI) {
if (!Callbacks.scan(RI.getData()))
return false;
}
return true;
}
return FR->getDecl()->getParent()->isUnion();
}
assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
const MemRegion *
Base = K.getConcreteOffsetRegion();
const MemRegion *R = K.getRegion();
while (R != Base) {
if (const FieldRegion *FR = dyn_cast<FieldRegion>(R))
Fields.push_back(FR->getDecl());
R = cast<SubRegion>(R)->getSuperRegion();
}
}
assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
if (Fields.empty())
return true;
ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
if (Delta >= 0)
return std::equal(FieldsInBindingKey.begin() + Delta,
FieldsInBindingKey.end(),
Fields.begin());
else
return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
Fields.begin() - Delta);
}
static void
const SubRegion *Top, BindingKey TopKey,
bool IncludeAllDefaultBindings) {
if (TopKey.hasSymbolicOffset()) {
Top = TopKey.getConcreteOffsetRegion();
TopKey = BindingKey::Make(Top, BindingKey::Default);
}
SVal Extent = Top->getMemRegionManager().getStaticSize(Top, SVB);
if (std::optional<nonloc::ConcreteInt> ExtentCI =
Extent.getAs<nonloc::ConcreteInt>()) {
const llvm::APSInt &ExtentInt = ExtentCI->getValue();
assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
Length = ExtentInt.getLimitedValue() * SVB.getContext().getCharWidth();
} else if (const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
if (FR->getDecl()->isBitField())
Length = FR->getDecl()->getBitWidthValue();
}
for (const auto &StoreEntry : Cluster) {
BindingKey NextKey = StoreEntry.first;
if (NextKey.getRegion() == TopKey.getRegion()) {
if (NextKey.getOffset() > TopKey.getOffset() &&
NextKey.getOffset() - TopKey.getOffset() < Length) {
} else if (NextKey.getOffset() == TopKey.getOffset()) {
if (IncludeAllDefaultBindings || NextKey.isDirect())
}
} else if (NextKey.hasSymbolicOffset()) {
const MemRegion *
Base = NextKey.getConcreteOffsetRegion();
if (Top->isSubRegionOf(Base) && Top != Base) {
if (IncludeAllDefaultBindings || NextKey.isDirect())
} else if (const SubRegion *BaseSR = dyn_cast<SubRegion>(Base)) {
if (BaseSR->isSubRegionOf(Top))
}
}
}
}
static void
const SubRegion *Top, bool IncludeAllDefaultBindings) {
BindingKey::Make(Top, BindingKey::Default),
IncludeAllDefaultBindings);
}
LimitedRegionBindingsRef
const SubRegion *Top) {
BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
const MemRegion *ClusterHead = TopKey.getBaseRegion();
if (Top == ClusterHead) {
}
if (!Cluster) {
if (TopKey.hasSymbolicOffset()) {
const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
return B.
addBinding(Concrete, BindingKey::Default, UnknownVal());
}
return B;
}
false);
for (BindingKey Key : llvm::make_first_range(
Bindings))
if (TopKey.hasSymbolicOffset()) {
const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
Result =
Result.add(BindingKey::Make(Concrete, BindingKey::Default),
UnknownVal());
}
}
namespace {
class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
{
unsigned Count;
const LocationContext *LCtx;
RegionAndSymbolInvalidationTraits &ITraits;
StoreManager::InvalidatedRegions *Regions;
GlobalsFilterKind GlobalsFilter;
public:
InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
RegionBindingsRef
b, ConstCFGElementRef elem,
unsigned count, const LocationContext *lctx,
RegionAndSymbolInvalidationTraits &ITraitsIn,
StoreManager::InvalidatedRegions *r,
GlobalsFilterKind GFK)
: ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr,
b), Elem(elem),
Count(count), LCtx(lctx), IS(
is), ITraits(ITraitsIn), Regions(r),
GlobalsFilter(GFK) {}
void VisitBinding(SVal
V);
using ClusterAnalysis::AddToWorkList;
bool AddToWorkList(const MemRegion *R);
bool includeEntireMemorySpace(const MemRegion *Base);
bool isInitiallyIncludedGlobalRegion(const MemRegion *R);
};
}
bool InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
bool doNotInvalidateSuperRegion = ITraits.
hasTrait(
R, RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
const MemRegion *BaseR = doNotInvalidateSuperRegion ? R : R->getBaseRegion();
return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
}
void InvalidateRegionsWorker::VisitBinding(SVal
V) {
if (SymbolRef Sym =
V.getAsSymbol())
IS.insert(Sym);
if (
const MemRegion *R =
V.getAsRegion()) {
AddToWorkList(R);
return;
}
if (std::optional<nonloc::LazyCompoundVal> LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
for (SVal
V : RM.getInterestingValues(*LCS))
if (!isa<nonloc::LazyCompoundVal>(
V))
return;
}
}
void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
bool PreserveRegionsContents =
RegionAndSymbolInvalidationTraits::TK_PreserveContents);
if (C) {
for (SVal Val : llvm::make_second_range(*C))
VisitBinding(Val);
if (!PreserveRegionsContents)
}
if (const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
if (const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
using namespace ast_matchers;
const char *DeclBind = "DeclBind";
to(
varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
auto Matches =
match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
RD->getASTContext());
for (BoundNodes &Match : Matches) {
auto *VD =
Match.getNodeAs<VarDecl>(DeclBind);
const VarRegion *ToInvalidate =
RM.getRegionManager().getVarRegion(VD, LCtx);
AddToWorkList(ToInvalidate);
}
}
}
}
if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
for (auto Var : BR->referenced_vars()) {
const VarRegion *VR = Var.getCapturedRegion();
const VarDecl *VD = VR->getDecl();
AddToWorkList(VR);
}
else if (Loc::isLocType(VR->getValueType())) {
SVal
V = RM.getBinding(B, loc::MemRegionVal(VR));
if (std::optional<Loc> L =
V.getAs<Loc>()) {
if (const MemRegion *LR = L->getAsRegion())
AddToWorkList(LR);
}
}
}
return;
}
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
IS.insert(SR->getSymbol());
if (PreserveRegionsContents)
return;
if (Regions)
Regions->push_back(baseR);
if (isa<AllocaRegion, SymbolicRegion>(baseR)) {
svalBuilder.conjureSymbolVal(baseR, Elem, LCtx, Ctx.
IntTy, Count);
return;
}
if (!baseR->isBoundable())
return;
const TypedValueRegion *TR = cast<TypedValueRegion>(baseR);
QualType
T = TR->getValueType();
if (isInitiallyIncludedGlobalRegion(baseR)) {
return;
}
svalBuilder.conjureSymbolVal(baseR, Elem, LCtx, Ctx.
IntTy, Count);
return;
}
bool doNotInvalidateSuperRegion = ITraits.
hasTrait(
baseR,
RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
if (doNotInvalidateSuperRegion) {
std::optional<uint64_t> NumElements;
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
NumElements = CAT->getZExtSize();
if (!NumElements)
goto conjure_default;
QualType ElementTy = AT->getElementType();
const RegionOffset &RO = baseR->getAsOffset();
const MemRegion *SuperR = baseR->getBaseRegion();
if (RO.hasSymbolicOffset()) {
if (SuperR)
AddToWorkList(SuperR);
goto conjure_default;
}
uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
bool UpperOverflow = UpperOffset < LowerOffset;
if (!SuperR)
goto conjure_default;
if (!C)
goto conjure_default;
for (
const auto &[BK,
V] : *C) {
std::optional<uint64_t> ROffset =
BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
if (!ROffset ||
((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
(UpperOverflow &&
(*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
(LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
B = B.removeBinding(BK);
const MemRegion *R =
V.getAsRegion();
if (isa_and_nonnull<SymbolicRegion>(R))
}
}
}
conjure_default:
DefinedOrUnknownSVal
V = svalBuilder.conjureSymbolVal(
baseR, Elem, LCtx, AT->getElementType(), Count);
return;
}
svalBuilder.conjureSymbolVal(baseR, Elem, LCtx, T, Count);
assert(SymbolManager::canSymbolicate(T) ||
V.isUnknown());
}
bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
const MemRegion *R) {
switch (GlobalsFilter) {
case GFK_None:
return false;
case GFK_SystemOnly:
return isa<GlobalSystemSpaceRegion>(R->getRawMemorySpace());
case GFK_All:
return isa<NonStaticGlobalSpaceRegion>(R->getRawMemorySpace());
}
llvm_unreachable("unknown globals filter");
}
bool InvalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
if (isInitiallyIncludedGlobalRegion(Base))
return true;
const MemSpaceRegion *MemSpace =
Base->getRawMemorySpace();
RegionAndSymbolInvalidationTraits::TK_EntireMemSpace);
}
RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
MemRegion::Kind K, ConstCFGElementRef Elem, unsigned Count,
const LocationContext *LCtx, RegionBindingsRef B,
InvalidatedRegions *Invalidated) {
const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
SVal
V = svalBuilder.conjureSymbolVal(
(const void *)GS, Elem, LCtx,
B = B.removeBinding(GS)
.addBinding(BindingKey::Make(GS, BindingKey::Default),
V);
if (Invalidated)
Invalidated->push_back(GS);
return B;
}
void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
ArrayRef<SVal> Values,
InvalidatedRegions *TopLevelRegions) {
if (
auto LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
for (SVal S : getInterestingValues(*LCS))
if (const MemRegion *R = S.getAsRegion())
W.AddToWorkList(R);
continue;
}
if (
const MemRegion *R =
V.getAsRegion()) {
if (TopLevelRegions)
TopLevelRegions->push_back(R);
W.AddToWorkList(R);
continue;
}
}
}
StoreRef RegionStoreManager::invalidateRegions(
Store store, ArrayRef<SVal> Values, ConstCFGElementRef Elem, unsigned Count,
const LocationContext *LCtx,
const CallEvent *
Call, InvalidatedSymbols &IS,
RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
GlobalsFilterKind GlobalsFilter;
if (
Call->isInSystemHeader())
GlobalsFilter = GFK_SystemOnly;
else
GlobalsFilter = GFK_All;
} else {
GlobalsFilter = GFK_None;
}
RegionBindingsRef B = getRegionBindings(store);
InvalidateRegionsWorker W(*this, StateMgr, B, Elem, Count, LCtx, IS, ITraits,
Invalidated, GlobalsFilter);
W.GenerateClusters();
populateWorkList(W, Values, TopLevelRegions);
W.RunWorkList();
B = W.getRegionBindings();
switch (GlobalsFilter) {
case GFK_All:
B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, Elem,
Count, LCtx, B, Invalidated);
[[fallthrough]];
case GFK_SystemOnly:
B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, Elem,
Count, LCtx, B, Invalidated);
[[fallthrough]];
case GFK_None:
break;
}
return StoreRef(B.asStore(), *this);
}
SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {
if (isa<loc::ConcreteInt>(Array))
return Array;
if (!isa<loc::MemRegionVal>(Array))
return UnknownVal();
const SubRegion *R =
cast<SubRegion>(Array.castAs<loc::MemRegionVal>().getRegion());
NonLoc ZeroIdx = svalBuilder.makeZeroArrayIndex();
return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
}
assert(!isa<UnknownVal>(L) && "location unknown");
assert(!isa<UndefinedVal>(L) && "location undefined");
if (L.getAs<loc::ConcreteInt>()) {
return UnknownVal();
}
if (!L.getAs<loc::MemRegionVal>()) {
return UnknownVal();
}
const MemRegion *MR = L.castAs<loc::MemRegionVal>().
getRegion();
if (isa<BlockDataRegion>(MR)) {
return UnknownVal();
}
if (const auto *TVR = dyn_cast<TypedValueRegion>(MR))
else if (const auto *TR = dyn_cast<TypedRegion>(MR))
else if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
T = SR->getPointeeStaticType();
}
assert(!
T.isNull() &&
"Unable to auto-detect binding type!");
assert(!
T->
isVoidType() &&
"Attempting to dereference a void pointer!");
if (!isa<TypedValueRegion>(MR))
MR = GetElementZeroRegion(cast<SubRegion>(MR), T);
const TypedValueRegion *R = cast<TypedValueRegion>(MR);
QualType RTy = R->getValueType();
return UnknownVal();
return getBindingForStruct(B, R);
return createLazyBinding(B, R);
return getBindingForArray(B, R);
else
return UnknownVal();
}
return UnknownVal();
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
return svalBuilder.evalCast(getBindingForField(B, FR), T, QualType{});
if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
return svalBuilder.evalCast(getBindingForElement(B, ER), T, QualType{});
}
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
return svalBuilder.evalCast(getBindingForObjCIvar(B, IVR), T, QualType{});
}
if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
return svalBuilder.evalCast(getBindingForVar(B, VR), T, QualType{});
}
const SVal *
V = B.lookup(R, BindingKey::Direct);
if (isa<StackLocalsSpaceRegion>(R->getRawMemorySpace())) {
return UndefinedVal();
}
return svalBuilder.getRegionValueSymbolVal(R);
}
QualType RegionTy;
if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R))
RegionTy = TVR->getValueType();
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
RegionTy = SR->getSymbol()->getType();
return RegionTy;
}
static std::optional<nonloc::LazyCompoundVal>
const SubRegion *R, bool AllowSubregionBindings) {
std::optional<SVal>
V = B.getDefaultBinding(R);
return std::nullopt;
std::optional<nonloc::LazyCompoundVal> LCV =
V->getAs<nonloc::LazyCompoundVal>();
if (!LCV)
return std::nullopt;
QualType SourceRegionTy = LCV->getRegion()->getValueType();
if (!SVB.getContext().hasSameUnqualifiedType(RegionTy, SourceRegionTy))
return std::nullopt;
}
if (!AllowSubregionBindings) {
true);
return std::nullopt;
}
return *LCV;
}
std::pair<Store, const SubRegion *>
const SubRegion *R,
const SubRegion *originalRegion) {
if (originalRegion != R) {
if (std::optional<nonloc::LazyCompoundVal>
V =
return std::make_pair(
V->getStore(),
V->getRegion());
}
typedef std::pair<Store, const SubRegion *> StoreRegionPair;
StoreRegionPair
Result = StoreRegionPair();
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
Result = findLazyBinding(B, cast<SubRegion>(ER->getSuperRegion()),
originalRegion);
Result.second = MRMgr.getElementRegionWithSuper(ER,
Result.second);
} else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
Result = findLazyBinding(B, cast<SubRegion>(FR->getSuperRegion()),
originalRegion);
Result.second = MRMgr.getFieldRegionWithSuper(FR,
Result.second);
} else if (const CXXBaseObjectRegion *BaseReg =
dyn_cast<CXXBaseObjectRegion>(R)) {
Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
originalRegion);
Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
}
}
static SmallVector<uint64_t, 2>
assert(CAT && "ConstantArrayType should not be null");
SmallVector<uint64_t, 2> Extents;
do {
return Extents;
}
static std::pair<SmallVector<SVal, 2>, const MemRegion *>
assert(ER && "ConstantArrayType should not be null");
SmallVector<SVal, 2> SValOffsets;
do {
SValOffsets.push_back(ER->getIndex());
Base = ER->getSuperRegion();
ER = dyn_cast<ElementRegion>(Base);
} while (ER);
return {SValOffsets,
Base};
}
static std::optional<SVal>
const SmallVector<uint64_t, 2> ArrayExtents,
SmallVector<uint64_t, 2> &DstOffsets) {
DstOffsets.resize(SrcOffsets.size());
auto ExtentIt = ArrayExtents.begin();
auto OffsetIt = DstOffsets.begin();
for (SVal
V : llvm::reverse(SrcOffsets)) {
if (
auto CI =
V.getAs<nonloc::ConcreteInt>()) {
const llvm::APSInt &Offset = CI->getValue();
if (Offset.isNegative() || Offset.uge(*(ExtentIt++)))
return UndefinedVal();
*(OffsetIt++) = Offset.getZExtValue();
continue;
}
return UnknownVal();
}
return std::nullopt;
}
std::optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer(
assert(R && "ElementRegion should not be null");
SmallVector<SVal, 2> SValOffsets;
const VarRegion *VR = dyn_cast<VarRegion>(Base);
if (!VR)
return std::nullopt;
assert(!SValOffsets.empty() && "getElementRegionOffsets guarantees the "
"offsets vector is not empty.");
const VarDecl *VD = VR->getDecl();
!R->getElementType().isConstQualified() &&
return std::nullopt;
if (!Init)
return std::nullopt;
if (!CAT)
return std::nullopt;
if (SValOffsets.size() != Extents.size())
return std::nullopt;
SmallVector<uint64_t, 2> ConcreteOffsets;
SValOffsets, Extents, ConcreteOffsets))
if (const auto *ILE = dyn_cast<InitListExpr>(Init))
return getSValFromInitListExpr(ILE, ConcreteOffsets, R->getElementType());
if (const auto *SL = dyn_cast<StringLiteral>(Init))
return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
R->getElementType());
return std::nullopt;
}
std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
const InitListExpr *ILE, const SmallVector<uint64_t, 2> &Offsets,
QualType ElemT) {
assert(ILE && "InitListExpr should not be null");
for (uint64_t Offset : Offsets) {
if (
const auto *SL = dyn_cast<StringLiteral>(ILE->
getInit(0)))
return getSValFromStringLiteral(SL, Offset, ElemT);
return svalBuilder.makeZeroVal(ElemT);
const Expr *E = ILE->
getInit(Offset);
const auto *IL = dyn_cast<InitListExpr>(E);
if (!IL)
return svalBuilder.getConstantVal(E);
ILE = IL;
}
assert(ILE);
return std::nullopt;
}
SVal RegionStoreManager::getSValFromStringLiteral(const StringLiteral *SL,
uint64_t Offset,
QualType ElemT) {
assert(SL && "StringLiteral should not be null");
uint32_t Code = (Offset >= SL->getLength()) ? 0 : SL->getCodeUnit(Offset);
return svalBuilder.makeIntVal(Code, ElemT);
}
const TypedValueRegion *SubReg, const ASTContext &Ctx, SValBuilder &SVB) {
assert(BaseRegion);
QualType BaseTy = BaseRegion->getValueType();
QualType Ty = SubReg->getValueType();
if (const std::optional<SVal> &ParentValue =
B.getDirectBinding(BaseRegion)) {
if (SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
return SVB.getDerivedRegionValueSymbolVal(ParentValueAsSym, SubReg);
if (ParentValue->isUndef())
return UndefinedVal();
return UnknownVal();
}
}
}
return std::nullopt;
}
const ElementRegion* R) {
if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
const MemRegion* superR = R->getSuperRegion();
if (const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
return UnknownVal();
if (const auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {
const llvm::APSInt &Idx = CI->getValue();
if (Idx < 0)
return UndefinedVal();
const StringLiteral *SL = StrR->getStringLiteral();
return getSValFromStringLiteral(SL, Idx.getZExtValue(), T);
}
} else if (isa<ElementRegion, VarRegion>(superR)) {
if (std::optional<SVal>
V = getConstantValFromConstArrayInitializer(B, R))
}
if (isa<CodeTextRegion>(superR))
return UnknownVal();
const RegionRawOffset &O = R->getAsArrayOffset();
if (!O.getRegion())
return UnknownVal();
if (const TypedValueRegion *baseR = dyn_cast<TypedValueRegion>(O.getRegion()))
return getBindingForFieldOrElementCommon(B, R, R->getElementType());
}
const FieldRegion* R) {
if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
const FieldDecl *FD = R->getDecl();
QualType Ty = FD->getType();
const MemRegion* superR = R->getSuperRegion();
if (const auto *VR = dyn_cast<VarRegion>(superR)) {
const VarDecl *VD = VR->getDecl();
QualType RecordVarTy = VD->
getType();
if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
if (Index < InitList->getNumInits()) {
if (const Expr *FieldInit = InitList->getInit(Index))
if (std::optional<SVal>
V = svalBuilder.getConstantVal(FieldInit))
} else {
return svalBuilder.makeZeroVal(Ty);
}
}
}
if (const auto *Base = dyn_cast<TypedValueRegion>(R->getBaseRegion()))
return getBindingForFieldOrElementCommon(B, R, Ty);
}
std::optional<SVal> RegionStoreManager::getBindingForDerivedDefaultValue(
const TypedValueRegion *R, QualType Ty) {
if (const std::optional<SVal> &D = B.getDefaultBinding(superR)) {
SVal val = *D;
if (SymbolRef parentSym = val.getAsSymbol())
return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
if (val.isZeroConstant())
return svalBuilder.makeZeroVal(Ty);
if (val.isUnknownOrUndef())
return val;
if (isa<nonloc::LazyCompoundVal, nonloc::CompoundVal>(val))
return val;
llvm_unreachable("Unknown default value");
}
return std::nullopt;
}
SVal RegionStoreManager::getLazyBinding(const SubRegion *LazyBindingRegion,
RegionBindingsRef LazyBinding) {
if (const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
Result = getBindingForElement(LazyBinding, ER);
else
Result = getBindingForField(LazyBinding,
cast<FieldRegion>(LazyBindingRegion));
}
SVal
const TypedValueRegion *R,
QualType Ty) {
Store lazyBindingStore =
nullptr;
const SubRegion *lazyBindingRegion = nullptr;
std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
if (lazyBindingRegion)
return getLazyBinding(lazyBindingRegion,
getRegionBindings(lazyBindingStore));
bool hasSymbolicIndex = false;
bool hasPartialLazyBinding = false;
const SubRegion *SR = R;
while (SR) {
const MemRegion *
Base = SR->getSuperRegion();
if (std::optional<SVal> D =
getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
if (D->getAs<nonloc::LazyCompoundVal>()) {
hasPartialLazyBinding = true;
break;
}
return *D;
}
if (const ElementRegion *ER = dyn_cast<ElementRegion>(Base)) {
NonLoc index = ER->getIndex();
if (!index.isConstant())
hasSymbolicIndex = true;
}
SR = dyn_cast<SubRegion>(Base);
}
if (isa<StackLocalsSpaceRegion>(R->getRawMemorySpace())) {
if (isa<ElementRegion>(R)) {
if (const TypedValueRegion *typedSuperR =
dyn_cast<TypedValueRegion>(R->getSuperRegion())) {
if (typedSuperR->getValueType()->isVectorType())
return UnknownVal();
}
}
if (hasSymbolicIndex)
return UnknownVal();
if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->getBaseRegion())) {
if (
const std::optional<SVal> &
V = B.getDefaultBinding(R))
return UndefinedVal();
}
}
return svalBuilder.getRegionValueSymbolVal(R);
}
const ObjCIvarRegion* R) {
if (
const std::optional<SVal> &
V = B.getDirectBinding(R))
const MemRegion *superR = R->getSuperRegion();
if (
const std::optional<SVal> &
V = B.getDefaultBinding(superR)) {
if (SymbolRef parentSym =
V->getAsSymbol())
return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
return UnknownVal();
}
return getBindingForLazySymbol(R);
}
const VarRegion *R) {
if (std::optional<SVal>
V = B.getDirectBinding(R))
if (std::optional<SVal>
V = B.getDefaultBinding(R))
const VarDecl *VD = R->getDecl();
const MemSpaceRegion *MS = R->getRawMemorySpace();
if (isa<StackArgumentsSpaceRegion>(MS))
return svalBuilder.getRegionValueSymbolVal(R);
if (std::optional<SVal>
V = svalBuilder.getConstantVal(Init))
return UnknownVal();
}
}
if (isa<UnknownSpaceRegion>(MS))
return svalBuilder.getRegionValueSymbolVal(R);
if (isa<GlobalsSpaceRegion>(MS)) {
if (B.isMainAnalysis())
if (std::optional<SVal>
V = svalBuilder.getConstantVal(Init))
if (isa<StaticGlobalSpaceRegion>(MS))
return svalBuilder.makeZeroVal(T);
if (std::optional<SVal>
V = getBindingForDerivedDefaultValue(B, MS, R, T)) {
assert(!
V->getAs<nonloc::LazyCompoundVal>());
}
return svalBuilder.getRegionValueSymbolVal(R);
}
return UndefinedVal();
}
SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) {
return svalBuilder.getRegionValueSymbolVal(R);
}
const RegionStoreManager::SValListTy &
RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.getCVData());
if (I != LazyBindingsMap.end())
return I->second;
SValListTy List;
const SubRegion *LazyR = LCV.getRegion();
RegionBindingsRef B = getRegionBindings(LCV.getStore());
if (!Cluster)
return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
true);
for (SVal
V : llvm::make_second_range(
Bindings)) {
if (
V.isUnknownOrUndef() ||
V.isConstant())
continue;
if (
auto InnerLCV =
V.getAs<nonloc::LazyCompoundVal>()) {
const SValListTy &InnerList = getInterestingValues(*InnerLCV);
llvm::append_range(List, InnerList);
}
}
return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
}
const TypedValueRegion *R) {
if (std::optional<nonloc::LazyCompoundVal>
V =
return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R);
}
const TypedValueRegion *R) {
const RecordDecl *RD =
R->getValueType()->castAsCanonical<RecordType>()->getDecl();
return UnknownVal();
return createLazyBinding(B, R);
}
const TypedValueRegion *R) {
"Only constant array types can have compound bindings.");
return createLazyBinding(B, R);
}
bool RegionStoreManager::includedInBindings(Store store,
const MemRegion *region) const {
RegionBindingsRef B = getRegionBindings(store);
region = region->getBaseRegion();
if (B.lookup(region))
return true;
for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
CI != CE; ++CI) {
SVal D = CI.getData();
if (const MemRegion *R = D.getAsRegion())
if (R->getBaseRegion() == region)
return true;
}
}
return false;
}
StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {
if (std::optional<loc::MemRegionVal> LV = L.getAs<loc::MemRegionVal>())
if (const MemRegion* R = LV->getRegion())
return StoreRef(getRegionBindings(ST)
.removeBinding(R)
.asImmutableMap()
.getRootWithoutRetain(),
*this);
return StoreRef(ST, *this);
}
LimitedRegionBindingsRef
llvm::TimeTraceScope TimeScope("RegionStoreManager::bind",
[&L]() { return locDescr(L); });
auto MemRegVal = L.getAs<loc::MemRegionVal>();
if (!MemRegVal)
return B;
const MemRegion *R = MemRegVal->getRegion();
if (const auto *SymReg = dyn_cast<SymbolicRegion>(R)) {
QualType Ty = SymReg->getPointeeStaticType();
Ty = StateMgr.getContext().CharTy;
R = GetElementZeroRegion(SymReg, Ty);
}
if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
QualType Ty = TR->getValueType();
return bindArray(B, TR,
V);
return bindStruct(B, TR,
V);
return bindVector(B, TR,
V);
return bindAggregate(B, TR,
V);
}
assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
"'this' pointer is not an l-value and is not assignable");
auto NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
auto KeyKind = isa<nonloc::LazyCompoundVal>(
V) ? BindingKey::Default
: BindingKey::Direct;
return NewB.addBinding(BindingKey::Make(R, KeyKind),
V);
}
LimitedRegionBindingsRef
const MemRegion *R, QualType T) {
return B;
if (Loc::isLocType(T))
V = svalBuilder.makeNullWithType(T);
V = svalBuilder.makeZeroVal(T);
V = svalBuilder.makeZeroVal(Ctx.
IntTy);
}
else {
assert(!SymbolManager::canSymbolicate(T) && "This type is representable");
}
}
std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallArray(
const ArrayType *AT, nonloc::LazyCompoundVal LCV) {
auto CAT = dyn_cast<ConstantArrayType>(AT);
if (!CAT)
return std::nullopt;
return std::nullopt;
if (ArrSize > SmallArrayLimit)
return std::nullopt;
LimitedRegionBindingsRef NewB = B;
for (uint64_t i = 0; i < ArrSize; ++i) {
auto Idx = svalBuilder.makeArrayIndex(i);
const ElementRegion *SrcER =
MRMgr.getElementRegion(Ty, Idx, LCV.getRegion(), Ctx);
SVal
V = getBindingForElement(getRegionBindings(LCV.getStore()), SrcER);
const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
NewB = bind(NewB, loc::MemRegionVal(DstER),
V);
}
return NewB;
}
LimitedRegionBindingsRef
const TypedValueRegion *R, SVal Init) {
llvm::TimeTraceScope TimeScope("RegionStoreManager::bindArray",
[R]() { return R->getDescriptiveName(); });
std::optional<uint64_t>
Size;
if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
if (std::optional<loc::MemRegionVal> MRV =
Init.getAs<loc::MemRegionVal>()) {
SVal
V = getBinding(B.asStore(), *MRV, R->getValueType());
return bindAggregate(B, R,
V);
}
return bindAggregate(B, R, Init);
if (std::optional LCV =
Init.getAs<nonloc::LazyCompoundVal>()) {
if (std::optional NewB = tryBindSmallArray(B, R, AT, *LCV))
return *NewB;
return bindAggregate(B, R, Init);
}
if (isa<nonloc::SymbolVal>(Init))
return bindAggregate(B, R, Init);
return bindAggregate(B, R, UnknownVal());
const nonloc::CompoundVal& CV =
Init.castAs<nonloc::CompoundVal>();
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
LimitedRegionBindingsRef NewB = B;
for (;
Size ? i < *
Size :
true; ++i, ++VI) {
if (VI == VE)
break;
NonLoc Idx = svalBuilder.makeArrayIndex(i);
const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
NewB = bindStruct(NewB, ER, *VI);
NewB = bindArray(NewB, ER, *VI);
else
NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
}
if (!Size || i < *Size)
NewB = setImplicitDefaultValue(NewB, R, ElementTy);
return NewB;
}
LimitedRegionBindingsRef
const TypedValueRegion *R, SVal
V) {
llvm::TimeTraceScope TimeScope("RegionStoreManager::bindVector",
[R]() { return R->getDescriptiveName(); });
QualType
T = R->getValueType();
const VectorType *VT =
T->
castAs<VectorType>();
if (isa<nonloc::LazyCompoundVal, nonloc::SymbolVal>(
V))
return bindAggregate(B, R,
V);
if (!isa<nonloc::CompoundVal>(
V)) {
return bindAggregate(B, R, UnknownVal());
}
nonloc::CompoundVal CV =
V.castAs<nonloc::CompoundVal>();
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
LimitedRegionBindingsRef NewB = B;
for ( ; index != numElements ; ++index) {
if (VI == VE)
break;
NonLoc Idx = svalBuilder.makeArrayIndex(index);
const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
NewB = bindArray(NewB, ER, *VI);
NewB = bindStruct(NewB, ER, *VI);
else
NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
}
return NewB;
}
std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
const RecordDecl *RD, nonloc::LazyCompoundVal LCV) {
if (const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
if (
Class->getNumBases() != 0 ||
Class->getNumVBases() != 0)
return std::nullopt;
for (
const auto *FD : RD->
fields()) {
continue;
if (Fields.size() == SmallStructLimit)
return std::nullopt;
QualType Ty = FD->getType();
continue;
return std::nullopt;
Fields.push_back(FD);
}
LimitedRegionBindingsRef NewB = B;
for (const FieldDecl *Field : Fields) {
const FieldRegion *SourceFR = MRMgr.getFieldRegion(Field, LCV.getRegion());
SVal
V = getBindingForField(getRegionBindings(LCV.getStore()), SourceFR);
const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
NewB = bind(NewB, loc::MemRegionVal(DestFR),
V);
}
return NewB;
}
LimitedRegionBindingsRef
const TypedValueRegion *R, SVal
V) {
llvm::TimeTraceScope TimeScope("RegionStoreManager::bindStruct",
[R]() { return R->getDescriptiveName(); });
QualType
T = R->getValueType();
return B;
if (std::optional<nonloc::LazyCompoundVal> LCV =
V.getAs<nonloc::LazyCompoundVal>()) {
if (std::optional NewB = tryBindSmallStruct(B, R, RD, *LCV))
return *NewB;
return bindAggregate(B, R,
V);
}
if (isa<nonloc::SymbolVal>(
V))
return bindAggregate(B, R,
V);
if (
V.isUnknown() || !isa<nonloc::CompoundVal>(
V))
return bindAggregate(B, R, UnknownVal());
const nonloc::CompoundVal& CV =
V.castAs<nonloc::CompoundVal>();
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
LimitedRegionBindingsRef NewB = B;
if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
assert((CRD->isAggregate() || (Ctx.
getLangOpts().ObjC && VI == VE)) &&
"Non-aggregates are constructed with a constructor!");
for (const auto &B : CRD->bases()) {
assert(!B.isVirtual() && "Aggregates cannot have virtual base classes!");
if (VI == VE)
break;
QualType BTy = B.getType();
assert(BRD && "Base classes must be C++ classes!");
const CXXBaseObjectRegion *BR =
MRMgr.getCXXBaseObjectRegion(BRD, R, false);
NewB = bindStruct(NewB, BR, *VI);
++VI;
}
}
RecordDecl::field_iterator FI, FE;
if (VI == VE)
break;
if (FI->isUnnamedBitField())
continue;
QualType FTy = FI->getType();
const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
NewB = bindArray(NewB, FR, *VI);
NewB = bindStruct(NewB, FR, *VI);
else
NewB = bind(NewB, loc::MemRegionVal(FR), *VI);
++VI;
}
if (FI != FE) {
svalBuilder.makeIntVal(0, false));
}
return NewB;
}
LimitedRegionBindingsRef
const TypedRegion *R, SVal Val) {
llvm::TimeTraceScope TimeScope("RegionStoreManager::bindAggregate",
[R]() { return R->getDescriptiveName(); });
return removeSubRegionBindings(B, R).
addBinding(R, BindingKey::Default, Val);
}
namespace {
class RemoveDeadBindingsWorker
: public ClusterAnalysis<RemoveDeadBindingsWorker> {
SmallVector<const SymbolicRegion *, 12> Postponed;
SymbolReaper &SymReaper;
const StackFrameContext *CurrentLCtx;
public:
RemoveDeadBindingsWorker(RegionStoreManager &rm,
ProgramStateManager &stateMgr,
RegionBindingsRef
b, SymbolReaper &symReaper,
const StackFrameContext *LCtx)
: ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr,
b),
SymReaper(symReaper), CurrentLCtx(LCtx) {}
void VisitAddedToCluster(
const MemRegion *baseR,
const ClusterBindings &C);
using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
using ClusterAnalysis::AddToWorkList;
bool AddToWorkList(const MemRegion *R);
bool UpdatePostponed();
void VisitBinding(SVal
V);
};
}
bool RemoveDeadBindingsWorker::AddToWorkList(const MemRegion *R) {
const MemRegion *BaseR = R->getBaseRegion();
return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
}
void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
if (const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
AddToWorkList(baseR, &C);
return;
}
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
if (SymReaper.
isLive(SR->getSymbol()))
AddToWorkList(SR, &C);
else
Postponed.push_back(SR);
return;
}
if (isa<NonStaticGlobalSpaceRegion>(baseR)) {
AddToWorkList(baseR, &C);
return;
}
if (const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
const auto *StackReg =
cast<StackArgumentsSpaceRegion>(TR->getSuperRegion());
const StackFrameContext *RegCtx = StackReg->getStackFrame();
if (CurrentLCtx &&
(RegCtx == CurrentLCtx || RegCtx->
isParentOf(CurrentLCtx)))
AddToWorkList(TR, &C);
}
}
void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
if (!C)
return;
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
for (const auto &[Key, Val] : *C) {
VisitBinding(Val);
}
}
void RemoveDeadBindingsWorker::VisitBinding(SVal
V) {
if (
auto LCS =
V.getAs<nonloc::LazyCompoundVal>()) {
for (SVal
V : RM.getInterestingValues(*LCS)) {
if (
auto DepLCS =
V.getAs<nonloc::LazyCompoundVal>())
else
}
return;
}
if (
const MemRegion *R =
V.getAsRegion()) {
AddToWorkList(R);
if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
for (auto Var : BR->referenced_vars())
AddToWorkList(Var.getCapturedRegion());
}
}
for (SymbolRef Sym :
V.symbols())
}
bool RemoveDeadBindingsWorker::UpdatePostponed() {
for (const SymbolicRegion *SR : Postponed) {
if (SymReaper.
isLive(SR->getSymbol())) {
SR = nullptr;
}
}
}
StoreRef RegionStoreManager::removeDeadBindings(Store store,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper) {
RegionBindingsRef B = getRegionBindings(store);
RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
W.GenerateClusters();
for (const MemRegion *Reg : SymReaper.regions()) {
W.AddToWorkList(Reg);
}
do W.RunWorkList(); while (W.UpdatePostponed());
for (const MemRegion *Base : llvm::make_first_range(B)) {
if (!W.isVisited(Base))
B = B.removeCluster(Base);
}
return StoreRef(B.asStore(), *this);
}
void RegionStoreManager::printJson(raw_ostream &Out, Store S, const char *NL,
unsigned int Space, bool IsDot) const {
RegionBindingsRef
Bindings = getRegionBindings(S);
Indent(Out, Space, IsDot) <<
"\"store\": ";
return;
}
Out <<
"{ \"pointer\": \"" <<
Bindings.asStore() <<
"\", \"items\": [" << NL;
Bindings.printJson(Out, NL, Space + 1, IsDot);
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)
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.
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.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
LimitedRegionBindingsRef removeCluster(const MemRegion *BaseRegion) const
LimitedRegionBindingsRef withValuesEscaped(SVal V) const
bool hasExhaustedBindingLimit() const
LimitedRegionBindingsRef addBinding(BindingKey K, SVal V) const
LimitedRegionBindingsRef addWithoutDecreasingLimit(const MemRegion *BaseRegion, data_type_ref BindingKeyAndValue) const
QualType getElementType() const
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.
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
bool isParentOf(const LocationContext *LC) const
const Decl * getDecl() const
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.
field_iterator field_begin() const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool isVoidPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isScalarType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
QualType getCanonicalTypeInternal() const
bool isStructureOrClassType() const
bool isVectorType() const
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
bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
void markElementIndicesLive(const MemRegion *region)
void markLazilyCopied(const MemRegion *region)
bool isLive(SymbolRef sym)
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
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
bool Init(InterpState &S, CodePtr OpPC)
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, LoanID ID)
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)
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...