Rework RegionStoreManager's implementation of InvalidateRegions() to

not build a subregion map and instead do a single scan of the store.
This is done by building "region clusters" that represent the
collection of regions that have the same base region.  Invalidating
any region in a cluster means that they all should get invalidated.

This change brought out a point that Zhongxing mentioned to me
offline: the flattened memory binding has issues distinguishing
between direct and default bindings.  For example, setting the default
value for an entire struct is the same as binding to the first
element.  To address this problem, I moved the binding "tag" (Direct
or Default) from BindingVal to BdingKey (and removed BindingVal
entirely).  This requires us to do double lookups in some cases; and
there is still much more cleanup that can be done.

This change produced a noticeable speedup when analyzing sqlite3 (a
reduction of 4% in running time).

llvm-svn: 95193
This commit is contained in:
Ted Kremenek 2010-02-03 03:06:46 +00:00
parent db56b919e5
commit 64efd0d213
1 changed files with 251 additions and 216 deletions

View File

@ -31,82 +31,56 @@ using namespace clang;
#define USE_EXPLICIT_COMPOUND 0 #define USE_EXPLICIT_COMPOUND 0
//===----------------------------------------------------------------------===//
// Representation of value bindings.
//===----------------------------------------------------------------------===//
namespace {
class BindingVal {
public:
enum BindingKind { Direct, Default };
private:
SVal Value;
BindingKind Kind;
public:
BindingVal(SVal V, BindingKind K) : Value(V), Kind(K) {}
bool isDefault() const { return Kind == Default; }
const SVal *getValue() const { return &Value; }
const SVal *getDirectValue() const { return isDefault() ? 0 : &Value; }
const SVal *getDefaultValue() const { return isDefault() ? &Value : 0; }
void Profile(llvm::FoldingSetNodeID& ID) const {
Value.Profile(ID);
ID.AddInteger(Kind);
}
inline bool operator==(const BindingVal& R) const {
return Value == R.Value && Kind == R.Kind;
}
inline bool operator!=(const BindingVal& R) const {
return !(*this == R);
}
};
}
namespace llvm {
static inline
llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingVal V) {
if (V.isDefault())
os << "(default) ";
else
os << "(direct) ";
os << *V.getValue();
return os;
}
} // end llvm namespace
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Representation of binding keys. // Representation of binding keys.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
namespace { namespace {
class BindingKey : public std::pair<const MemRegion*, uint64_t> { class BindingKey {
public: public:
explicit BindingKey(const MemRegion *r, uint64_t offset) enum Kind { Direct = 0x0, Default = 0x1 };
: std::pair<const MemRegion*,uint64_t>(r, offset) { assert(r); } private:
llvm ::PointerIntPair<const MemRegion*, 1> P;
uint64_t Offset;
const MemRegion *getRegion() const { return first; } explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
uint64_t getOffset() const { return second; } : P(r, (unsigned) k), Offset(offset) {}
public:
bool isDefault() const { return P.getInt() == Default; }
bool isDirect() const { return P.getInt() == Direct; }
const MemRegion *getRegion() const { return P.getPointer(); }
uint64_t getOffset() const { return Offset; }
void Profile(llvm::FoldingSetNodeID& ID) const { void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddPointer(getRegion()); ID.AddPointer(P.getOpaqueValue());
ID.AddInteger(getOffset()); ID.AddInteger(Offset);
} }
static BindingKey Make(const MemRegion *R); static BindingKey Make(const MemRegion *R, Kind k);
bool operator<(const BindingKey &X) const {
if (P.getOpaqueValue() < X.P.getOpaqueValue())
return true;
if (P.getOpaqueValue() > X.P.getOpaqueValue())
return false;
return Offset < X.Offset;
}
bool operator==(const BindingKey &X) const {
return P.getOpaqueValue() == X.P.getOpaqueValue() &&
Offset == X.Offset;
}
}; };
} // end anonymous namespace } // end anonymous namespace
namespace llvm { namespace llvm {
static inline static inline
llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) { llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) {
os << '(' << K.getRegion() << ',' << K.getOffset() << ')'; os << '(' << K.getRegion() << ',' << K.getOffset()
<< ',' << (K.isDirect() ? "direct" : "default")
<< ')';
return os; return os;
} }
} // end llvm namespace } // end llvm namespace
@ -115,7 +89,7 @@ namespace llvm {
// Actual Store type. // Actual Store type.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
typedef llvm::ImmutableMap<BindingKey, BindingVal> RegionBindings; typedef llvm::ImmutableMap<BindingKey, SVal> RegionBindings;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Fine-grained control of RegionStoreManager. // Fine-grained control of RegionStoreManager.
@ -222,6 +196,7 @@ public:
} }
}; };
class RegionStoreManager : public StoreManager { class RegionStoreManager : public StoreManager {
const RegionStoreFeatures Features; const RegionStoreFeatures Features;
RegionBindings::Factory RBFactory; RegionBindings::Factory RBFactory;
@ -314,21 +289,31 @@ public:
const Expr *E, unsigned Count, const Expr *E, unsigned Count,
InvalidatedSymbols *IS); InvalidatedSymbols *IS);
private: public: // Made public for helper classes.
void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R, void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R,
RegionStoreSubRegionMap &M); RegionStoreSubRegionMap &M);
RegionBindings Add(RegionBindings B, BindingKey K, BindingVal V); RegionBindings Add(RegionBindings B, BindingKey K, SVal V);
RegionBindings Add(RegionBindings B, const MemRegion *R, BindingVal V);
const BindingVal *Lookup(RegionBindings B, BindingKey K); RegionBindings Add(RegionBindings B, const MemRegion *R,
const BindingVal *Lookup(RegionBindings B, const MemRegion *R); BindingKey::Kind k, SVal V);
const SVal *Lookup(RegionBindings B, BindingKey K);
const SVal *Lookup(RegionBindings B, const MemRegion *R, BindingKey::Kind k);
RegionBindings Remove(RegionBindings B, BindingKey K); RegionBindings Remove(RegionBindings B, BindingKey K);
RegionBindings Remove(RegionBindings B, const MemRegion *R); RegionBindings Remove(RegionBindings B, const MemRegion *R,
BindingKey::Kind k);
RegionBindings Remove(RegionBindings B, const MemRegion *R) {
return Remove(Remove(B, R, BindingKey::Direct), R, BindingKey::Default);
}
Store Remove(Store store, BindingKey K); Store Remove(Store store, BindingKey K);
public: public: // Part of public interface to class.
const GRState *Bind(const GRState *state, Loc LV, SVal V); const GRState *Bind(const GRState *state, Loc LV, SVal V);
const GRState *BindCompoundLiteral(const GRState *state, const GRState *BindCompoundLiteral(const GRState *state,
@ -519,61 +504,104 @@ void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B,
B = Remove(B, R); B = Remove(B, R);
} }
const GRState *RegionStoreManager::InvalidateRegions(const GRState *state, namespace {
class InvalidateRegionsWorker {
typedef BumpVector<const MemRegion *> RegionCluster;
typedef llvm::DenseMap<const MemRegion *, RegionCluster *> ClusterMap;
typedef llvm::SmallVector<RegionCluster*, 10> WorkList;
BumpVectorContext BVC;
ClusterMap ClusterM;
WorkList WL;
public:
const GRState *InvalidateRegions(RegionStoreManager &RM,
const GRState *state,
const MemRegion * const *I, const MemRegion * const *I,
const MemRegion * const *E, const MemRegion * const *E,
const Expr *Ex, const Expr *Ex,
unsigned Count, unsigned Count,
InvalidatedSymbols *IS) { StoreManager::InvalidatedSymbols *IS);
ASTContext& Ctx = StateMgr.getContext();
// Get the mapping of regions -> subregions. private:
llvm::OwningPtr<RegionStoreSubRegionMap> void AddToWorkList(const MemRegion *R);
SubRegions(getRegionStoreSubRegionMap(state->getStore())); void AddToCluster(const MemRegion *R);
RegionCluster **getCluster(const MemRegion *R);
RegionBindings B = GetRegionBindings(state->getStore()); };
llvm::DenseMap<const MemRegion *, unsigned> Visited;
llvm::SmallVector<const MemRegion *, 10> WorkList;
for ( ; I != E; ++I) {
// Strip away casts.
WorkList.push_back((*I)->StripCasts());
} }
while (!WorkList.empty()) { void InvalidateRegionsWorker::AddToCluster(const MemRegion *R) {
const MemRegion *R = WorkList.back(); const MemRegion *baseR = R->getBaseRegion();
WorkList.pop_back(); RegionCluster **CPtr = getCluster(baseR);
if (R != baseR) {
assert(*CPtr);
(*CPtr)->push_back(R, BVC);
}
}
// Have we visited this region before? void InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
unsigned &visited = Visited[R]; RegionCluster **CPtr = getCluster( R->getBaseRegion());
if (visited) if (RegionCluster *C = *CPtr) {
continue; WL.push_back(C);
visited = 1; *CPtr = NULL;
}
}
// Add subregions to work list. InvalidateRegionsWorker::RegionCluster **
if (const RegionStoreSubRegionMap::Set *S = SubRegions->getSubRegions(R)) InvalidateRegionsWorker::getCluster(const MemRegion *R) {
for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end(); RegionCluster *&CRef = ClusterM[R];
I != E; ++I) if (!CRef) {
WorkList.push_back(*I); void *Mem = BVC.getAllocator().Allocate<RegionCluster>();
CRef = new (Mem) RegionCluster(BVC, 10);
CRef->push_back(R, BVC);
}
return &CRef;
}
const GRState *
InvalidateRegionsWorker::InvalidateRegions(RegionStoreManager &RM,
const GRState *state,
const MemRegion * const *I,
const MemRegion * const *E,
const Expr *Ex, unsigned Count,
StoreManager::InvalidatedSymbols *IS)
{
ASTContext &Ctx = state->getStateManager().getContext();
ValueManager &ValMgr = state->getStateManager().getValueManager();
RegionBindings B = RegionStoreManager::GetRegionBindings(state->getStore());
// Scan the entire store and make the region clusters.
for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
AddToCluster(RI.getKey().getRegion());
if (const MemRegion *R = RI.getData().getAsRegion())
AddToCluster(R);
}
// Add the cluster for I .. E to a worklist.
for ( ; I != E; ++I)
AddToWorkList(*I);
while (!WL.empty()) {
RegionCluster *C = WL.back();
WL.pop_back();
for (RegionCluster::iterator I = C->begin(), E = C->end(); I != E; ++I) {
const MemRegion *R = *I;
// Get the old binding. Is it a region? If so, add it to the worklist. // Get the old binding. Is it a region? If so, add it to the worklist.
if (Optional<SVal> V = getDirectBinding(B, R)) { if (Optional<SVal> V = RM.getDirectBinding(B, R)) {
if (const MemRegion *RV = V->getAsRegion()) if (const MemRegion *RV = V->getAsRegion())
WorkList.push_back(RV); AddToWorkList(RV);
// A symbol? Mark it touched by the invalidation. // A symbol? Mark it touched by the invalidation.
if (IS) { if (IS)
if (SymbolRef Sym = V->getAsSymbol()) if (SymbolRef Sym = V->getAsSymbol())
IS->insert(Sym); IS->insert(Sym);
} }
}
// Symbolic region? Mark that symbol touched by the invalidation. // Symbolic region? Mark that symbol touched by the invalidation.
if (IS) { if (IS)
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
IS->insert(SR->getSymbol()); IS->insert(SR->getSymbol());
}
// BlockDataRegion? If so, invalidate captured variables that are passed // BlockDataRegion? If so, invalidate captured variables that are passed
// by reference. // by reference.
@ -583,7 +611,7 @@ const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
I != E; ++I) { I != E; ++I) {
const VarRegion *VR = *I; const VarRegion *VR = *I;
if (VR->getDecl()->getAttr<BlocksAttr>()) if (VR->getDecl()->getAttr<BlocksAttr>())
WorkList.push_back(VR); AddToWorkList(VR);
} }
continue; continue;
} }
@ -594,7 +622,7 @@ const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
// conjured symbol. The type of the symbol is irrelavant. // conjured symbol. The type of the symbol is irrelavant.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy, DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy,
Count); Count);
B = Add(B, R, BindingVal(V, BindingVal::Default)); B = RM.Add(B, R, BindingKey::Default, V);
continue; continue;
} }
@ -604,48 +632,60 @@ const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
const TypedRegion *TR = cast<TypedRegion>(R); const TypedRegion *TR = cast<TypedRegion>(R);
QualType T = TR->getValueType(Ctx); QualType T = TR->getValueType(Ctx);
// Invalidate the binding.
if (const RecordType *RT = T->getAsStructureType()) { if (const RecordType *RT = T->getAsStructureType()) {
const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx); const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx);
// No record definition. There is nothing we can do. // No record definition. There is nothing we can do.
if (!RD) if (!RD) {
B = RM.Remove(B, R);
continue; continue;
}
// Invalidate the region by setting its default value to // Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelavant. // conjured symbol. The type of the symbol is irrelavant.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy, DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy,
Count); Count);
B = Add(B, R, BindingVal(V, BindingVal::Default)); B = RM.Add(B, R, BindingKey::Default, V);
continue; continue;
} }
if (const ArrayType *AT = Ctx.getAsArrayType(T)) { if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
// Set the default value of the array to conjured symbol. // Set the default value of the array to conjured symbol.
DefinedOrUnknownSVal V = DefinedOrUnknownSVal V =
ValMgr.getConjuredSymbolVal(R, Ex, AT->getElementType(), Count); ValMgr.getConjuredSymbolVal(R, Ex, AT->getElementType(), Count);
B = Add(B, R, BindingVal(V, BindingVal::Default)); B = RM.Add(B, R, BindingKey::Default, V);
continue; continue;
} }
if ((isa<FieldRegion>(R)||isa<ElementRegion>(R)||isa<ObjCIvarRegion>(R)) // For fields and elements that aren't themselves structs or arrays,
&& Visited[cast<SubRegion>(R)->getSuperRegion()]) { // just remove the binding. Base regions will get default values from
// For fields and elements whose super region has also been invalidated, // which the fields and elements will get lazily symbolicated.
// only remove the old binding. The super region will get set with a if (isa<FieldRegion>(R) || isa<ElementRegion>(R)) {
// default value from which we can lazily derive a new symbolic value. B = RM.Remove(B, R, BindingKey::Direct);
B = Remove(B, R);
continue; continue;
} }
// Invalidate the binding.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, T, Count); DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, T, Count);
assert(SymbolManager::canSymbolicate(T) || V.isUnknown()); assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
B = Add(B, R, BindingVal(V, BindingVal::Direct)); B = RM.Add(B, R, BindingKey::Direct, V);
}
} }
// Create a new state with the updated bindings. // Create a new state with the updated bindings.
return state->makeWithStore(B.getRoot()); return state->makeWithStore(B.getRoot());
} }
const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
const MemRegion * const *I,
const MemRegion * const *E,
const Expr *Ex,
unsigned Count,
InvalidatedSymbols *IS) {
InvalidateRegionsWorker W;
return W.InvalidateRegions(*this, state, I, E, Ex, Count, IS);
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// getLValueXXX methods. // getLValueXXX methods.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -991,32 +1031,32 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
Optional<SVal> RegionStoreManager::getDirectBinding(RegionBindings B, Optional<SVal> RegionStoreManager::getDirectBinding(RegionBindings B,
const MemRegion *R) { const MemRegion *R) {
if (const BindingVal *BV = Lookup(B, R)) if (const SVal *V = Lookup(B, R, BindingKey::Direct))
return Optional<SVal>::create(BV->getDirectValue()); return *V;
return Optional<SVal>(); return Optional<SVal>();
} }
Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B, Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
const MemRegion *R) { const MemRegion *R) {
if (R->isBoundable()) if (R->isBoundable())
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) if (const TypedRegion *TR = dyn_cast<TypedRegion>(R))
if (TR->getValueType(getContext())->isUnionType()) if (TR->getValueType(getContext())->isUnionType())
return UnknownVal(); return UnknownVal();
if (const BindingVal *V = Lookup(B, R)) if (const SVal *V = Lookup(B, R, BindingKey::Default))
return Optional<SVal>::create(V->getDefaultValue()); return *V;
return Optional<SVal>(); return Optional<SVal>();
} }
Optional<SVal> RegionStoreManager::getBinding(RegionBindings B, Optional<SVal> RegionStoreManager::getBinding(RegionBindings B,
const MemRegion *R) { const MemRegion *R) {
if (const BindingVal *BV = Lookup(B, R))
return Optional<SVal>::create(BV->getValue());
return Optional<SVal>(); if (Optional<SVal> V = getDirectBinding(B, R))
return V;
return getDefaultBinding(B, R);
} }
static bool IsReinterpreted(QualType RTy, QualType UsedTy, ASTContext &Ctx) { static bool IsReinterpreted(QualType RTy, QualType UsedTy, ASTContext &Ctx) {
@ -1160,12 +1200,11 @@ RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
} }
RegionBindings B = GetRegionBindings(state->getStore()); RegionBindings B = GetRegionBindings(state->getStore());
const BindingVal *V = Lookup(B, R); const SVal *V = Lookup(B, R, BindingKey::Direct);
// Check if the region has a binding. // Check if the region has a binding.
if (V) if (V)
if (SVal const *SV = V->getValue()) return SValuator::CastResult(state, *V);
return SValuator::CastResult(state, *SV);
// The location does not have a bound value. This means that it has // The location does not have a bound value. This means that it has
// the value it had upon its creation and/or entry to the analyzed // the value it had upon its creation and/or entry to the analyzed
@ -1459,7 +1498,7 @@ SVal RegionStoreManager::RetrieveArray(const GRState *state,
Store RegionStoreManager::Remove(Store store, Loc L) { Store RegionStoreManager::Remove(Store store, Loc L) {
if (isa<loc::MemRegionVal>(L)) if (isa<loc::MemRegionVal>(L))
if (const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion()) if (const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion())
return Remove(store, BindingKey::Make(R)); return Remove(GetRegionBindings(store), R).getRoot();
return store; return store;
} }
@ -1518,8 +1557,7 @@ const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
// Perform the binding. // Perform the binding.
RegionBindings B = GetRegionBindings(state->getStore()); RegionBindings B = GetRegionBindings(state->getStore());
return state->makeWithStore(Add(B, R, return state->makeWithStore(Add(B, R, BindingKey::Direct, V).getRoot());
BindingVal(V, BindingVal::Direct)).getRoot());
} }
const GRState *RegionStoreManager::BindDecl(const GRState *ST, const GRState *RegionStoreManager::BindDecl(const GRState *ST,
@ -1566,8 +1604,7 @@ const GRState *RegionStoreManager::setImplicitDefaultValue(const GRState *state,
return state; return state;
} }
return state->makeWithStore(Add(B, R, return state->makeWithStore(Add(B, R, BindingKey::Default, V).getRoot());
BindingVal(V, BindingVal::Default)).getRoot());
} }
const GRState *RegionStoreManager::BindArray(const GRState *state, const GRState *RegionStoreManager::BindArray(const GRState *state,
@ -1699,7 +1736,7 @@ RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R,
if (FI != FE) { if (FI != FE) {
Store store = state->getStore(); Store store = state->getStore();
RegionBindings B = GetRegionBindings(store); RegionBindings B = GetRegionBindings(store);
B = Add(B, R, BindingVal(ValMgr.makeIntVal(0, false), BindingVal::Default)); B = Add(B, R, BindingKey::Default, ValMgr.makeIntVal(0, false));
state = state->makeWithStore(B.getRoot()); state = state->makeWithStore(B.getRoot());
} }
@ -1713,9 +1750,7 @@ Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R) {
RemoveSubRegionBindings(B, R, *SubRegions); RemoveSubRegionBindings(B, R, *SubRegions);
// Set the default value of the struct region to "unknown". // Set the default value of the struct region to "unknown".
B = Add(B, R, BindingVal(UnknownVal(), BindingVal::Default)); return Add(B, R, BindingKey::Default, UnknownVal()).getRoot();
return B.getRoot();
} }
const GRState* const GRState*
@ -1734,53 +1769,53 @@ RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
// Now copy the bindings. This amounts to just binding 'V' to 'R'. This // Now copy the bindings. This amounts to just binding 'V' to 'R'. This
// results in a zero-copy algorithm. // results in a zero-copy algorithm.
return state->makeWithStore(Add(B, R, return state->makeWithStore(Add(B, R, BindingKey::Direct, V).getRoot());
BindingVal(V, BindingVal::Direct)).getRoot());
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// "Raw" retrievals and bindings. // "Raw" retrievals and bindings.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
BindingKey BindingKey::Make(const MemRegion *R) { BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
const RegionRawOffset &O = ER->getAsRawOffset(); const RegionRawOffset &O = ER->getAsRawOffset();
if (O.getRegion()) if (O.getRegion())
return BindingKey(O.getRegion(), O.getByteOffset()); return BindingKey(O.getRegion(), O.getByteOffset(), k);
// FIXME: There are some ElementRegions for which we cannot compute // FIXME: There are some ElementRegions for which we cannot compute
// raw offsets yet, including regions with symbolic offsets. // raw offsets yet, including regions with symbolic offsets.
} }
return BindingKey(R, 0); return BindingKey(R, 0, k);
} }
RegionBindings RegionStoreManager::Add(RegionBindings B, BindingKey K, RegionBindings RegionStoreManager::Add(RegionBindings B, BindingKey K, SVal V) {
BindingVal V) {
return RBFactory.Add(B, K, V); return RBFactory.Add(B, K, V);
} }
RegionBindings RegionStoreManager::Add(RegionBindings B, const MemRegion *R, RegionBindings RegionStoreManager::Add(RegionBindings B, const MemRegion *R,
BindingVal V) { BindingKey::Kind k, SVal V) {
return Add(B, BindingKey::Make(R), V); return Add(B, BindingKey::Make(R, k), V);
} }
const BindingVal *RegionStoreManager::Lookup(RegionBindings B, BindingKey K) { const SVal *RegionStoreManager::Lookup(RegionBindings B, BindingKey K) {
return B.lookup(K); return B.lookup(K);
} }
const BindingVal *RegionStoreManager::Lookup(RegionBindings B, const SVal *RegionStoreManager::Lookup(RegionBindings B,
const MemRegion *R) { const MemRegion *R,
return Lookup(B, BindingKey::Make(R)); BindingKey::Kind k) {
return Lookup(B, BindingKey::Make(R, k));
} }
RegionBindings RegionStoreManager::Remove(RegionBindings B, BindingKey K) { RegionBindings RegionStoreManager::Remove(RegionBindings B, BindingKey K) {
return RBFactory.Remove(B, K); return RBFactory.Remove(B, K);
} }
RegionBindings RegionStoreManager::Remove(RegionBindings B, const MemRegion *R){ RegionBindings RegionStoreManager::Remove(RegionBindings B, const MemRegion *R,
return Remove(B, BindingKey::Make(R)); BindingKey::Kind k){
return Remove(B, BindingKey::Make(R, k));
} }
Store RegionStoreManager::Remove(Store store, BindingKey K) { Store RegionStoreManager::Remove(Store store, BindingKey K) {
@ -1982,7 +2017,7 @@ tryAgain:
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
SymReaper.maybeDead(SymR->getSymbol()); SymReaper.maybeDead(SymR->getSymbol());
SVal X = *I.getData().getValue(); SVal X = I.getData();
SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
for (; SI != SE; ++SI) for (; SI != SE; ++SI)
SymReaper.maybeDead(*SI); SymReaper.maybeDead(*SI);