forked from OSchip/llvm-project
Simplify 'Environment' to contain only one map from 'const Stmt*' to SVals, greatly simplifying the logic of the analyzer in many places. We now only distinguish between block-level expressions and subexpressions in Environment::RemoveDeadBindings and GRState pretty-printing.
llvm-svn: 80194
This commit is contained in:
parent
81cb753298
commit
907a711f60
|
@ -26,10 +26,12 @@
|
|||
|
||||
namespace clang {
|
||||
|
||||
class AnalysisContext;
|
||||
class EnvironmentManager;
|
||||
class ValueManager;
|
||||
class LiveVariables;
|
||||
|
||||
|
||||
class Environment {
|
||||
private:
|
||||
friend class EnvironmentManager;
|
||||
|
@ -38,47 +40,27 @@ private:
|
|||
typedef llvm::ImmutableMap<const Stmt*,SVal> BindingsTy;
|
||||
|
||||
// Data.
|
||||
BindingsTy SubExprBindings;
|
||||
BindingsTy BlkExprBindings;
|
||||
BindingsTy ExprBindings;
|
||||
|
||||
Environment(BindingsTy seb, BindingsTy beb)
|
||||
: SubExprBindings(seb), BlkExprBindings(beb) {}
|
||||
Environment(BindingsTy eb)
|
||||
: ExprBindings(eb) {}
|
||||
|
||||
public:
|
||||
public:
|
||||
typedef BindingsTy::iterator iterator;
|
||||
iterator begin() const { return ExprBindings.begin(); }
|
||||
iterator end() const { return ExprBindings.end(); }
|
||||
|
||||
typedef BindingsTy::iterator seb_iterator;
|
||||
seb_iterator seb_begin() const { return SubExprBindings.begin(); }
|
||||
seb_iterator seb_end() const { return SubExprBindings.end(); }
|
||||
|
||||
typedef BindingsTy::iterator beb_iterator;
|
||||
beb_iterator beb_begin() const { return BlkExprBindings.begin(); }
|
||||
beb_iterator beb_end() const { return BlkExprBindings.end(); }
|
||||
|
||||
SVal LookupSubExpr(const Stmt* E) const {
|
||||
const SVal* X = SubExprBindings.lookup(cast<Expr>(E));
|
||||
return X ? *X : UnknownVal();
|
||||
}
|
||||
|
||||
SVal LookupBlkExpr(const Stmt* E) const {
|
||||
const SVal* X = BlkExprBindings.lookup(E);
|
||||
return X ? *X : UnknownVal();
|
||||
}
|
||||
|
||||
SVal LookupExpr(const Stmt* E) const {
|
||||
const SVal* X = SubExprBindings.lookup(E);
|
||||
if (X) return *X;
|
||||
X = BlkExprBindings.lookup(E);
|
||||
const SVal* X = ExprBindings.lookup(E);
|
||||
return X ? *X : UnknownVal();
|
||||
}
|
||||
|
||||
SVal GetSVal(const Stmt* Ex, ValueManager& ValMgr) const;
|
||||
SVal GetBlkExprSVal(const Stmt* Ex, ValueManager& ValMgr) const;
|
||||
|
||||
/// Profile - Profile the contents of an Environment object for use
|
||||
/// in a FoldingSet.
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, const Environment* E) {
|
||||
E->SubExprBindings.Profile(ID);
|
||||
E->BlkExprBindings.Profile(ID);
|
||||
E->ExprBindings.Profile(ID);
|
||||
}
|
||||
|
||||
/// Profile - Used to profile the contents of this object for inclusion
|
||||
|
@ -88,8 +70,7 @@ public:
|
|||
}
|
||||
|
||||
bool operator==(const Environment& RHS) const {
|
||||
return SubExprBindings == RHS.SubExprBindings &&
|
||||
BlkExprBindings == RHS.BlkExprBindings;
|
||||
return ExprBindings == RHS.ExprBindings;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -98,51 +79,20 @@ private:
|
|||
typedef Environment::BindingsTy::Factory FactoryTy;
|
||||
FactoryTy F;
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {}
|
||||
~EnvironmentManager() {}
|
||||
|
||||
/// RemoveBlkExpr - Return a new environment object with the same bindings as
|
||||
/// the provided environment except with any bindings for the provided Stmt*
|
||||
/// removed. This method only removes bindings for block-level expressions.
|
||||
/// Using this method on a non-block level expression will return the
|
||||
/// same environment object.
|
||||
Environment RemoveBlkExpr(const Environment& Env, const Stmt* E) {
|
||||
return Environment(Env.SubExprBindings, F.Remove(Env.BlkExprBindings, E));
|
||||
}
|
||||
|
||||
Environment RemoveSubExpr(const Environment& Env, const Stmt* E) {
|
||||
return Environment(F.Remove(Env.SubExprBindings, E), Env.BlkExprBindings);
|
||||
}
|
||||
|
||||
Environment AddBlkExpr(const Environment& Env, const Stmt *E, SVal V) {
|
||||
return Environment(Env.SubExprBindings, F.Add(Env.BlkExprBindings, E, V));
|
||||
}
|
||||
|
||||
Environment AddSubExpr(const Environment& Env, const Stmt *E, SVal V) {
|
||||
return Environment(F.Add(Env.SubExprBindings, E, V), Env.BlkExprBindings);
|
||||
}
|
||||
|
||||
/// RemoveSubExprBindings - Return a new environment object with
|
||||
/// the same bindings as the provided environment except with all the
|
||||
/// subexpression bindings removed.
|
||||
Environment RemoveSubExprBindings(const Environment& Env) {
|
||||
return Environment(F.GetEmptyMap(), Env.BlkExprBindings);
|
||||
}
|
||||
|
||||
Environment getInitialEnvironment() {
|
||||
return Environment(F.GetEmptyMap(), F.GetEmptyMap());
|
||||
return Environment(F.GetEmptyMap());
|
||||
}
|
||||
|
||||
Environment BindExpr(const Environment& Env, const Stmt* E, SVal V,
|
||||
bool isBlkExpr, bool Invalidate);
|
||||
|
||||
Environment
|
||||
RemoveDeadBindings(Environment Env, Stmt* Loc, SymbolReaper& SymReaper,
|
||||
GRStateManager& StateMgr, const GRState *state,
|
||||
llvm::SmallVectorImpl<const MemRegion*>& DRoots);
|
||||
Environment BindExpr(Environment Env, const Stmt *S, SVal V,
|
||||
bool Invalidate);
|
||||
|
||||
Environment RemoveDeadBindings(Environment Env, const Stmt *S,
|
||||
SymbolReaper &SymReaper, const GRState *ST,
|
||||
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
|
|
@ -67,6 +67,15 @@ template <typename T> struct GRStateTrait {
|
|||
|
||||
class GRStateManager;
|
||||
|
||||
class GRStateContext : public std::pair<GRStateManager*, AnalysisContext*> {
|
||||
public:
|
||||
GRStateContext(GRStateManager *Mgr, AnalysisContext *ACtx)
|
||||
: std::pair<GRStateManager*, AnalysisContext*>(Mgr, ACtx) {}
|
||||
|
||||
GRStateManager *getStateManager() const { return first; }
|
||||
AnalysisContext *getAnalysisContext() const { return second; }
|
||||
};
|
||||
|
||||
/// GRState - This class encapsulates the actual data values for
|
||||
/// for a "state" in our symbolic value tracking. It is intended to be
|
||||
/// used as a functional object; that is once it is created and made
|
||||
|
@ -81,7 +90,7 @@ private:
|
|||
|
||||
friend class GRStateManager;
|
||||
|
||||
GRStateManager *Mgr;
|
||||
GRStateContext StateCtx;
|
||||
Environment Env;
|
||||
Store St;
|
||||
|
||||
|
@ -92,9 +101,9 @@ public:
|
|||
public:
|
||||
|
||||
/// This ctor is used when creating the first GRState object.
|
||||
GRState(GRStateManager *mgr, const Environment& env, Store st,
|
||||
GenericDataMap gdm)
|
||||
: Mgr(mgr),
|
||||
GRState(GRStateManager *mgr, AnalysisContext *actx, const Environment& env,
|
||||
Store st, GenericDataMap gdm)
|
||||
: StateCtx(mgr, actx),
|
||||
Env(env),
|
||||
St(st),
|
||||
GDM(gdm) {}
|
||||
|
@ -103,13 +112,21 @@ public:
|
|||
/// in FoldingSetNode will also get copied.
|
||||
GRState(const GRState& RHS)
|
||||
: llvm::FoldingSetNode(),
|
||||
Mgr(RHS.Mgr),
|
||||
StateCtx(RHS.StateCtx),
|
||||
Env(RHS.Env),
|
||||
St(RHS.St),
|
||||
GDM(RHS.GDM) {}
|
||||
|
||||
/// getStateManager - Return the GRStateManager associated with this state.
|
||||
GRStateManager &getStateManager() const { return *Mgr; }
|
||||
GRStateManager &getStateManager() const {
|
||||
return *StateCtx.getStateManager();
|
||||
}
|
||||
|
||||
/// getAnalysisContext - Return the AnalysisContext associated with this
|
||||
/// state.
|
||||
AnalysisContext &getAnalysisContext() const {
|
||||
return *StateCtx.getAnalysisContext();
|
||||
}
|
||||
|
||||
/// getEnvironment - Return the environment associated with this state.
|
||||
/// The environment is the mapping from expressions to values.
|
||||
|
@ -129,6 +146,7 @@ public:
|
|||
/// Profile - Profile the contents of a GRState object for use
|
||||
/// in a FoldingSet.
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, const GRState* V) {
|
||||
// FIXME: Do we need to include the AnalysisContext in the profile?
|
||||
V->Env.Profile(ID);
|
||||
ID.AddPointer(V->St);
|
||||
V->GDM.Profile(ID);
|
||||
|
@ -147,16 +165,7 @@ public:
|
|||
/// makeWithStore - Return a GRState with the same values as the current
|
||||
/// state with the exception of using the specified Store.
|
||||
const GRState *makeWithStore(Store store) const;
|
||||
|
||||
// Iterators.
|
||||
typedef Environment::seb_iterator seb_iterator;
|
||||
seb_iterator seb_begin() const { return Env.seb_begin(); }
|
||||
seb_iterator seb_end() const { return Env.beb_end(); }
|
||||
|
||||
typedef Environment::beb_iterator beb_iterator;
|
||||
beb_iterator beb_begin() const { return Env.beb_begin(); }
|
||||
beb_iterator beb_end() const { return Env.beb_end(); }
|
||||
|
||||
|
||||
BasicValueFactory &getBasicVals() const;
|
||||
SymbolManager &getSymbolManager() const;
|
||||
GRTransferFuncs &getTransferFuncs() const;
|
||||
|
@ -216,16 +225,8 @@ public:
|
|||
const GRState* bindCompoundLiteral(const CompoundLiteralExpr* CL,
|
||||
SVal V) const;
|
||||
|
||||
const GRState *bindExpr(const Stmt* Ex, SVal V, bool isBlkExpr,
|
||||
bool Invalidate) const;
|
||||
|
||||
const GRState *bindExpr(const Stmt* Ex, SVal V, CFG &cfg,
|
||||
bool Invalidate = true) const;
|
||||
|
||||
const GRState *bindBlkExpr(const Stmt *Ex, SVal V) const {
|
||||
return bindExpr(Ex, V, true, false);
|
||||
}
|
||||
|
||||
const GRState *bindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
|
||||
|
||||
const GRState *bindDecl(const VarDecl *VD, const LocationContext *LC,
|
||||
SVal V) const;
|
||||
|
||||
|
@ -259,8 +260,6 @@ public:
|
|||
|
||||
SVal getSVal(const Stmt* Ex) const;
|
||||
|
||||
SVal getBlkExprSVal(const Stmt* Ex) const;
|
||||
|
||||
SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
|
||||
|
||||
SVal getSVal(Loc LV, QualType T = QualType()) const;
|
||||
|
@ -475,12 +474,6 @@ public:
|
|||
const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc,
|
||||
SymbolReaper& SymReaper);
|
||||
|
||||
const GRState* RemoveSubExprBindings(const GRState* St) {
|
||||
GRState NewSt = *St;
|
||||
NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env);
|
||||
return getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
SVal ArrayToPointer(Loc Array) {
|
||||
|
@ -583,36 +576,36 @@ public:
|
|||
|
||||
inline const VarRegion* GRState::getRegion(const VarDecl *D,
|
||||
const LocationContext *LC) const {
|
||||
return Mgr->getRegionManager().getVarRegion(D, LC);
|
||||
return getStateManager().getRegionManager().getVarRegion(D, LC);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::assume(SVal Cond, bool Assumption) const {
|
||||
return Mgr->ConstraintMgr->Assume(this, Cond, Assumption);
|
||||
return getStateManager().ConstraintMgr->Assume(this, Cond, Assumption);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::assumeInBound(SVal Idx, SVal UpperBound,
|
||||
bool Assumption) const {
|
||||
return Mgr->ConstraintMgr->AssumeInBound(this, Idx, UpperBound, Assumption);
|
||||
return getStateManager().ConstraintMgr->AssumeInBound(this, Idx, UpperBound, Assumption);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
|
||||
SVal V) const {
|
||||
return Mgr->StoreMgr->BindCompoundLiteral(this, CL, V);
|
||||
return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindDecl(const VarDecl* VD,
|
||||
const LocationContext *LC,
|
||||
SVal IVal) const {
|
||||
return Mgr->StoreMgr->BindDecl(this, VD, LC, IVal);
|
||||
return getStateManager().StoreMgr->BindDecl(this, VD, LC, IVal);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindDeclWithNoInit(const VarDecl* VD,
|
||||
const LocationContext *LC) const {
|
||||
return Mgr->StoreMgr->BindDeclWithNoInit(this, VD, LC);
|
||||
return getStateManager().StoreMgr->BindDeclWithNoInit(this, VD, LC);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
|
||||
return Mgr->StoreMgr->Bind(this, LV, V);
|
||||
return getStateManager().StoreMgr->Bind(this, LV, V);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
|
||||
|
@ -621,39 +614,35 @@ inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
|
|||
|
||||
inline SVal GRState::getLValue(const VarDecl* VD,
|
||||
const LocationContext *LC) const {
|
||||
return Mgr->StoreMgr->getLValueVar(this, VD, LC);
|
||||
return getStateManager().StoreMgr->getLValueVar(this, VD, LC);
|
||||
}
|
||||
|
||||
inline SVal GRState::getLValue(const StringLiteral *literal) const {
|
||||
return Mgr->StoreMgr->getLValueString(this, literal);
|
||||
return getStateManager().StoreMgr->getLValueString(this, literal);
|
||||
}
|
||||
|
||||
inline SVal GRState::getLValue(const CompoundLiteralExpr *literal) const {
|
||||
return Mgr->StoreMgr->getLValueCompoundLiteral(this, literal);
|
||||
return getStateManager().StoreMgr->getLValueCompoundLiteral(this, literal);
|
||||
}
|
||||
|
||||
inline SVal GRState::getLValue(const ObjCIvarDecl *D, SVal Base) const {
|
||||
return Mgr->StoreMgr->getLValueIvar(this, D, Base);
|
||||
return getStateManager().StoreMgr->getLValueIvar(this, D, Base);
|
||||
}
|
||||
|
||||
inline SVal GRState::getLValue(SVal Base, const FieldDecl* D) const {
|
||||
return Mgr->StoreMgr->getLValueField(this, Base, D);
|
||||
return getStateManager().StoreMgr->getLValueField(this, Base, D);
|
||||
}
|
||||
|
||||
inline SVal GRState::getLValue(QualType ElementType, SVal Base, SVal Idx) const{
|
||||
return Mgr->StoreMgr->getLValueElement(this, ElementType, Base, Idx);
|
||||
return getStateManager().StoreMgr->getLValueElement(this, ElementType, Base, Idx);
|
||||
}
|
||||
|
||||
inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const {
|
||||
return Mgr->getSymVal(this, sym);
|
||||
return getStateManager().getSymVal(this, sym);
|
||||
}
|
||||
|
||||
inline SVal GRState::getSVal(const Stmt* Ex) const {
|
||||
return Env.GetSVal(Ex, Mgr->ValueMgr);
|
||||
}
|
||||
|
||||
inline SVal GRState::getBlkExprSVal(const Stmt* Ex) const {
|
||||
return Env.GetBlkExprSVal(Ex, Mgr->ValueMgr);
|
||||
return Env.GetSVal(Ex, getStateManager().ValueMgr);
|
||||
}
|
||||
|
||||
inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const {
|
||||
|
@ -667,62 +656,62 @@ inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const {
|
|||
}
|
||||
|
||||
inline SVal GRState::getSVal(Loc LV, QualType T) const {
|
||||
return Mgr->StoreMgr->Retrieve(this, LV, T).getSVal();
|
||||
return getStateManager().StoreMgr->Retrieve(this, LV, T).getSVal();
|
||||
}
|
||||
|
||||
inline SVal GRState::getSVal(const MemRegion* R) const {
|
||||
return Mgr->StoreMgr->Retrieve(this, loc::MemRegionVal(R)).getSVal();
|
||||
return getStateManager().StoreMgr->Retrieve(this, loc::MemRegionVal(R)).getSVal();
|
||||
}
|
||||
|
||||
inline BasicValueFactory &GRState::getBasicVals() const {
|
||||
return Mgr->getBasicVals();
|
||||
return getStateManager().getBasicVals();
|
||||
}
|
||||
|
||||
inline SymbolManager &GRState::getSymbolManager() const {
|
||||
return Mgr->getSymbolManager();
|
||||
return getStateManager().getSymbolManager();
|
||||
}
|
||||
|
||||
inline GRTransferFuncs &GRState::getTransferFuncs() const {
|
||||
return Mgr->getTransferFuncs();
|
||||
return getStateManager().getTransferFuncs();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const {
|
||||
return Mgr->add<T>(this, K, get_context<T>());
|
||||
return getStateManager().add<T>(this, K, get_context<T>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename GRStateTrait<T>::context_type GRState::get_context() const {
|
||||
return Mgr->get_context<T>();
|
||||
return getStateManager().get_context<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::remove(typename GRStateTrait<T>::key_type K) const {
|
||||
return Mgr->remove<T>(this, K, get_context<T>());
|
||||
return getStateManager().remove<T>(this, K, get_context<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::remove(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::context_type C) const {
|
||||
return Mgr->remove<T>(this, K, C);
|
||||
return getStateManager().remove<T>(this, K, C);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::set(typename GRStateTrait<T>::data_type D) const {
|
||||
return Mgr->set<T>(this, D);
|
||||
return getStateManager().set<T>(this, D);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::value_type E) const {
|
||||
return Mgr->set<T>(this, K, E, get_context<T>());
|
||||
return getStateManager().set<T>(this, K, E, get_context<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
|
||||
typename GRStateTrait<T>::value_type E,
|
||||
typename GRStateTrait<T>::context_type C) const {
|
||||
return Mgr->set<T>(this, K, E, C);
|
||||
return getStateManager().set<T>(this, K, E, C);
|
||||
}
|
||||
|
||||
template <typename CB>
|
||||
|
|
|
@ -2900,7 +2900,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
|
|||
unsigned Count = Builder.getCurrentBlockCount();
|
||||
ValueManager &ValMgr = Eng.getValueManager();
|
||||
SVal X = ValMgr.getConjuredSymbolVal(Ex, T, Count);
|
||||
state = state->bindExpr(Ex, X, Pred->getCFG(), false);
|
||||
state = state->bindExpr(Ex, X, false);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2911,14 +2911,14 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
|
|||
assert (arg_end >= arg_beg);
|
||||
assert (idx < (unsigned) (arg_end - arg_beg));
|
||||
SVal V = state->getSValAsScalarOrLoc(*(arg_beg+idx));
|
||||
state = state->bindExpr(Ex, V, Pred->getCFG(), false);
|
||||
state = state->bindExpr(Ex, V, false);
|
||||
break;
|
||||
}
|
||||
|
||||
case RetEffect::ReceiverAlias: {
|
||||
assert (Receiver);
|
||||
SVal V = state->getSValAsScalarOrLoc(Receiver);
|
||||
state = state->bindExpr(Ex, V, Pred->getCFG(), false);
|
||||
state = state->bindExpr(Ex, V, false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2930,7 +2930,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
|
|||
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
|
||||
state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
|
||||
RetT));
|
||||
state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), Pred->getCFG(), false);
|
||||
state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), false);
|
||||
|
||||
// FIXME: Add a flag to the checker where allocations are assumed to
|
||||
// *not fail.
|
||||
|
@ -2953,7 +2953,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
|
|||
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
|
||||
state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
|
||||
RetT));
|
||||
state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), Pred->getCFG(), false);
|
||||
state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,42 +68,18 @@ SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const {
|
|||
return LookupExpr(E);
|
||||
}
|
||||
|
||||
SVal Environment::GetBlkExprSVal(const Stmt *E, ValueManager& ValMgr) const {
|
||||
|
||||
while (1) {
|
||||
switch (E->getStmtClass()) {
|
||||
case Stmt::ParenExprClass:
|
||||
E = cast<ParenExpr>(E)->getSubExpr();
|
||||
continue;
|
||||
|
||||
case Stmt::CharacterLiteralClass: {
|
||||
const CharacterLiteral* C = cast<CharacterLiteral>(E);
|
||||
return ValMgr.makeIntVal(C->getValue(), C->getType());
|
||||
}
|
||||
|
||||
case Stmt::IntegerLiteralClass: {
|
||||
return ValMgr.makeIntVal(cast<IntegerLiteral>(E));
|
||||
}
|
||||
|
||||
default:
|
||||
return LookupBlkExpr(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Environment EnvironmentManager::BindExpr(const Environment& Env, const Stmt* E,
|
||||
SVal V, bool isBlkExpr,
|
||||
bool Invalidate) {
|
||||
assert (E);
|
||||
Environment EnvironmentManager::BindExpr(Environment Env, const Stmt *S,
|
||||
SVal V, bool Invalidate) {
|
||||
assert(S);
|
||||
|
||||
if (V.isUnknown()) {
|
||||
if (Invalidate)
|
||||
return isBlkExpr ? RemoveBlkExpr(Env, E) : RemoveSubExpr(Env, E);
|
||||
return Environment(F.Remove(Env.ExprBindings, S));
|
||||
else
|
||||
return Env;
|
||||
}
|
||||
|
||||
return isBlkExpr ? AddBlkExpr(Env, E, V) : AddSubExpr(Env, E, V);
|
||||
return Environment(F.Add(Env.ExprBindings, S, V));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -124,23 +100,34 @@ public:
|
|||
// - Mark the region in DRoots if the binding is a loc::MemRegionVal.
|
||||
|
||||
Environment
|
||||
EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
|
||||
SymbolReaper& SymReaper,
|
||||
GRStateManager& StateMgr,
|
||||
const GRState *state,
|
||||
llvm::SmallVectorImpl<const MemRegion*>& DRoots) {
|
||||
EnvironmentManager::RemoveDeadBindings(Environment Env, const Stmt *S,
|
||||
SymbolReaper &SymReaper,
|
||||
const GRState *ST,
|
||||
llvm::SmallVectorImpl<const MemRegion*> &DRoots) {
|
||||
|
||||
CFG &C = *ST->getAnalysisContext().getCFG();
|
||||
|
||||
// We construct a new Environment object entirely, as this is cheaper than
|
||||
// individually removing all the subexpression bindings (which will greatly
|
||||
// outnumber block-level expression bindings).
|
||||
Environment NewEnv = getInitialEnvironment();
|
||||
|
||||
// Drop bindings for subexpressions.
|
||||
Env = RemoveSubExprBindings(Env);
|
||||
|
||||
// Iterate over the block-expr bindings.
|
||||
for (Environment::beb_iterator I = Env.beb_begin(), E = Env.beb_end();
|
||||
for (Environment::iterator I = Env.begin(), E = Env.end();
|
||||
I != E; ++I) {
|
||||
|
||||
const Stmt *BlkExpr = I.getKey();
|
||||
|
||||
if (SymReaper.isLive(Loc, BlkExpr)) {
|
||||
SVal X = I.getData();
|
||||
|
||||
|
||||
// Not a block-level expression?
|
||||
if (!C.isBlkExpr(BlkExpr))
|
||||
continue;
|
||||
|
||||
const SVal &X = I.getData();
|
||||
|
||||
if (SymReaper.isLive(S, BlkExpr)) {
|
||||
// Copy the binding to the new map.
|
||||
NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X);
|
||||
|
||||
// If the block expr's value is a memory region, then mark that region.
|
||||
if (isa<loc::MemRegionVal>(X)) {
|
||||
const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion();
|
||||
|
@ -151,28 +138,23 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
|
|||
// We only add one level super region for now.
|
||||
|
||||
// FIXME: maybe multiple level of super regions should be added.
|
||||
if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
|
||||
if (const SubRegion *SR = dyn_cast<SubRegion>(R))
|
||||
DRoots.push_back(SR->getSuperRegion());
|
||||
}
|
||||
}
|
||||
|
||||
// Mark all symbols in the block expr's value live.
|
||||
MarkLiveCallback cb(SymReaper);
|
||||
state->scanReachableSymbols(X, cb);
|
||||
} else {
|
||||
// The block expr is dead.
|
||||
SVal X = I.getData();
|
||||
|
||||
// Do not misclean LogicalExpr or ConditionalOperator. It is dead at the
|
||||
// beginning of itself, but we need its UndefinedVal to determine its
|
||||
// SVal.
|
||||
|
||||
if (X.isUndef() && cast<UndefinedVal>(X).getData())
|
||||
continue;
|
||||
|
||||
Env = RemoveBlkExpr(Env, BlkExpr);
|
||||
ST->scanReachableSymbols(X, cb);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise the expression is dead with a couple exceptions.
|
||||
// Do not misclean LogicalExpr or ConditionalOperator. It is dead at the
|
||||
// beginning of itself, but we need its UndefinedVal to determine its
|
||||
// SVal.
|
||||
if (X.isUndef() && cast<UndefinedVal>(X).getData())
|
||||
NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X);
|
||||
}
|
||||
|
||||
return Env;
|
||||
return NewEnv;
|
||||
}
|
||||
|
|
|
@ -341,8 +341,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
|
|||
}
|
||||
else if (B->getOpcode() == BinaryOperator::Comma) {
|
||||
const GRState* state = GetState(Pred);
|
||||
MakeNode(Dst, B, Pred, state->bindExpr(B, state->getSVal(B->getRHS()),
|
||||
Pred->getCFG()));
|
||||
MakeNode(Dst, B, Pred, state->bindExpr(B, state->getSVal(B->getRHS())));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -459,8 +458,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
|
|||
|
||||
if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
|
||||
const GRState* state = GetState(Pred);
|
||||
MakeNode(Dst, SE, Pred, state->bindExpr(SE, state->getSVal(LastExpr),
|
||||
Pred->getCFG()));
|
||||
MakeNode(Dst, SE, Pred, state->bindExpr(SE, state->getSVal(LastExpr)));
|
||||
}
|
||||
else
|
||||
Dst.Add(Pred);
|
||||
|
@ -543,7 +541,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
|
|||
case Stmt::StringLiteralClass: {
|
||||
const GRState* state = GetState(Pred);
|
||||
SVal V = state->getLValue(cast<StringLiteral>(Ex));
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG()));
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -612,7 +610,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
|
|||
(Op == BinaryOperator::LOr && !branchTaken)
|
||||
? B->getRHS() : B->getLHS();
|
||||
|
||||
return state->bindBlkExpr(B, UndefinedVal(Ex));
|
||||
return state->bindExpr(B, UndefinedVal(Ex));
|
||||
}
|
||||
|
||||
case Stmt::ConditionalOperatorClass: { // ?:
|
||||
|
@ -629,7 +627,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
|
|||
else
|
||||
Ex = C->getRHS();
|
||||
|
||||
return state->bindBlkExpr(C, UndefinedVal(Ex));
|
||||
return state->bindExpr(C, UndefinedVal(Ex));
|
||||
}
|
||||
|
||||
case Stmt::ChooseExprClass: { // ?:
|
||||
|
@ -637,7 +635,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
|
|||
ChooseExpr* C = cast<ChooseExpr>(Terminator);
|
||||
|
||||
Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();
|
||||
return state->bindBlkExpr(C, UndefinedVal(Ex));
|
||||
return state->bindExpr(C, UndefinedVal(Ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -684,10 +682,6 @@ static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
|
|||
void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
|
||||
GRBranchNodeBuilder& builder) {
|
||||
|
||||
// Remove old bindings for subexpressions.
|
||||
const GRState* PrevState =
|
||||
StateMgr.RemoveSubExprBindings(builder.getState());
|
||||
|
||||
// Check for NULL conditions; e.g. "for(;;)"
|
||||
if (!Condition) {
|
||||
builder.markInfeasible(false);
|
||||
|
@ -697,7 +691,8 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
|
|||
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
|
||||
Condition->getLocStart(),
|
||||
"Error evaluating branch");
|
||||
|
||||
|
||||
const GRState* PrevState = builder.getState();
|
||||
SVal V = PrevState->getSVal(Condition);
|
||||
|
||||
switch (V.getBaseKind()) {
|
||||
|
@ -808,16 +803,16 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
|
|||
assert (Ex == CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(Ex));
|
||||
|
||||
const GRState* state = GetState(Pred);
|
||||
SVal X = state->getBlkExprSVal(Ex);
|
||||
SVal X = state->getSVal(Ex);
|
||||
|
||||
assert (X.isUndef());
|
||||
|
||||
Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
|
||||
assert(SE);
|
||||
X = state->getBlkExprSVal(SE);
|
||||
X = state->getSVal(SE);
|
||||
|
||||
// Make sure that we invalidate the previous binding.
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, X, true, true));
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, X, true));
|
||||
}
|
||||
|
||||
/// ProcessSwitch - Called by GRCoreEngine. Used to generate successor
|
||||
|
@ -918,7 +913,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
|
|||
assert(B == CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B));
|
||||
|
||||
const GRState* state = GetState(Pred);
|
||||
SVal X = state->getBlkExprSVal(B);
|
||||
SVal X = state->getSVal(B);
|
||||
assert(X.isUndef());
|
||||
|
||||
Expr* Ex = (Expr*) cast<UndefinedVal>(X).getData();
|
||||
|
@ -927,12 +922,12 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
|
|||
|
||||
if (Ex == B->getRHS()) {
|
||||
|
||||
X = state->getBlkExprSVal(Ex);
|
||||
X = state->getSVal(Ex);
|
||||
|
||||
// Handle undefined values.
|
||||
|
||||
if (X.isUndef()) {
|
||||
MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X));
|
||||
MakeNode(Dst, B, Pred, state->bindExpr(B, X));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -944,11 +939,11 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
|
|||
// the payoff is not likely to be large. Instead, we do eager evaluation.
|
||||
if (const GRState *newState = state->assume(X, true))
|
||||
MakeNode(Dst, B, Pred,
|
||||
newState->bindBlkExpr(B, ValMgr.makeIntVal(1U, B->getType())));
|
||||
newState->bindExpr(B, ValMgr.makeIntVal(1U, B->getType())));
|
||||
|
||||
if (const GRState *newState = state->assume(X, false))
|
||||
MakeNode(Dst, B, Pred,
|
||||
newState->bindBlkExpr(B, ValMgr.makeIntVal(0U, B->getType())));
|
||||
newState->bindExpr(B, ValMgr.makeIntVal(0U, B->getType())));
|
||||
}
|
||||
else {
|
||||
// We took the LHS expression. Depending on whether we are '&&' or
|
||||
|
@ -956,7 +951,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
|
|||
// the short-circuiting.
|
||||
X = ValMgr.makeIntVal(B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U,
|
||||
B->getType());
|
||||
MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X));
|
||||
MakeNode(Dst, B, Pred, state->bindExpr(B, X));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -976,7 +971,7 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr *Ex, ExplodedNode *Pred,
|
|||
SVal V = state->getLValue(VD, Pred->getLocationContext());
|
||||
|
||||
if (asLValue)
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG()),
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V),
|
||||
ProgramPoint::PostLValueKind);
|
||||
else
|
||||
EvalLoad(Dst, Ex, Pred, state, V);
|
||||
|
@ -986,13 +981,13 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr *Ex, ExplodedNode *Pred,
|
|||
assert(!asLValue && "EnumConstantDecl does not have lvalue.");
|
||||
|
||||
SVal V = ValMgr.makeIntVal(ED->getInitVal());
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG()));
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V));
|
||||
return;
|
||||
|
||||
} else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
|
||||
assert(asLValue);
|
||||
SVal V = ValMgr.getFunctionPointer(FD);
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG()),
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V),
|
||||
ProgramPoint::PostLValueKind);
|
||||
return;
|
||||
}
|
||||
|
@ -1030,7 +1025,7 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A,
|
|||
state->getSVal(Idx));
|
||||
|
||||
if (asLValue)
|
||||
MakeNode(Dst, A, *I2, state->bindExpr(A, V, Pred->getCFG()),
|
||||
MakeNode(Dst, A, *I2, state->bindExpr(A, V),
|
||||
ProgramPoint::PostLValueKind);
|
||||
else
|
||||
EvalLoad(Dst, A, *I2, state, V);
|
||||
|
@ -1062,7 +1057,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
|
|||
SVal L = state->getLValue(state->getSVal(Base), Field);
|
||||
|
||||
if (asLValue)
|
||||
MakeNode(Dst, M, *I, state->bindExpr(M, L, Pred->getCFG()),
|
||||
MakeNode(Dst, M, *I, state->bindExpr(M, L),
|
||||
ProgramPoint::PostLValueKind);
|
||||
else
|
||||
EvalLoad(Dst, M, *I, state, L);
|
||||
|
@ -1146,7 +1141,7 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
|
|||
|
||||
if (location.isUnknown()) {
|
||||
// This is important. We must nuke the old binding.
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, UnknownVal(), Pred->getCFG()),
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, UnknownVal()),
|
||||
K, tag);
|
||||
}
|
||||
else {
|
||||
|
@ -1164,7 +1159,7 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
|
|||
// V = EvalCast(V, Ex->getType());
|
||||
//}
|
||||
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V, Pred->getCFG()), K, tag);
|
||||
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V), K, tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1387,16 +1382,14 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet& Dst,
|
|||
ExplodedNode *predNew = *I2;
|
||||
const GRState *stateNew = predNew->getState();
|
||||
SVal Res = Engine.getValueManager().makeTruthVal(true, CE->getType());
|
||||
Engine.MakeNode(Dst, CE, predNew, stateNew->bindExpr(CE, Res,
|
||||
Pred->getCFG()));
|
||||
Engine.MakeNode(Dst, CE, predNew, stateNew->bindExpr(CE, Res));
|
||||
}
|
||||
}
|
||||
|
||||
// Were they not equal?
|
||||
if (const GRState *stateNotEqual = stateLoad->assume(Cmp, false)) {
|
||||
SVal Res = Engine.getValueManager().makeTruthVal(false, CE->getType());
|
||||
Engine.MakeNode(Dst, CE, N, stateNotEqual->bindExpr(CE, Res,
|
||||
Pred->getCFG()));
|
||||
Engine.MakeNode(Dst, CE, N, stateNotEqual->bindExpr(CE, Res));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1611,7 +1604,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
|
|||
// For __builtin_expect, just return the value of the subexpression.
|
||||
assert (CE->arg_begin() != CE->arg_end());
|
||||
SVal X = state->getSVal(*(CE->arg_begin()));
|
||||
MakeNode(Dst, CE, *DI, state->bindExpr(CE, X, Pred->getCFG()));
|
||||
MakeNode(Dst, CE, *DI, state->bindExpr(CE, X));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1626,9 +1619,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
|
|||
// cannot represent values like symbol*8.
|
||||
SVal Extent = state->getSVal(*(CE->arg_begin()));
|
||||
state = getStoreManager().setExtent(state, R, Extent);
|
||||
|
||||
MakeNode(Dst, CE, *DI, state->bindExpr(CE, loc::MemRegionVal(R),
|
||||
Pred->getCFG()));
|
||||
MakeNode(Dst, CE, *DI, state->bindExpr(CE, loc::MemRegionVal(R)));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1701,8 +1692,7 @@ void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
|||
// First assume that the condition is true.
|
||||
if (const GRState *stateTrue = state->assume(V, true)) {
|
||||
stateTrue = stateTrue->bindExpr(Ex,
|
||||
ValMgr.makeIntVal(1U, Ex->getType()),
|
||||
Pred->getCFG());
|
||||
ValMgr.makeIntVal(1U, Ex->getType()));
|
||||
Dst.Add(Builder->generateNode(PostStmtCustom(Ex,
|
||||
&EagerlyAssumeTag, Pred->getLocationContext()),
|
||||
stateTrue, Pred));
|
||||
|
@ -1711,8 +1701,7 @@ void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
|||
// Next, assume that the condition is false.
|
||||
if (const GRState *stateFalse = state->assume(V, false)) {
|
||||
stateFalse = stateFalse->bindExpr(Ex,
|
||||
ValMgr.makeIntVal(0U, Ex->getType()),
|
||||
Pred->getCFG());
|
||||
ValMgr.makeIntVal(0U, Ex->getType()));
|
||||
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag,
|
||||
Pred->getLocationContext()),
|
||||
stateFalse, Pred));
|
||||
|
@ -1741,7 +1730,7 @@ void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex,
|
|||
SVal location = state->getLValue(Ex->getDecl(), BaseVal);
|
||||
|
||||
if (asLValue)
|
||||
MakeNode(Dst, Ex, *I, state->bindExpr(Ex, location, Pred->getCFG()));
|
||||
MakeNode(Dst, Ex, *I, state->bindExpr(Ex, location));
|
||||
else
|
||||
EvalLoad(Dst, Ex, *I, state, location);
|
||||
}
|
||||
|
@ -1817,11 +1806,11 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
|
|||
|
||||
// Handle the case where the container still has elements.
|
||||
SVal TrueV = ValMgr.makeTruthVal(1);
|
||||
const GRState *hasElems = state->bindExpr(S, TrueV, Pred->getCFG());
|
||||
const GRState *hasElems = state->bindExpr(S, TrueV);
|
||||
|
||||
// Handle the case where the container has no elements.
|
||||
SVal FalseV = ValMgr.makeTruthVal(0);
|
||||
const GRState *noElems = state->bindExpr(S, FalseV, Pred->getCFG());
|
||||
const GRState *noElems = state->bindExpr(S, FalseV);
|
||||
|
||||
if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
|
||||
if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
|
||||
|
@ -1973,7 +1962,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
|
|||
// of this case unless we have *a lot* more knowledge.
|
||||
//
|
||||
SVal V = ValMgr.makeZeroVal(ME->getType());
|
||||
MakeNode(Dst, ME, Pred, StNull->bindExpr(ME, V, Pred->getCFG()));
|
||||
MakeNode(Dst, ME, Pred, StNull->bindExpr(ME, V));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2110,7 +2099,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, Exploded
|
|||
const GRState* state = GetState(N);
|
||||
SVal V = state->getSVal(Ex);
|
||||
const SValuator::CastResult &Res = SVator.EvalCast(V, state, T, ExTy);
|
||||
state = Res.getState()->bindExpr(CastE, Res.getSVal(), Pred->getCFG());
|
||||
state = Res.getState()->bindExpr(CastE, Res.getSVal());
|
||||
MakeNode(Dst, CastE, N, state);
|
||||
}
|
||||
}
|
||||
|
@ -2129,10 +2118,9 @@ void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL,
|
|||
state = state->bindCompoundLiteral(CL, ILV);
|
||||
|
||||
if (asLValue)
|
||||
MakeNode(Dst, CL, *I, state->bindExpr(CL, state->getLValue(CL),
|
||||
Pred->getCFG()));
|
||||
MakeNode(Dst, CL, *I, state->bindExpr(CL, state->getLValue(CL)));
|
||||
else
|
||||
MakeNode(Dst, CL, *I, state->bindExpr(CL, ILV, Pred->getCFG()));
|
||||
MakeNode(Dst, CL, *I, state->bindExpr(CL, ILV));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2256,7 +2244,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
|
|||
// e.g: static int* myArray[] = {};
|
||||
if (NumInitElements == 0) {
|
||||
SVal V = ValMgr.makeCompoundVal(T, StartVals);
|
||||
MakeNode(Dst, E, Pred, state->bindExpr(E, V, Pred->getCFG()));
|
||||
MakeNode(Dst, E, Pred, state->bindExpr(E, V));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2291,7 +2279,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
|
|||
SVal V = ValMgr.makeCompoundVal(T, NewVals);
|
||||
|
||||
// Make final state and node.
|
||||
MakeNode(Dst, E, *NI, state->bindExpr(E, V, (*NI)->getCFG()));
|
||||
MakeNode(Dst, E, *NI, state->bindExpr(E, V));
|
||||
}
|
||||
else {
|
||||
// Still some initializer values to go. Push them onto the worklist.
|
||||
|
@ -2310,7 +2298,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
|
|||
Visit(Init, Pred, Tmp);
|
||||
for (ExplodedNodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I != EI; ++I) {
|
||||
state = GetState(*I);
|
||||
MakeNode(Dst, E, *I, state->bindExpr(E, state->getSVal(Init), Pred->getCFG()));
|
||||
MakeNode(Dst, E, *I, state->bindExpr(E, state->getSVal(Init)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -2351,8 +2339,7 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
|
|||
amt = getContext().getTypeAlign(T) / 8;
|
||||
|
||||
MakeNode(Dst, Ex, Pred,
|
||||
GetState(Pred)->bindExpr(Ex, ValMgr.makeIntVal(amt, Ex->getType()),
|
||||
Pred->getCFG()));
|
||||
GetState(Pred)->bindExpr(Ex, ValMgr.makeIntVal(amt, Ex->getType())));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2376,7 +2363,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
SVal location = state->getSVal(Ex);
|
||||
|
||||
if (asLValue)
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, location, (*I)->getCFG()),
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, location),
|
||||
ProgramPoint::PostLValueKind);
|
||||
else
|
||||
EvalLoad(Dst, U, *I, state, location);
|
||||
|
@ -2403,7 +2390,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
// For all other types, UnaryOperator::Real is an identity operation.
|
||||
assert (U->getType() == Ex->getType());
|
||||
const GRState* state = GetState(*I);
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex), (*I)->getCFG()));
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex)));
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -2427,7 +2414,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
assert (Ex->getType()->isIntegerType());
|
||||
const GRState* state = GetState(*I);
|
||||
SVal X = ValMgr.makeZeroVal(Ex->getType());
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, X, (*I)->getCFG()));
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, X));
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -2452,7 +2439,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
|
||||
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
|
||||
const GRState* state = GetState(*I);
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex), (*I)->getCFG()));
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex)));
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -2468,7 +2455,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
|
||||
const GRState* state = GetState(*I);
|
||||
SVal V = state->getSVal(Ex);
|
||||
state = state->bindExpr(U, V, (*I)->getCFG());
|
||||
state = state->bindExpr(U, V);
|
||||
MakeNode(Dst, U, *I, state);
|
||||
}
|
||||
|
||||
|
@ -2491,7 +2478,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
SVal V = state->getSVal(Ex);
|
||||
|
||||
if (V.isUnknownOrUndef()) {
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, V, (*I)->getCFG()));
|
||||
MakeNode(Dst, U, *I, state->bindExpr(U, V));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2513,13 +2500,12 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
|
||||
case UnaryOperator::Not:
|
||||
// FIXME: Do we need to handle promotions?
|
||||
state = state->bindExpr(U, EvalComplement(cast<NonLoc>(V)),
|
||||
(*I)->getCFG());
|
||||
state = state->bindExpr(U, EvalComplement(cast<NonLoc>(V)));
|
||||
break;
|
||||
|
||||
case UnaryOperator::Minus:
|
||||
// FIXME: Do we need to handle promotions?
|
||||
state = state->bindExpr(U, EvalMinus(cast<NonLoc>(V)), (*I)->getCFG());
|
||||
state = state->bindExpr(U, EvalMinus(cast<NonLoc>(V)));
|
||||
break;
|
||||
|
||||
case UnaryOperator::LNot:
|
||||
|
@ -2541,7 +2527,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
U->getType());
|
||||
}
|
||||
|
||||
state = state->bindExpr(U, Result, (*I)->getCFG());
|
||||
state = state->bindExpr(U, Result);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2576,7 +2562,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
|
||||
// Propagate unknown and undefined values.
|
||||
if (V2.isUnknownOrUndef()) {
|
||||
MakeNode(Dst, U, *I2, state->bindExpr(U, V2, (*I2)->getCFG()));
|
||||
MakeNode(Dst, U, *I2, state->bindExpr(U, V2));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2622,7 +2608,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
|
|||
}
|
||||
}
|
||||
|
||||
state = state->bindExpr(U, U->isPostfix() ? V2 : Result, (*I2)->getCFG());
|
||||
state = state->bindExpr(U, U->isPostfix() ? V2 : Result);
|
||||
|
||||
// Perform the store.
|
||||
EvalStore(Dst, U, *I2, state, V1, Result);
|
||||
|
@ -2846,7 +2832,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
|||
|
||||
// Simulate the effects of a "store": bind the value of the RHS
|
||||
// to the L-Value represented by the LHS.
|
||||
EvalStore(Dst, B, LHS, *I2, state->bindExpr(B, RightV, (*I2)->getCFG()),
|
||||
EvalStore(Dst, B, LHS, *I2, state->bindExpr(B, RightV),
|
||||
LeftV, RightV);
|
||||
continue;
|
||||
}
|
||||
|
@ -2889,7 +2875,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
|||
// The operands were *not* undefined, but the result is undefined.
|
||||
// This is a special node that should be flagged as an error.
|
||||
|
||||
if (ExplodedNode* UndefNode = Builder->generateNode(B, state, *I2)) {
|
||||
if (ExplodedNode* UndefNode = Builder->generateNode(B, state, *I2)){
|
||||
UndefNode->markAsSink();
|
||||
UndefResults.insert(UndefNode);
|
||||
}
|
||||
|
@ -2899,7 +2885,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
|||
|
||||
// Otherwise, create a new node.
|
||||
|
||||
MakeNode(Dst, B, *I2, state->bindExpr(B, Result, (*I2)->getCFG()));
|
||||
MakeNode(Dst, B, *I2, state->bindExpr(B, Result));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -2947,15 +2933,15 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
|||
|
||||
// Propagate undefined values (left-side).
|
||||
if (V.isUndef()) {
|
||||
EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, V, (*I3)->getCFG()),
|
||||
EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, V),
|
||||
location, V);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Propagate unknown values (left and right-side).
|
||||
if (RightV.isUnknown() || V.isUnknown()) {
|
||||
EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, UnknownVal(),
|
||||
(*I3)->getCFG()), location, UnknownVal());
|
||||
EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, UnknownVal()),
|
||||
location, UnknownVal());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2982,8 +2968,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
|||
// Evaluate operands and promote to result type.
|
||||
if (RightV.isUndef()) {
|
||||
// Propagate undefined values (right-side).
|
||||
EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, RightV, (*I3)->getCFG()),
|
||||
location, RightV);
|
||||
EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, RightV), location,
|
||||
RightV);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3028,7 +3014,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
|
|||
llvm::tie(state, LHSVal) = SVator.EvalCast(Result, state, LTy, CTy);
|
||||
}
|
||||
|
||||
EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, Result, (*I3)->getCFG()),
|
||||
EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, Result),
|
||||
location, LHSVal);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ GRStateManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
|
|||
llvm::SmallVector<const MemRegion*, 10> RegionRoots;
|
||||
GRState NewState = *state;
|
||||
|
||||
NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, SymReaper, *this,
|
||||
NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, SymReaper,
|
||||
state, RegionRoots);
|
||||
|
||||
// Clean up the store.
|
||||
|
@ -58,14 +58,14 @@ GRStateManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
|
|||
|
||||
const GRState *GRState::unbindLoc(Loc LV) const {
|
||||
Store OldStore = getStore();
|
||||
Store NewStore = Mgr->StoreMgr->Remove(OldStore, LV);
|
||||
Store NewStore = getStateManager().StoreMgr->Remove(OldStore, LV);
|
||||
|
||||
if (NewStore == OldStore)
|
||||
return this;
|
||||
|
||||
GRState NewSt = *this;
|
||||
NewSt.St = NewStore;
|
||||
return Mgr->getPersistentState(NewSt);
|
||||
return getStateManager().getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
|
||||
|
@ -76,7 +76,7 @@ SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
|
|||
return UnknownVal();
|
||||
|
||||
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
|
||||
QualType T = TR->getValueType(Mgr->getContext());
|
||||
QualType T = TR->getValueType(getStateManager().getContext());
|
||||
if (Loc::IsLocType(T) || T->isIntegerType())
|
||||
return getSVal(R);
|
||||
}
|
||||
|
@ -85,38 +85,22 @@ SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
|
|||
}
|
||||
|
||||
|
||||
const GRState *GRState::bindExpr(const Stmt* Ex, SVal V, bool isBlkExpr,
|
||||
bool Invalidate) const {
|
||||
const GRState *GRState::bindExpr(const Stmt* Ex, SVal V, bool Invalidate) const {
|
||||
|
||||
Environment NewEnv = Mgr->EnvMgr.BindExpr(Env, Ex, V, isBlkExpr, Invalidate);
|
||||
Environment NewEnv = getStateManager().EnvMgr.BindExpr(Env, Ex, V,
|
||||
Invalidate);
|
||||
|
||||
if (NewEnv == Env)
|
||||
return this;
|
||||
|
||||
GRState NewSt = *this;
|
||||
NewSt.Env = NewEnv;
|
||||
return Mgr->getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
const GRState *GRState::bindExpr(const Stmt* Ex, SVal V, CFG &cfg,
|
||||
bool Invalidate) const {
|
||||
|
||||
bool isBlkExpr = false;
|
||||
|
||||
if (Ex == Mgr->CurrentStmt) {
|
||||
// FIXME: Should this just be an assertion? When would we want to set
|
||||
// the value of a block-level expression if it wasn't CurrentStmt?
|
||||
isBlkExpr = cfg.isBlkExpr(Ex);
|
||||
|
||||
if (!isBlkExpr)
|
||||
return this;
|
||||
}
|
||||
|
||||
return bindExpr(Ex, V, isBlkExpr, Invalidate);
|
||||
return getStateManager().getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) {
|
||||
GRState State(this, EnvMgr.getInitialEnvironment(),
|
||||
GRState State(this, InitLoc->getAnalysisContext(),
|
||||
EnvMgr.getInitialEnvironment(),
|
||||
StoreMgr->getInitialStore(InitLoc),
|
||||
GDMFactory.GetEmptyMap());
|
||||
|
||||
|
@ -141,7 +125,7 @@ const GRState* GRStateManager::getPersistentState(GRState& State) {
|
|||
const GRState* GRState::makeWithStore(Store store) const {
|
||||
GRState NewSt = *this;
|
||||
NewSt.St = store;
|
||||
return Mgr->getPersistentState(NewSt);
|
||||
return getStateManager().getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -151,12 +135,17 @@ const GRState* GRState::makeWithStore(Store store) const {
|
|||
void GRState::print(llvm::raw_ostream& Out, const char* nl,
|
||||
const char* sep) const {
|
||||
// Print the store.
|
||||
Mgr->getStoreManager().print(getStore(), Out, nl, sep);
|
||||
GRStateManager &Mgr = getStateManager();
|
||||
Mgr.getStoreManager().print(getStore(), Out, nl, sep);
|
||||
|
||||
CFG &C = *getAnalysisContext().getCFG();
|
||||
|
||||
// Print Subexpression bindings.
|
||||
bool isFirst = true;
|
||||
|
||||
for (seb_iterator I = seb_begin(), E = seb_end(); I != E; ++I) {
|
||||
for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
|
||||
if (C.isBlkExpr(I.getKey()))
|
||||
continue;
|
||||
|
||||
if (isFirst) {
|
||||
Out << nl << nl << "Sub-Expressions:" << nl;
|
||||
|
@ -172,8 +161,10 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl,
|
|||
|
||||
// Print block-expression bindings.
|
||||
isFirst = true;
|
||||
|
||||
for (beb_iterator I = beb_begin(), E = beb_end(); I != E; ++I) {
|
||||
|
||||
for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
|
||||
if (!C.isBlkExpr(I.getKey()))
|
||||
continue;
|
||||
|
||||
if (isFirst) {
|
||||
Out << nl << nl << "Block-level Expressions:" << nl;
|
||||
|
@ -187,11 +178,11 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl,
|
|||
Out << " : " << I.getData();
|
||||
}
|
||||
|
||||
Mgr->getConstraintManager().print(this, Out, nl, sep);
|
||||
Mgr.getConstraintManager().print(this, Out, nl, sep);
|
||||
|
||||
// Print checker-specific data.
|
||||
for (std::vector<Printer*>::iterator I = Mgr->Printers.begin(),
|
||||
E = Mgr->Printers.end(); I != E; ++I) {
|
||||
for (std::vector<Printer*>::iterator I = Mgr.Printers.begin(),
|
||||
E = Mgr.Printers.end(); I != E; ++I) {
|
||||
(*I)->Print(Out, this, nl, sep);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue