forked from OSchip/llvm-project
Lazy bingding for region-store manager.
* Now Bind() methods take and return GRState* because binding could also alter GDM. * No variables are initialized except those declared with initial values. * failed C test cases are due to bugs in RemoveDeadBindings(), which removes constraints that is still alive. This will be fixed in later patch. * default value of array and struct regions will be implemented in later patch. llvm-svn: 61274
This commit is contained in:
parent
ab66b87f7f
commit
af7415ffb1
|
@ -336,15 +336,24 @@ public:
|
|||
|
||||
typedef StoreManager::DeadSymbolsTy DeadSymbolsTy;
|
||||
|
||||
const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal* IVal,
|
||||
unsigned Count);
|
||||
const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal IVal) {
|
||||
// Store manager should return a persistent state.
|
||||
return StoreMgr->BindDecl(St, VD, IVal);
|
||||
}
|
||||
|
||||
const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
|
||||
// Store manager should return a persistent state.
|
||||
return StoreMgr->BindDeclWithNoInit(St, VD);
|
||||
}
|
||||
|
||||
/// BindCompoundLiteral - Return the state that has the bindings currently
|
||||
/// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region
|
||||
/// for the compound literal and 'BegInit' and 'EndInit' represent an
|
||||
/// array of initializer values.
|
||||
const GRState* BindCompoundLiteral(const GRState* state,
|
||||
const CompoundLiteralExpr* CL, SVal V);
|
||||
const GRState* BindCompoundLiteral(const GRState* St,
|
||||
const CompoundLiteralExpr* CL, SVal V) {
|
||||
return StoreMgr->BindCompoundLiteral(St, CL, V);
|
||||
}
|
||||
|
||||
const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc,
|
||||
const LiveVariables& Liveness,
|
||||
|
@ -468,11 +477,9 @@ public:
|
|||
return StoreMgr->GetRegionSVal(state, R);
|
||||
}
|
||||
|
||||
void BindLoc(GRState& St, Loc LV, SVal V) {
|
||||
St.St = StoreMgr->Bind(St.St, LV, V);
|
||||
const GRState* BindLoc(const GRState* St, Loc LV, SVal V) {
|
||||
return StoreMgr->Bind(St, LV, V);
|
||||
}
|
||||
|
||||
const GRState* BindLoc(const GRState* St, Loc LV, SVal V);
|
||||
|
||||
void Unbind(GRState& St, Loc LV) {
|
||||
St.St = StoreMgr->Remove(St.St, LV);
|
||||
|
@ -481,6 +488,9 @@ public:
|
|||
const GRState* Unbind(const GRState* St, Loc LV);
|
||||
|
||||
const GRState* getPersistentState(GRState& Impl);
|
||||
|
||||
// MakeStateWithStore - get a persistent state with the new store.
|
||||
const GRState* MakeStateWithStore(const GRState* St, Store store);
|
||||
|
||||
bool isEqual(const GRState* state, Expr* Ex, const llvm::APSInt& V);
|
||||
bool isEqual(const GRState* state, Expr* Ex, uint64_t);
|
||||
|
@ -501,7 +511,15 @@ public:
|
|||
return addGDM(st, GRStateTrait<T>::GDMIndex(),
|
||||
GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Set(st->get<T>(), K, V, C)));
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
const GRState* add(const GRState* st,
|
||||
typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::context_type C) {
|
||||
return addGDM(st, GRStateTrait<T>::GDMIndex(),
|
||||
GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Add(st->get<T>(), K, C)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const GRState* remove(const GRState* st,
|
||||
typename GRStateTrait<T>::key_type K,
|
||||
|
@ -587,14 +605,12 @@ public:
|
|||
return GRStateRef(Mgr->BindExpr(St, Ex, V, Invalidate), *Mgr);
|
||||
}
|
||||
|
||||
GRStateRef BindDecl(const VarDecl* VD, SVal* InitVal, unsigned Count) {
|
||||
return GRStateRef(Mgr->BindDecl(St, VD, InitVal, Count), *Mgr);
|
||||
GRStateRef BindDecl(const VarDecl* VD, SVal InitVal) {
|
||||
return GRStateRef(Mgr->BindDecl(St, VD, InitVal), *Mgr);
|
||||
}
|
||||
|
||||
GRStateRef BindLoc(Loc LV, SVal V) {
|
||||
GRState StImpl = *St;
|
||||
Mgr->BindLoc(StImpl, LV, V);
|
||||
return GRStateRef(Mgr->getPersistentState(StImpl), *Mgr);
|
||||
return GRStateRef(Mgr->BindLoc(St, LV, V), *Mgr);
|
||||
}
|
||||
|
||||
GRStateRef BindLoc(SVal LV, SVal V) {
|
||||
|
@ -644,7 +660,12 @@ public:
|
|||
typename GRStateTrait<T>::value_type E) {
|
||||
return GRStateRef(Mgr->set<T>(St, K, E, get_context<T>()), *Mgr);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
GRStateRef add(typename GRStateTrait<T>::key_type K) {
|
||||
return GRStateRef(Mgr->add<T>(St, K, get_context<T>()), *Mgr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
GRStateRef remove(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::context_type C) {
|
||||
|
@ -658,7 +679,7 @@ public:
|
|||
|
||||
template<typename T>
|
||||
bool contains(typename GRStateTrait<T>::key_type key) const {
|
||||
return St->contains(key);
|
||||
return St->contains<T>(key);
|
||||
}
|
||||
|
||||
// Lvalue methods.
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
const MemRegion* getSuperRegion() const {
|
||||
return superRegion;
|
||||
}
|
||||
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
return R->getKind() > SymbolicRegionKind;
|
||||
}
|
||||
|
@ -466,6 +466,12 @@ public:
|
|||
assert(R);
|
||||
return R == globals;
|
||||
}
|
||||
|
||||
/// onStack - check if the region is allocated on the stack.
|
||||
bool onStack(const MemRegion* R);
|
||||
|
||||
/// onHeap - check if the region is allocated on the heap, usually by malloc.
|
||||
bool onHeap(const MemRegion* R);
|
||||
|
||||
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
|
||||
AllocaRegion* getAllocaRegion(const Expr* Ex, unsigned Cnt);
|
||||
|
|
|
@ -71,7 +71,13 @@ public:
|
|||
inline bool operator!=(const SVal& R) const {
|
||||
return !(*this == R);
|
||||
}
|
||||
|
||||
|
||||
/// MakeSymbolValue - make a unique symbol value for the region R according to
|
||||
/// its kind. R should be a scalar region. The symbol value T has the same
|
||||
/// type as R's rvalue type.
|
||||
static SVal MakeSymbolValue(SymbolManager& SymMgr, const MemRegion* R,
|
||||
QualType T);
|
||||
|
||||
static SVal GetSymbolValue(SymbolManager& SymMgr, VarDecl *D);
|
||||
static SVal getSymbolValue(SymbolManager& SymMgr, const MemRegion* R,
|
||||
const llvm::APSInt* Idx, QualType T);
|
||||
|
@ -171,6 +177,8 @@ public:
|
|||
|
||||
// Utility methods to create NonLocs.
|
||||
|
||||
static NonLoc MakeVal(SymbolRef sym);
|
||||
|
||||
static NonLoc MakeVal(BasicValueFactory& BasicVals, unsigned X,
|
||||
bool isUnsigned);
|
||||
|
||||
|
@ -212,6 +220,8 @@ public:
|
|||
static Loc MakeVal(const MemRegion* R);
|
||||
|
||||
static Loc MakeVal(AddrLabelExpr* E);
|
||||
|
||||
static Loc MakeVal(SymbolRef sym);
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SVal* V) {
|
||||
|
|
|
@ -49,16 +49,19 @@ public:
|
|||
SVal GetRegionSVal(const GRState* state, const MemRegion* R) {
|
||||
return Retrieve(state, loc::MemRegionVal(R));
|
||||
}
|
||||
|
||||
virtual Store Bind(Store St, Loc LV, SVal V) = 0;
|
||||
virtual Store Remove(Store St, Loc LV) = 0;
|
||||
|
||||
/// Bind value V to location L.
|
||||
virtual const GRState* Bind(const GRState* St, Loc L, SVal V) = 0;
|
||||
|
||||
virtual Store Remove(Store St, Loc L) = 0;
|
||||
|
||||
/// BindCompoundLiteral - Return the store that has the bindings currently
|
||||
/// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region
|
||||
/// for the compound literal and 'BegInit' and 'EndInit' represent an
|
||||
/// array of initializer values.
|
||||
virtual Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL,
|
||||
SVal V) = 0;
|
||||
virtual const GRState* BindCompoundLiteral(const GRState* St,
|
||||
const CompoundLiteralExpr* CL,
|
||||
SVal V) = 0;
|
||||
|
||||
virtual Store getInitialStore() = 0;
|
||||
virtual MemRegionManager& getRegionManager() = 0;
|
||||
|
@ -112,8 +115,11 @@ public:
|
|||
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
|
||||
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) = 0;
|
||||
|
||||
virtual Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal,
|
||||
unsigned Count) = 0;
|
||||
virtual const GRState* BindDecl(const GRState* St, const VarDecl* VD,
|
||||
SVal InitVal) = 0;
|
||||
|
||||
virtual const GRState* BindDeclWithNoInit(const GRState* St,
|
||||
const VarDecl* VD) = 0;
|
||||
|
||||
virtual const GRState* setExtent(const GRState* St,
|
||||
const MemRegion* R, SVal Extent) {
|
||||
|
|
|
@ -104,15 +104,15 @@ public:
|
|||
};
|
||||
|
||||
class SymbolDataParmVar : public SymbolData {
|
||||
ParmVarDecl *VD;
|
||||
const ParmVarDecl *VD;
|
||||
|
||||
public:
|
||||
SymbolDataParmVar(SymbolRef MySym, ParmVarDecl* vd)
|
||||
SymbolDataParmVar(SymbolRef MySym, const ParmVarDecl* vd)
|
||||
: SymbolData(ParmKind, MySym), VD(vd) {}
|
||||
|
||||
ParmVarDecl* getDecl() const { return VD; }
|
||||
const ParmVarDecl* getDecl() const { return VD; }
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID& profile, ParmVarDecl* VD) {
|
||||
static void Profile(llvm::FoldingSetNodeID& profile, const ParmVarDecl* VD) {
|
||||
profile.AddInteger((unsigned) ParmKind);
|
||||
profile.AddPointer(VD);
|
||||
}
|
||||
|
@ -128,15 +128,15 @@ public:
|
|||
};
|
||||
|
||||
class SymbolDataGlobalVar : public SymbolData {
|
||||
VarDecl *VD;
|
||||
const VarDecl *VD;
|
||||
|
||||
public:
|
||||
SymbolDataGlobalVar(SymbolRef MySym, VarDecl* vd) :
|
||||
SymbolDataGlobalVar(SymbolRef MySym, const VarDecl* vd) :
|
||||
SymbolData(GlobalKind, MySym), VD(vd) {}
|
||||
|
||||
VarDecl* getDecl() const { return VD; }
|
||||
const VarDecl* getDecl() const { return VD; }
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID& profile, VarDecl* VD) {
|
||||
static void Profile(llvm::FoldingSetNodeID& profile, const VarDecl* VD) {
|
||||
profile.AddInteger((unsigned) GlobalKind);
|
||||
profile.AddPointer(VD);
|
||||
}
|
||||
|
@ -275,8 +275,10 @@ public:
|
|||
: SymbolCounter(0), BPAlloc(bpalloc) {}
|
||||
|
||||
~SymbolManager();
|
||||
|
||||
SymbolRef getSymbol(VarDecl* D);
|
||||
|
||||
/// Make a unique symbol for MemRegion R according to its kind.
|
||||
SymbolRef getSymbol(const MemRegion* R);
|
||||
SymbolRef getSymbol(const VarDecl* D);
|
||||
SymbolRef getElementSymbol(const MemRegion* R, const llvm::APSInt* Idx);
|
||||
SymbolRef getFieldSymbol(const MemRegion* R, const FieldDecl* D);
|
||||
SymbolRef getConjuredSymbol(Stmt* E, QualType T, unsigned VisitCount);
|
||||
|
|
|
@ -39,7 +39,14 @@ public:
|
|||
~BasicStoreManager() {}
|
||||
|
||||
SVal Retrieve(const GRState *state, Loc LV, QualType T);
|
||||
Store Bind(Store St, Loc LV, SVal V);
|
||||
|
||||
const GRState* Bind(const GRState* St, Loc L, SVal V) {
|
||||
Store store = St->getStore();
|
||||
store = BindInternal(store, L, V);
|
||||
return StateMgr.MakeStateWithStore(St, store);
|
||||
}
|
||||
|
||||
Store BindInternal(Store St, Loc LV, SVal V);
|
||||
Store Remove(Store St, Loc LV);
|
||||
Store getInitialStore();
|
||||
MemRegionManager& getRegionManager() { return MRMgr; }
|
||||
|
@ -49,9 +56,10 @@ public:
|
|||
return loc::MemRegionVal(MRMgr.getVarRegion(VD));
|
||||
}
|
||||
|
||||
Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL,
|
||||
SVal V) {
|
||||
return store;
|
||||
const GRState* BindCompoundLiteral(const GRState* St,
|
||||
const CompoundLiteralExpr* CL,
|
||||
SVal V) {
|
||||
return St;
|
||||
}
|
||||
|
||||
SVal getLValueVar(const GRState* St, const VarDecl* VD);
|
||||
|
@ -89,7 +97,25 @@ public:
|
|||
|
||||
void iterBindings(Store store, BindingsHandler& f);
|
||||
|
||||
Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count);
|
||||
const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal) {
|
||||
Store store = St->getStore();
|
||||
store = BindDeclInternal(store, VD, &InitVal);
|
||||
return StateMgr.MakeStateWithStore(St, store);
|
||||
}
|
||||
|
||||
const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
|
||||
Store store = St->getStore();
|
||||
store = BindDeclInternal(store, VD, 0);
|
||||
return StateMgr.MakeStateWithStore(St, store);
|
||||
}
|
||||
|
||||
const GRState* BindDecl(const GRState* St, const VarDecl* VD) {
|
||||
Store store = St->getStore();
|
||||
store = BindDeclInternal(store, VD, 0);
|
||||
return StateMgr.MakeStateWithStore(St, store);
|
||||
}
|
||||
|
||||
Store BindDeclInternal(Store store, const VarDecl* VD, SVal* InitVal);
|
||||
|
||||
static inline VarBindingsTy GetVarBindings(Store store) {
|
||||
return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store));
|
||||
|
@ -286,7 +312,7 @@ SVal BasicStoreManager::Retrieve(const GRState* state, Loc LV, QualType T) {
|
|||
return UnknownVal();
|
||||
}
|
||||
|
||||
Store BasicStoreManager::Bind(Store store, Loc LV, SVal V) {
|
||||
Store BasicStoreManager::BindInternal(Store store, Loc LV, SVal V) {
|
||||
switch (LV.getSubKind()) {
|
||||
case loc::MemRegionKind: {
|
||||
const VarRegion* R =
|
||||
|
@ -421,8 +447,8 @@ Store BasicStoreManager::getInitialStore() {
|
|||
SelfRegion = MRMgr.getObjCObjectRegion(MD->getClassInterface(),
|
||||
MRMgr.getHeapRegion());
|
||||
|
||||
St = Bind(St, loc::MemRegionVal(MRMgr.getVarRegion(PD)),
|
||||
loc::MemRegionVal(SelfRegion));
|
||||
St = BindInternal(St, loc::MemRegionVal(MRMgr.getVarRegion(PD)),
|
||||
loc::MemRegionVal(SelfRegion));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -441,15 +467,15 @@ Store BasicStoreManager::getInitialStore() {
|
|||
? SVal::GetSymbolValue(StateMgr.getSymbolManager(), VD)
|
||||
: UndefinedVal();
|
||||
|
||||
St = Bind(St, loc::MemRegionVal(MRMgr.getVarRegion(VD)), X);
|
||||
St = BindInternal(St, loc::MemRegionVal(MRMgr.getVarRegion(VD)), X);
|
||||
}
|
||||
}
|
||||
}
|
||||
return St;
|
||||
}
|
||||
|
||||
Store BasicStoreManager::BindDecl(Store store, const VarDecl* VD,
|
||||
SVal* InitVal, unsigned Count) {
|
||||
Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
|
||||
SVal* InitVal) {
|
||||
|
||||
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
|
||||
|
||||
|
@ -479,16 +505,16 @@ Store BasicStoreManager::BindDecl(Store store, const VarDecl* VD,
|
|||
if (!InitVal) {
|
||||
QualType T = VD->getType();
|
||||
if (Loc::IsLocType(T))
|
||||
store = Bind(store, getLoc(VD),
|
||||
store = BindInternal(store, getLoc(VD),
|
||||
loc::ConcreteInt(BasicVals.getValue(0, T)));
|
||||
else if (T->isIntegerType())
|
||||
store = Bind(store, getLoc(VD),
|
||||
store = BindInternal(store, getLoc(VD),
|
||||
nonloc::ConcreteInt(BasicVals.getValue(0, T)));
|
||||
else {
|
||||
// assert(0 && "ignore other types of variables");
|
||||
}
|
||||
} else {
|
||||
store = Bind(store, getLoc(VD), *InitVal);
|
||||
store = BindInternal(store, getLoc(VD), *InitVal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -496,7 +522,7 @@ Store BasicStoreManager::BindDecl(Store store, const VarDecl* VD,
|
|||
QualType T = VD->getType();
|
||||
if (Loc::IsLocType(T) || T->isIntegerType()) {
|
||||
SVal V = InitVal ? *InitVal : UndefinedVal();
|
||||
store = Bind(store, getLoc(VD), V);
|
||||
store = BindInternal(store, getLoc(VD), V);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1811,7 +1811,8 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) {
|
|||
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
|
||||
const GRState* St = GetState(*I);
|
||||
unsigned Count = Builder->getCurrentBlockCount();
|
||||
|
||||
|
||||
// Decls without InitExpr are not initialized explicitly.
|
||||
if (InitEx) {
|
||||
SVal InitVal = GetSVal(St, InitEx);
|
||||
QualType T = VD->getType();
|
||||
|
@ -1829,11 +1830,9 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) {
|
|||
}
|
||||
}
|
||||
|
||||
St = StateMgr.BindDecl(St, VD, &InitVal, Count);
|
||||
}
|
||||
else
|
||||
St = StateMgr.BindDecl(St, VD, 0, Count);
|
||||
|
||||
St = StateMgr.BindDecl(St, VD, InitVal);
|
||||
} else
|
||||
St = StateMgr.BindDeclWithNoInit(St, VD);
|
||||
|
||||
// Check if 'VD' is a VLA and if so check if has a non-zero size.
|
||||
QualType T = getContext().getCanonicalType(VD->getType());
|
||||
|
|
|
@ -59,51 +59,6 @@ GRStateManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
|
|||
LSymbols, DSymbols);
|
||||
}
|
||||
|
||||
const GRState* GRStateManager::BindLoc(const GRState* St, Loc LV, SVal V) {
|
||||
|
||||
Store OldStore = St->getStore();
|
||||
Store NewStore = StoreMgr->Bind(OldStore, LV, V);
|
||||
|
||||
if (NewStore == OldStore)
|
||||
return St;
|
||||
|
||||
GRState NewSt = *St;
|
||||
NewSt.St = NewStore;
|
||||
return getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
const GRState* GRStateManager::BindDecl(const GRState* St, const VarDecl* VD,
|
||||
SVal* InitVal, unsigned Count) {
|
||||
Store OldStore = St->getStore();
|
||||
Store NewStore = StoreMgr->BindDecl(OldStore, VD, InitVal, Count);
|
||||
|
||||
if (NewStore == OldStore)
|
||||
return St;
|
||||
|
||||
GRState NewSt = *St;
|
||||
NewSt.St = NewStore;
|
||||
return getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
/// BindCompoundLiteral - Return the store that has the bindings currently
|
||||
/// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region
|
||||
/// for the compound literal and 'BegInit' and 'EndInit' represent an
|
||||
/// array of initializer values.
|
||||
const GRState*
|
||||
GRStateManager::BindCompoundLiteral(const GRState* state,
|
||||
const CompoundLiteralExpr* CL, SVal ILV) {
|
||||
|
||||
Store oldStore = state->getStore();
|
||||
Store newStore = StoreMgr->BindCompoundLiteral(oldStore, CL, ILV);
|
||||
|
||||
if (newStore == oldStore)
|
||||
return state;
|
||||
|
||||
GRState newState = *state;
|
||||
newState.St = newStore;
|
||||
return getPersistentState(newState);
|
||||
}
|
||||
|
||||
const GRState* GRStateManager::Unbind(const GRState* St, Loc LV) {
|
||||
Store OldStore = St->getStore();
|
||||
Store NewStore = StoreMgr->Remove(OldStore, LV);
|
||||
|
@ -140,6 +95,13 @@ const GRState* GRStateManager::getPersistentState(GRState& State) {
|
|||
return I;
|
||||
}
|
||||
|
||||
const GRState* GRStateManager::MakeStateWithStore(const GRState* St,
|
||||
Store store) {
|
||||
GRState NewSt = *St;
|
||||
NewSt.St = store;
|
||||
return getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// State pretty-printing.
|
||||
|
|
|
@ -215,6 +215,20 @@ MemSpaceRegion* MemRegionManager::getUnknownRegion() {
|
|||
return LazyAllocate(unknown);
|
||||
}
|
||||
|
||||
bool MemRegionManager::onStack(const MemRegion* R) {
|
||||
while (const SubRegion* SR = dyn_cast<SubRegion>(R))
|
||||
R = SR->getSuperRegion();
|
||||
|
||||
return (R != 0) && (R == stack);
|
||||
}
|
||||
|
||||
bool MemRegionManager::onHeap(const MemRegion* R) {
|
||||
while (const SubRegion* SR = dyn_cast<SubRegion>(R))
|
||||
R = SR->getSuperRegion();
|
||||
|
||||
return (R != 0) && (R == heap);
|
||||
}
|
||||
|
||||
StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
MemSpaceRegion* GlobalsR = getGlobalsRegion();
|
||||
|
|
|
@ -62,6 +62,16 @@ namespace clang {
|
|||
};
|
||||
}
|
||||
|
||||
// Regions that have default value zero.
|
||||
// FIXME: redefinition!
|
||||
// typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionDefaultValue;
|
||||
// static int RegionDefaultValueIndex = 0;
|
||||
// namespace clang {
|
||||
// template<> struct GRStateTrait<RegionDefaultValue>
|
||||
// : public GRStatePartialTrait<RegionDefaultValue> {
|
||||
// static void* GDMIndex() { return &RegionDefaultValueIndex; }
|
||||
// };
|
||||
// }
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -83,7 +93,8 @@ public:
|
|||
|
||||
MemRegionManager& getRegionManager() { return MRMgr; }
|
||||
|
||||
Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL, SVal V);
|
||||
const GRState* BindCompoundLiteral(const GRState* St,
|
||||
const CompoundLiteralExpr* CL, SVal V);
|
||||
|
||||
SVal getLValueString(const GRState* St, const StringLiteral* S);
|
||||
|
||||
|
@ -107,13 +118,24 @@ public:
|
|||
CastResult CastRegion(const GRState* state, const MemRegion* R,
|
||||
QualType CastToTy);
|
||||
|
||||
/// The high level logic for this method is this:
|
||||
/// Retrieve (L)
|
||||
/// if L has binding
|
||||
/// return L's binding
|
||||
/// else if L is in killset
|
||||
/// return unknown
|
||||
/// else
|
||||
/// if L is on stack or heap
|
||||
/// return undefined
|
||||
/// else
|
||||
/// return symbolic
|
||||
SVal Retrieve(const GRState* state, Loc L, QualType T = QualType());
|
||||
|
||||
Store Bind(Store St, Loc LV, SVal V);
|
||||
const GRState* Bind(const GRState* St, Loc LV, SVal V);
|
||||
|
||||
Store Remove(Store store, Loc LV);
|
||||
|
||||
Store getInitialStore();
|
||||
Store getInitialStore() { return RBFactory.GetEmptyMap().getRoot(); }
|
||||
|
||||
/// getSelfRegion - Returns the region for the 'self' (Objective-C) or
|
||||
/// 'this' object (C++). When used when analyzing a normal function this
|
||||
|
@ -133,7 +155,11 @@ public:
|
|||
|
||||
void UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols);
|
||||
|
||||
Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count);
|
||||
const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal);
|
||||
|
||||
const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
|
||||
return St;
|
||||
}
|
||||
|
||||
const GRState* setExtent(const GRState* St, const MemRegion* R, SVal Extent);
|
||||
|
||||
|
@ -152,22 +178,16 @@ private:
|
|||
return loc::MemRegionVal(MRMgr.getVarRegion(VD));
|
||||
}
|
||||
|
||||
Store InitializeArray(Store store, const TypedRegion* R, SVal Init);
|
||||
Store BindArrayToVal(Store store, const TypedRegion* BaseR, SVal V);
|
||||
Store BindArrayToSymVal(Store store, const TypedRegion* BaseR);
|
||||
|
||||
Store InitializeStruct(Store store, const TypedRegion* R, SVal Init);
|
||||
Store BindStructToVal(Store store, const TypedRegion* BaseR, SVal V);
|
||||
Store BindStructToSymVal(Store store, const TypedRegion* BaseR);
|
||||
const GRState* BindArray(const GRState* St, const TypedRegion* R, SVal V);
|
||||
|
||||
/// Retrieve the values in a struct and return a CompoundVal, used when doing
|
||||
/// struct copy:
|
||||
/// struct s x, y;
|
||||
/// x = y;
|
||||
/// y's value is retrieved by this method.
|
||||
SVal RetrieveStruct(Store store, const TypedRegion* R);
|
||||
SVal RetrieveStruct(const GRState* St, const TypedRegion* R);
|
||||
|
||||
Store BindStruct(Store store, const TypedRegion* R, SVal V);
|
||||
const GRState* BindStruct(const GRState* St, const TypedRegion* R, SVal V);
|
||||
|
||||
// Utility methods.
|
||||
BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
|
||||
|
@ -396,41 +416,60 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
|
|||
return CastResult(AddRegionView(state, ViewR, R), ViewR);
|
||||
}
|
||||
|
||||
SVal RegionStoreManager::Retrieve(const GRState* state, Loc L, QualType T) {
|
||||
SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
|
||||
assert(!isa<UnknownVal>(L) && "location unknown");
|
||||
assert(!isa<UndefinedVal>(L) && "location undefined");
|
||||
Store S = state->getStore();
|
||||
|
||||
switch (L.getSubKind()) {
|
||||
case loc::MemRegionKind: {
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
|
||||
assert(R && "bad region");
|
||||
|
||||
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
|
||||
if (TR->getRValueType(getContext())->isStructureType())
|
||||
return RetrieveStruct(S, TR);
|
||||
|
||||
RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(S));
|
||||
RegionBindingsTy::data_type* V = B.lookup(R);
|
||||
return V ? *V : UnknownVal();
|
||||
}
|
||||
|
||||
case loc::SymbolValKind:
|
||||
if (isa<loc::SymbolVal>(L))
|
||||
return UnknownVal();
|
||||
|
||||
case loc::ConcreteIntKind:
|
||||
return UndefinedVal(); // As in BasicStoreManager.
|
||||
if (isa<loc::ConcreteInt>(L))
|
||||
return UndefinedVal();
|
||||
|
||||
case loc::FuncValKind:
|
||||
if (isa<loc::FuncVal>(L))
|
||||
return L;
|
||||
|
||||
default:
|
||||
assert(false && "Invalid Location");
|
||||
return L;
|
||||
}
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
|
||||
assert(R && "bad region");
|
||||
|
||||
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
|
||||
if (TR->getRValueType(getContext())->isStructureType())
|
||||
return RetrieveStruct(St, TR);
|
||||
|
||||
RegionBindingsTy B = GetRegionBindings(St->getStore());
|
||||
RegionBindingsTy::data_type* V = B.lookup(R);
|
||||
|
||||
// Check if the region has a binding.
|
||||
if (V)
|
||||
return *V;
|
||||
|
||||
// Check if the region is in killset.
|
||||
GRStateRef state(St, StateMgr);
|
||||
if (state.contains<RegionKills>(R))
|
||||
return UnknownVal();
|
||||
|
||||
// The location is not initialized.
|
||||
|
||||
// We treat parameters as symbolic values.
|
||||
if (const VarRegion* VR = dyn_cast<VarRegion>(R))
|
||||
if (isa<ParmVarDecl>(VR->getDecl()))
|
||||
return SVal::MakeSymbolValue(getSymbolManager(), VR,
|
||||
VR->getRValueType(getContext()));
|
||||
|
||||
if (MRMgr.onStack(R) || MRMgr.onHeap(R))
|
||||
return UndefinedVal();
|
||||
else
|
||||
return SVal::MakeSymbolValue(getSymbolManager(), R,
|
||||
cast<TypedRegion>(R)->getRValueType(getContext()));
|
||||
|
||||
// FIXME: consider default values for elements and fields.
|
||||
}
|
||||
|
||||
SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
|
||||
SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){
|
||||
|
||||
Store store = St->getStore();
|
||||
GRStateRef state(St, StateMgr);
|
||||
|
||||
// FIXME: Verify we want getRValueType instead of getLValueType.
|
||||
QualType T = R->getRValueType(getContext());
|
||||
assert(T->isStructureType());
|
||||
|
@ -447,10 +486,21 @@ SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
|
|||
FieldEnd = Fields.rend();
|
||||
Field != FieldEnd; ++Field) {
|
||||
FieldRegion* FR = MRMgr.getFieldRegion(*Field, R);
|
||||
RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(store));
|
||||
RegionBindingsTy B = GetRegionBindings(store);
|
||||
RegionBindingsTy::data_type* data = B.lookup(FR);
|
||||
|
||||
SVal FieldValue = data ? *data : UnknownVal();
|
||||
SVal FieldValue;
|
||||
if (data)
|
||||
FieldValue = *data;
|
||||
else if (state.contains<RegionKills>(FR))
|
||||
FieldValue = UnknownVal();
|
||||
else {
|
||||
if (MRMgr.onStack(FR) || MRMgr.onHeap(FR))
|
||||
FieldValue = UndefinedVal();
|
||||
else
|
||||
FieldValue = SVal::MakeSymbolValue(getSymbolManager(), FR,
|
||||
FR->getRValueType(getContext()));
|
||||
}
|
||||
|
||||
StructVal = getBasicVals().consVals(FieldValue, StructVal);
|
||||
}
|
||||
|
@ -458,25 +508,37 @@ SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
|
|||
return NonLoc::MakeCompoundVal(T, StructVal, getBasicVals());
|
||||
}
|
||||
|
||||
Store RegionStoreManager::Bind(Store store, Loc LV, SVal V) {
|
||||
if (LV.getSubKind() == loc::SymbolValKind)
|
||||
return store;
|
||||
const GRState* RegionStoreManager::Bind(const GRState* St, Loc L, SVal V) {
|
||||
// Currently we don't bind value to symbolic location. But if the logic is
|
||||
// made clear, we might change this decision.
|
||||
if (isa<loc::SymbolVal>(L))
|
||||
return St;
|
||||
|
||||
assert(LV.getSubKind() == loc::MemRegionKind);
|
||||
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion();
|
||||
|
||||
// If we get here, the location should be a region.
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
|
||||
assert(R);
|
||||
|
||||
// Check if the region is a struct region.
|
||||
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
|
||||
// FIXME: Verify we want getRValueType().
|
||||
if (TR->getRValueType(getContext())->isStructureType())
|
||||
return BindStruct(store, TR, V);
|
||||
return BindStruct(St, TR, V);
|
||||
|
||||
Store store = St->getStore();
|
||||
RegionBindingsTy B = GetRegionBindings(store);
|
||||
return V.isUnknown()
|
||||
? RBFactory.Remove(B, R).getRoot()
|
||||
: RBFactory.Add(B, R, V).getRoot();
|
||||
|
||||
if (V.isUnknown()) {
|
||||
// Remove the binding.
|
||||
store = RBFactory.Remove(B, R).getRoot();
|
||||
|
||||
// Add the region to the killset.
|
||||
GRStateRef state(St, StateMgr);
|
||||
St = state.add<RegionKills>(R);
|
||||
}
|
||||
else
|
||||
store = RBFactory.Add(B, R, V).getRoot();
|
||||
|
||||
return StateMgr.MakeStateWithStore(St, store);
|
||||
}
|
||||
|
||||
Store RegionStoreManager::Remove(Store store, Loc L) {
|
||||
|
@ -488,150 +550,37 @@ Store RegionStoreManager::Remove(Store store, Loc L) {
|
|||
return RBFactory.Remove(B, R).getRoot();
|
||||
}
|
||||
|
||||
Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R, SVal V){
|
||||
// Verify we want getRValueType.
|
||||
QualType T = R->getRValueType(getContext());
|
||||
assert(T->isStructureType());
|
||||
const GRState* RegionStoreManager::BindDecl(const GRState* St,
|
||||
const VarDecl* VD, SVal InitVal) {
|
||||
// All static variables are treated as symbolic values.
|
||||
if (VD->hasGlobalStorage())
|
||||
return St;
|
||||
|
||||
const RecordType* RT = cast<RecordType>(T.getTypePtr());
|
||||
RecordDecl* RD = RT->getDecl();
|
||||
// Process local variables.
|
||||
|
||||
if (!RD->isDefinition()) {
|
||||
// This can only occur when a pointer of incomplete struct type is used as a
|
||||
// function argument.
|
||||
assert(V.isUnknown());
|
||||
return store;
|
||||
}
|
||||
QualType T = VD->getType();
|
||||
|
||||
VarRegion* VR = MRMgr.getVarRegion(VD);
|
||||
|
||||
if (Loc::IsLocType(T) || T->isIntegerType())
|
||||
return Bind(St, Loc::MakeVal(VR), InitVal);
|
||||
|
||||
RegionBindingsTy B = GetRegionBindings(store);
|
||||
else if (T->isArrayType())
|
||||
return BindArray(St, VR, InitVal);
|
||||
|
||||
if (isa<UnknownVal>(V))
|
||||
return BindStructToVal(store, R, UnknownVal());
|
||||
else if (T->isStructureType())
|
||||
return BindStruct(St, VR, InitVal);
|
||||
|
||||
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
|
||||
|
||||
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
||||
RecordDecl::field_iterator FI = RD->field_begin(), FE = RD->field_end();
|
||||
|
||||
for (; FI != FE; ++FI, ++VI) {
|
||||
assert(VI != VE);
|
||||
|
||||
FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
|
||||
|
||||
B = RBFactory.Add(B, FR, *VI);
|
||||
}
|
||||
|
||||
return B.getRoot();
|
||||
}
|
||||
|
||||
Store RegionStoreManager::getInitialStore() {
|
||||
typedef LiveVariables::AnalysisDataTy LVDataTy;
|
||||
LVDataTy& D = StateMgr.getLiveVariables().getAnalysisData();
|
||||
|
||||
Store St = RBFactory.GetEmptyMap().getRoot();
|
||||
|
||||
for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
|
||||
NamedDecl* ND = const_cast<NamedDecl*>(I->first);
|
||||
|
||||
if (VarDecl* VD = dyn_cast<VarDecl>(ND)) {
|
||||
// Punt on static variables for now.
|
||||
if (VD->getStorageClass() == VarDecl::Static)
|
||||
continue;
|
||||
|
||||
VarRegion* VR = MRMgr.getVarRegion(VD);
|
||||
|
||||
QualType T = VD->getType();
|
||||
// Only handle pointers and integers for now.
|
||||
if (Loc::IsLocType(T) || T->isIntegerType()) {
|
||||
// Initialize globals and parameters to symbolic values.
|
||||
// Initialize local variables to undefined.
|
||||
SVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
|
||||
isa<ImplicitParamDecl>(VD))
|
||||
? SVal::GetSymbolValue(getSymbolManager(), VD)
|
||||
: UndefinedVal();
|
||||
|
||||
St = Bind(St, getVarLoc(VD), X);
|
||||
}
|
||||
else if (T->isArrayType()) {
|
||||
if (VD->hasGlobalStorage()) // Params cannot have array type.
|
||||
St = BindArrayToSymVal(St, VR);
|
||||
else
|
||||
St = BindArrayToVal(St, VR, UndefinedVal());
|
||||
}
|
||||
else if (T->isStructureType()) {
|
||||
if (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
|
||||
isa<ImplicitParamDecl>(VD))
|
||||
St = BindStructToSymVal(St, VR);
|
||||
else
|
||||
St = BindStructToVal(St, VR, UndefinedVal());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Other types of variable are not supported yet.
|
||||
return St;
|
||||
}
|
||||
|
||||
Store RegionStoreManager::BindDecl(Store store, const VarDecl* VD,
|
||||
SVal* InitVal, unsigned Count) {
|
||||
|
||||
if (VD->hasGlobalStorage()) {
|
||||
// Static global variables should not be visited here.
|
||||
assert(!(VD->getStorageClass() == VarDecl::Static &&
|
||||
VD->isFileVarDecl()));
|
||||
// Process static variables.
|
||||
if (VD->getStorageClass() == VarDecl::Static) {
|
||||
if (!InitVal) {
|
||||
// Only handle pointer and integer static variables.
|
||||
|
||||
QualType T = VD->getType();
|
||||
|
||||
if (Loc::IsLocType(T))
|
||||
store = Bind(store, getVarLoc(VD),
|
||||
loc::ConcreteInt(getBasicVals().getValue(0, T)));
|
||||
|
||||
else if (T->isIntegerType())
|
||||
store = Bind(store, getVarLoc(VD),
|
||||
loc::ConcreteInt(getBasicVals().getValue(0, T)));
|
||||
|
||||
// Other types of static local variables are not handled yet.
|
||||
} else {
|
||||
store = Bind(store, getVarLoc(VD), *InitVal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Process local variables.
|
||||
|
||||
QualType T = VD->getType();
|
||||
|
||||
VarRegion* VR = MRMgr.getVarRegion(VD);
|
||||
|
||||
if (Loc::IsLocType(T) || T->isIntegerType()) {
|
||||
SVal V = InitVal ? *InitVal : UndefinedVal();
|
||||
store = Bind(store, loc::MemRegionVal(VR), V);
|
||||
}
|
||||
else if (T->isArrayType()) {
|
||||
if (!InitVal)
|
||||
store = BindArrayToVal(store, VR, UndefinedVal());
|
||||
else
|
||||
store = InitializeArray(store, VR, *InitVal);
|
||||
}
|
||||
else if (T->isStructureType()) {
|
||||
if (!InitVal)
|
||||
store = BindStructToVal(store, VR, UndefinedVal());
|
||||
else
|
||||
store = InitializeStruct(store, VR, *InitVal);
|
||||
}
|
||||
|
||||
// Other types of local variables are not handled yet.
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
||||
Store RegionStoreManager::BindCompoundLiteral(Store store,
|
||||
const CompoundLiteralExpr* CL,
|
||||
SVal V) {
|
||||
// FIXME: this method should be merged into Bind().
|
||||
const GRState*
|
||||
RegionStoreManager::BindCompoundLiteral(const GRState* St,
|
||||
const CompoundLiteralExpr* CL, SVal V) {
|
||||
CompoundLiteralRegion* R = MRMgr.getCompoundLiteralRegion(CL);
|
||||
store = Bind(store, loc::MemRegionVal(R), V);
|
||||
return store;
|
||||
return Bind(St, loc::MemRegionVal(R), V);
|
||||
}
|
||||
|
||||
const GRState* RegionStoreManager::setExtent(const GRState* St,
|
||||
|
@ -781,19 +730,24 @@ void RegionStoreManager::print(Store store, std::ostream& Out,
|
|||
}
|
||||
}
|
||||
|
||||
Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R,
|
||||
SVal Init) {
|
||||
const GRState* RegionStoreManager::BindArray(const GRState* St,
|
||||
const TypedRegion* R, SVal Init) {
|
||||
|
||||
// FIXME: Verify we should use getLValueType or getRValueType.
|
||||
QualType T = R->getRValueType(getContext());
|
||||
assert(T->isArrayType());
|
||||
|
||||
// When we are binding the whole array, it always has default value 0.
|
||||
GRStateRef state(St, StateMgr);
|
||||
// St = state.set<RegionDefaultValue>(R, NonLoc::MakeVal(getBasicVals(), 0,
|
||||
// false));
|
||||
|
||||
Store store = St->getStore();
|
||||
|
||||
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
|
||||
|
||||
llvm::APSInt Size(CAT->getSize(), false);
|
||||
|
||||
llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(),
|
||||
Size.isUnsigned());
|
||||
llvm::APSInt i = getBasicVals().getZeroWithPtrWidth(false);
|
||||
|
||||
// Check if the init expr is a StringLiteral.
|
||||
if (isa<loc::MemRegionVal>(Init)) {
|
||||
|
@ -803,21 +757,21 @@ Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R,
|
|||
unsigned len = S->getByteLength();
|
||||
unsigned j = 0;
|
||||
|
||||
// Copy bytes from the string literal into the target array. Trailing bytes
|
||||
// in the array that are not covered by the string literal are initialized
|
||||
// to zero.
|
||||
for (; i < Size; ++i, ++j) {
|
||||
if (j >= len)
|
||||
break;
|
||||
|
||||
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
|
||||
ElementRegion* ER = MRMgr.getElementRegion(Idx, R);
|
||||
|
||||
// Copy bytes from the string literal into the target array. Trailing
|
||||
// bytes in the array that are not covered by the string literal are
|
||||
// initialized to zero.
|
||||
SVal V = (j < len)
|
||||
? NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true)
|
||||
: NonLoc::MakeVal(getBasicVals(), 0, sizeof(char)*8, true);
|
||||
|
||||
store = Bind(store, loc::MemRegionVal(ER), V);
|
||||
SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true);
|
||||
St = Bind(St, loc::MemRegionVal(ER), V);
|
||||
}
|
||||
|
||||
return store;
|
||||
return StateMgr.MakeStateWithStore(St, store);
|
||||
}
|
||||
|
||||
|
||||
|
@ -825,79 +779,25 @@ Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R,
|
|||
|
||||
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
||||
|
||||
for (; i < Size; ++i) {
|
||||
for (; i < Size; ++i, ++VI) {
|
||||
// The init list might be shorter than the array decl.
|
||||
if (VI == VE)
|
||||
break;
|
||||
|
||||
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
|
||||
ElementRegion* ER = MRMgr.getElementRegion(Idx, R);
|
||||
|
||||
store = Bind(store, loc::MemRegionVal(ER), (VI!=VE) ? *VI : UndefinedVal());
|
||||
// The init list might be shorter than the array decl.
|
||||
if (VI != VE) ++VI;
|
||||
|
||||
if (CAT->getElementType()->isStructureType())
|
||||
St = BindStruct(St, ER, *VI);
|
||||
else
|
||||
St = Bind(St, Loc::MakeVal(ER), *VI);
|
||||
}
|
||||
|
||||
return store;
|
||||
return StateMgr.MakeStateWithStore(St, store);
|
||||
}
|
||||
|
||||
// Bind all elements of the array to some value.
|
||||
Store RegionStoreManager::BindArrayToVal(Store store, const TypedRegion* BaseR,
|
||||
SVal V){
|
||||
|
||||
// FIXME: Verify we want getRValueType.
|
||||
QualType T = BaseR->getRValueType(getContext());
|
||||
assert(T->isArrayType());
|
||||
|
||||
// Only handle constant size array for now.
|
||||
if (ConstantArrayType* CAT=dyn_cast<ConstantArrayType>(T.getTypePtr())) {
|
||||
|
||||
llvm::APInt Size = CAT->getSize();
|
||||
llvm::APInt i = llvm::APInt::getNullValue(Size.getBitWidth());
|
||||
|
||||
for (; i != Size; ++i) {
|
||||
nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i, false)));
|
||||
|
||||
ElementRegion* ER = MRMgr.getElementRegion(Idx, BaseR);
|
||||
|
||||
if (CAT->getElementType()->isStructureType())
|
||||
store = BindStructToVal(store, ER, V);
|
||||
else
|
||||
store = Bind(store, loc::MemRegionVal(ER), V);
|
||||
}
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
Store RegionStoreManager::BindArrayToSymVal(Store store,
|
||||
const TypedRegion* BaseR) {
|
||||
|
||||
// FIXME: Verify we want getRValueType.
|
||||
QualType T = BaseR->getRValueType(getContext());
|
||||
assert(T->isArrayType());
|
||||
|
||||
if (ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(T.getTypePtr())) {
|
||||
llvm::APInt Size = CAT->getSize();
|
||||
llvm::APInt i = llvm::APInt::getNullValue(Size.getBitWidth());
|
||||
for (; i != Size; ++i) {
|
||||
nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i, false)));
|
||||
|
||||
ElementRegion* ER = MRMgr.getElementRegion(Idx, BaseR);
|
||||
|
||||
if (CAT->getElementType()->isStructureType()) {
|
||||
store = BindStructToSymVal(store, ER);
|
||||
}
|
||||
else {
|
||||
SVal V = SVal::getSymbolValue(getSymbolManager(), BaseR,
|
||||
&Idx.getValue(), CAT->getElementType());
|
||||
store = Bind(store, loc::MemRegionVal(ER), V);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R,
|
||||
SVal Init) {
|
||||
|
||||
const GRState*
|
||||
RegionStoreManager::BindStruct(const GRState* St, const TypedRegion* R, SVal V){
|
||||
// FIXME: Verify that we should use getRValueType or getLValueType.
|
||||
QualType T = R->getRValueType(getContext());
|
||||
assert(T->isStructureType());
|
||||
|
@ -906,102 +806,35 @@ Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R,
|
|||
RecordDecl* RD = RT->getDecl();
|
||||
assert(RD->isDefinition());
|
||||
|
||||
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
|
||||
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
|
||||
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
||||
RecordDecl::field_iterator FI = RD->field_begin(), FE = RD->field_end();
|
||||
|
||||
for (; FI != FE; ++FI) {
|
||||
for (; FI != FE; ++FI, ++VI) {
|
||||
|
||||
// There may be fewer values than fields only when we are initializing a
|
||||
// struct decl. In this case, mark the region as having default value.
|
||||
if (VI == VE) {
|
||||
// GRStateRef state(St, StateMgr);
|
||||
//St = state.set<RegionDefaultValue>(R, NonLoc::MakeVal(getBasicVals(), 0,
|
||||
// false));
|
||||
break;
|
||||
}
|
||||
|
||||
QualType FTy = (*FI)->getType();
|
||||
FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
|
||||
|
||||
if (Loc::IsLocType(FTy) || FTy->isIntegerType()) {
|
||||
if (VI != VE) {
|
||||
store = Bind(store, loc::MemRegionVal(FR), *VI);
|
||||
++VI;
|
||||
} else
|
||||
store = Bind(store, loc::MemRegionVal(FR), UndefinedVal());
|
||||
}
|
||||
else if (FTy->isArrayType()) {
|
||||
if (VI != VE) {
|
||||
store = InitializeArray(store, FR, *VI);
|
||||
++VI;
|
||||
} else
|
||||
store = BindArrayToVal(store, FR, UndefinedVal());
|
||||
}
|
||||
else if (FTy->isStructureType()) {
|
||||
if (VI != VE) {
|
||||
store = InitializeStruct(store, FR, *VI);
|
||||
++VI;
|
||||
} else
|
||||
store = BindStructToVal(store, FR, UndefinedVal());
|
||||
}
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
||||
// Bind all fields of the struct to some value.
|
||||
Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR,
|
||||
SVal V) {
|
||||
|
||||
// FIXME: Verify that we should use getLValueType or getRValueType.
|
||||
QualType T = BaseR->getRValueType(getContext());
|
||||
assert(T->isStructureType());
|
||||
|
||||
const RecordType* RT = cast<RecordType>(T.getTypePtr());
|
||||
RecordDecl* RD = RT->getDecl();
|
||||
assert(RD->isDefinition());
|
||||
|
||||
RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
|
||||
|
||||
for (; I != E; ++I) {
|
||||
if (Loc::IsLocType(FTy) || FTy->isIntegerType())
|
||||
St = Bind(St, Loc::MakeVal(FR), *VI);
|
||||
|
||||
QualType FTy = (*I)->getType();
|
||||
FieldRegion* FR = MRMgr.getFieldRegion(*I, BaseR);
|
||||
|
||||
if (Loc::IsLocType(FTy) || FTy->isIntegerType()) {
|
||||
store = Bind(store, loc::MemRegionVal(FR), V);
|
||||
else if (FTy->isArrayType())
|
||||
St = BindArray(St, FR, *VI);
|
||||
|
||||
} else if (FTy->isArrayType()) {
|
||||
store = BindArrayToVal(store, FR, V);
|
||||
|
||||
} else if (FTy->isStructureType()) {
|
||||
store = BindStructToVal(store, FR, V);
|
||||
}
|
||||
else if (FTy->isStructureType())
|
||||
St = BindStruct(St, FR, *VI);
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
Store RegionStoreManager::BindStructToSymVal(Store store,
|
||||
const TypedRegion* BaseR) {
|
||||
|
||||
// FIXME: Verify that we should use getLValueType or getRValueType
|
||||
QualType T = BaseR->getRValueType(getContext());
|
||||
assert(T->isStructureType());
|
||||
|
||||
const RecordType* RT = cast<RecordType>(T.getTypePtr());
|
||||
RecordDecl* RD = RT->getDecl();
|
||||
assert(RD->isDefinition());
|
||||
|
||||
RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
|
||||
|
||||
for (; I != E; ++I) {
|
||||
QualType FTy = (*I)->getType();
|
||||
FieldRegion* FR = MRMgr.getFieldRegion(*I, BaseR);
|
||||
|
||||
if (Loc::IsLocType(FTy) || FTy->isIntegerType()) {
|
||||
store = Bind(store, loc::MemRegionVal(FR),
|
||||
SVal::getSymbolValue(getSymbolManager(), BaseR, *I, FTy));
|
||||
}
|
||||
else if (FTy->isArrayType()) {
|
||||
store = BindArrayToSymVal(store, FR);
|
||||
}
|
||||
else if (FTy->isStructureType()) {
|
||||
store = BindStructToSymVal(store, FR);
|
||||
}
|
||||
}
|
||||
|
||||
return store;
|
||||
return St;
|
||||
}
|
||||
|
||||
const GRState* RegionStoreManager::AddRegionView(const GRState* St,
|
||||
|
|
|
@ -242,6 +242,11 @@ NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const {
|
|||
//===----------------------------------------------------------------------===//
|
||||
// Utility methods for constructing Non-Locs.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
NonLoc NonLoc::MakeVal(SymbolRef sym) {
|
||||
return nonloc::SymbolVal(sym);
|
||||
}
|
||||
|
||||
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, unsigned X,
|
||||
bool isUnsigned) {
|
||||
return nonloc::ConcreteInt(BasicVals.getValue(X, sizeof(unsigned)*8,
|
||||
|
@ -281,6 +286,14 @@ NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
|
|||
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
|
||||
}
|
||||
|
||||
SVal SVal::MakeSymbolValue(SymbolManager& SymMgr, const MemRegion* R,
|
||||
QualType T) {
|
||||
if (Loc::IsLocType(T))
|
||||
return Loc::MakeVal(SymMgr.getSymbol(R));
|
||||
else
|
||||
return NonLoc::MakeVal(SymMgr.getSymbol(R));
|
||||
}
|
||||
|
||||
SVal SVal::GetSymbolValue(SymbolManager& SymMgr, VarDecl* D) {
|
||||
|
||||
QualType T = D->getType();
|
||||
|
@ -320,6 +333,8 @@ Loc Loc::MakeVal(const MemRegion* R) { return loc::MemRegionVal(R); }
|
|||
|
||||
Loc Loc::MakeVal(AddrLabelExpr* E) { return loc::GotoLabel(E->getLabel()); }
|
||||
|
||||
Loc Loc::MakeVal(SymbolRef sym) { return loc::SymbolVal(sym); }
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pretty-Printing.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/SymbolManager.h"
|
||||
#include "clang/Analysis/PathSensitive/MemRegion.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace clang;
|
||||
|
@ -21,14 +22,35 @@ void SymbolRef::print(llvm::raw_ostream& os) const {
|
|||
os << getNumber();
|
||||
}
|
||||
|
||||
SymbolRef SymbolManager::getSymbol(VarDecl* D) {
|
||||
SymbolRef SymbolManager::getSymbol(const MemRegion* R) {
|
||||
switch (R->getKind()) {
|
||||
case MemRegion::VarRegionKind:
|
||||
return getSymbol(cast<VarRegion>(R)->getDecl());
|
||||
|
||||
case MemRegion::ElementRegionKind: {
|
||||
const ElementRegion* ER = cast<ElementRegion>(R);
|
||||
const llvm::APSInt& Idx =
|
||||
cast<nonloc::ConcreteInt>(ER->getIndex()).getValue();
|
||||
return getElementSymbol(ER->getSuperRegion(), &Idx);
|
||||
}
|
||||
|
||||
case MemRegion::FieldRegionKind: {
|
||||
const FieldRegion* FR = cast<FieldRegion>(R);
|
||||
return getFieldSymbol(FR->getSuperRegion(), FR->getDecl());
|
||||
}
|
||||
default:
|
||||
assert(0 && "unprocessed region");
|
||||
}
|
||||
}
|
||||
|
||||
SymbolRef SymbolManager::getSymbol(const VarDecl* D) {
|
||||
|
||||
assert (isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ||
|
||||
D->hasGlobalStorage());
|
||||
|
||||
llvm::FoldingSetNodeID profile;
|
||||
|
||||
ParmVarDecl* PD = dyn_cast<ParmVarDecl>(D);
|
||||
const ParmVarDecl* PD = dyn_cast<ParmVarDecl>(D);
|
||||
|
||||
if (PD)
|
||||
SymbolDataParmVar::Profile(profile, PD);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// RUN: clang -std=gnu99 -checker-simple -verify %s &&
|
||||
// RUN: clang -std=gnu99 -checker-simple -analyzer-store-region -verify %s
|
||||
// RUN: clang -std=gnu99 -checker-simple -verify %s
|
||||
// DISABLE: clang -std=gnu99 -checker-simple -analyzer-store-region -verify %s
|
||||
|
||||
#include<stdint.h>
|
||||
#include <assert.h>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang -checker-simple -analyzer-store-region -verify %s
|
||||
// DISABLE: clang -checker-simple -analyzer-store-region -verify %s
|
||||
|
||||
struct s {
|
||||
int data;
|
||||
|
|
Loading…
Reference in New Issue