const GRState* SetRVal(const GRState* St, const Expr* Ex, RVal V) {
return SetRVal(St, const_cast<Expr*>(Ex), V);
}
-
- LVal getLVal(VarDecl* V) {
- return getStateManager().getLVal(V);
- }
-
+
protected:
const GRState* SetBlkExprRVal(const GRState* St, Expr* Ex, RVal V) {
RVal GetRVal(const GRState* St, LVal LV, QualType T = QualType()) {
return StateMgr.GetRVal(St, LV, T);
}
-
- // Get the lvalue of an expression.
- // FIXME: Remove this method, and used specialized versions of GetLValue
- // in GRStateManager.
- RVal GetLValue(const GRState* St, const Expr* Ex) {
- return StateMgr.GetLValue(St, Ex);
- }
inline NonLVal MakeConstantVal(uint64_t X, Expr* Ex) {
return NonLVal::MakeVal(getBasicVals(), X, Ex->getType());
return getRegionManager().getVarRegion(D);
}
- LVal getLVal(const VarDecl* D) {
- return StoreMgr->getLVal(D);
+ // Get the lvalue for a variable reference.
+ RVal GetLValue(const GRState* St, const VarDecl* D) {
+ return StoreMgr->getLValueVar(St, D);
}
-
- // Get the lvalue of expression.
- // FIXME: Remove this method, and implement specialized versions for
- // specific Decls.
- RVal GetLValue(const GRState* St, const Expr* Ex) {
- // Forward to store manager. The lvalue of an expression is determined by
- // the store manager.
- return StoreMgr->getLValue(St, Ex);
+
+ // Get the lvalue for an ivar reference.
+ RVal GetLValue(const GRState* St, const ObjCIvarDecl* D, RVal Base) {
+ return StoreMgr->getLValueIvar(St, D, Base);
}
- RVal GetLValue(const GRState* St, ObjCIvarDecl* D, RVal Base) {
- return StoreMgr->getLValue(St, D, Base);
+ // Get the lvalue for a field reference.
+ RVal GetLValue(const GRState* St, const FieldDecl* D, RVal Base) {
+ return StoreMgr->getLValueField(St, D, Base);
}
+
+ // Get the lvalue for an array index.
+ RVal GetLValue(const GRState* St, RVal Base, RVal Idx) {
+ return StoreMgr->getLValueElement(St, Base, Idx);
+ }
// Methods that query & manipulate the Environment.
return GRStateRef(Mgr->remove<T>(St, K, get_context<T>()), *Mgr);
}
+ // Lvalue methods.
+ RVal GetLValue(const VarDecl* VD) {
+ return Mgr->GetLValue(St, VD);
+ }
+
// Pretty-printing.
void print(std::ostream& Out, const char* nl = "\n",
const char *sep = "") const;
symbol_iterator symbol_begin() const;
symbol_iterator symbol_end() const;
- static RVal MakeVal(GRStateManager& SMgr, DeclRefExpr* E);
-
// Implement isa<T> support.
static inline bool classof(const RVal*) { return true; }
};
namespace lval {
enum Kind { SymbolValKind, GotoLabelKind, MemRegionKind, FuncValKind,
- ConcreteIntKind, StringLiteralValKind, FieldOffsetKind,
- ArrayOffsetKind };
+ ConcreteIntKind, StringLiteralValKind };
class SymbolVal : public LVal {
public:
}
};
-class FieldOffset : public LVal {
- FieldOffset(const std::pair<RVal, uintptr_t>& data)
- : LVal(FieldOffsetKind, &data) {}
-
-public:
-
- LVal getBase() const {
- return reinterpret_cast<const std::pair<LVal,uintptr_t>*> (Data)->first;
- }
-
- const LVal& getPersistentBase() const {
- return reinterpret_cast<const std::pair<LVal,uintptr_t>*> (Data)->first;
- }
-
-
- FieldDecl* getFieldDecl() const {
- return (FieldDecl*)
- reinterpret_cast<const std::pair<LVal,uintptr_t>*> (Data)->second;
- }
-
- // Implement isa<T> support.
- static inline bool classof(const RVal* V) {
- return V->getBaseKind() == LValKind &&
- V->getSubKind() == FieldOffsetKind;
- }
-
- static inline bool classof(const LVal* V) {
- return V->getSubKind() == FieldOffsetKind;
- }
-
- static inline RVal Make(BasicValueFactory& Vals, RVal Base, FieldDecl* D) {
-
- if (Base.isUnknownOrUndef())
- return Base;
-
- return FieldOffset(Vals.getPersistentRValWithData(cast<LVal>(Base),
- (uintptr_t) D));
- }
-};
-
-class ArrayOffset : public LVal {
- ArrayOffset(const std::pair<RVal,RVal>& data) : LVal(ArrayOffsetKind,&data) {}
-public:
-
- LVal getBase() const {
- return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->first;
- }
-
- const LVal& getPersistentBase() const {
- return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->first;
- }
-
- RVal getOffset() const {
- return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->second;
- }
-
- const RVal& getPersistentOffset() const {
- return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->second;
- }
-
-
- // Implement isa<T> support.
- static inline bool classof(const RVal* V) {
- return V->getBaseKind() == LValKind &&
- V->getSubKind() == ArrayOffsetKind;
- }
-
- static inline bool classof(const LVal* V) {
- return V->getSubKind() == ArrayOffsetKind;
- }
-
- static inline RVal Make(BasicValueFactory& Vals, RVal Base, RVal Offset) {
-
- if (Base.isUnknownOrUndef())
- return Base;
-
- if (Offset.isUndef())
- return Offset;
-
- return ArrayOffset(Vals.getPersistentRValPair(cast<LVal>(Base), Offset));
- }
-};
-
} // end clang::lval namespace
} // end clang namespace
virtual Store Remove(Store St, LVal LV) = 0;
virtual Store getInitialStore() = 0;
virtual MemRegionManager& getRegionManager() = 0;
- virtual LVal getLVal(const VarDecl* VD) = 0;
- // Get the lvalue of an expression.
- // FIXME: Remove this method, and implement specialized versions for
- // specific Decls.
- virtual RVal getLValue(const GRState* St, const Expr* Ex) = 0;
+ virtual RVal getLValueVar(const GRState* St, const VarDecl* VD) = 0;
- virtual RVal getLValue(const GRState* St, const ObjCIvarDecl* D, RVal Base)=0;
+ virtual RVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
+ RVal Base)=0;
+
+ virtual RVal getLValueField(const GRState* St, const FieldDecl* D,
+ RVal Base) = 0;
+
+ virtual RVal getLValueElement(const GRState* St, RVal Base, RVal Offset) = 0;
virtual Store
isFeasible = Assumption;
return St;
- case lval::FieldOffsetKind:
- return AssumeAux(St, cast<lval::FieldOffset>(Cond).getBase(),
- Assumption, isFeasible);
-
- case lval::ArrayOffsetKind:
- return AssumeAux(St, cast<lval::ArrayOffset>(Cond).getBase(),
- Assumption, isFeasible);
-
case lval::ConcreteIntKind: {
bool b = cast<lval::ConcreteInt>(Cond).getValue() != 0;
isFeasible = b ? Assumption : !Assumption;
virtual LVal getLVal(const VarDecl* VD) {
return lval::MemRegionVal(MRMgr.getVarRegion(VD));
}
-
- virtual RVal getLValue(const GRState* St, const Expr* Ex);
- virtual RVal getLValue(const GRState* St, const ObjCIvarDecl* D, RVal Base);
+
+ RVal getLValueVar(const GRState* St, const VarDecl* VD);
+ RVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, RVal Base);
+ RVal getLValueField(const GRState* St, const FieldDecl* D, RVal Base);
+ RVal getLValueElement(const GRState* St, RVal Base, RVal Offset);
virtual Store
RemoveDeadBindings(Store store, Stmt* Loc, const LiveVariables& Live,
StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
return new BasicStoreManager(StMgr);
}
+RVal BasicStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
+ QualType T = VD->getType();
+ assert(!T->isArrayType() && "Array and struct variable have no lvalue.");
+ return lval::MemRegionVal(MRMgr.getVarRegion(VD));
+}
+
+RVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
+ RVal Base) {
+ return UnknownVal();
+}
+
+
+RVal BasicStoreManager::getLValueField(const GRState* St, const FieldDecl* D,
+ RVal Base) {
+ return UnknownVal();
+}
-// FIXME: replace ArrayOffset and FieldOffset with some region value.
-RVal BasicStoreManager::getLValue(const GRState* St, const Expr* Ex) {
- if (const DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(Ex)) {
- const VarDecl* VD = cast<VarDecl>(DRE->getDecl());
- QualType T = VD->getType();
-
- // Array and struct variable have no lvalue.
- assert(!T->isArrayType());
-
- return lval::MemRegionVal(MRMgr.getVarRegion(VD));
-
- } else if (const ArraySubscriptExpr* A = dyn_cast<ArraySubscriptExpr>(Ex)) {
- const Expr* Base = A->getBase()->IgnoreParens();
- const Expr* Idx = A->getIdx()->IgnoreParens();
- RVal BaseV = StateMgr.GetRVal(St, Base);
- RVal IdxV = StateMgr.GetRVal(St, Idx);
- return lval::ArrayOffset::Make(StateMgr.getBasicVals(), BaseV, IdxV);
-
- } else if (const MemberExpr* M = dyn_cast<MemberExpr>(Ex)) {
- Expr* Base = M->getBase()->IgnoreParens();
- RVal BaseV = StateMgr.GetRVal(St, Base);
- return lval::FieldOffset::Make(StateMgr.getBasicVals(), BaseV,
- M->getMemberDecl());
- } else {
- Ex->dump();
- assert(0);
- }
+RVal BasicStoreManager::getLValueElement(const GRState* St, RVal Base,
+ RVal Offset) {
+ return UnknownVal();
}
RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
// Some clients may call GetRVal with such an option simply because
// they are doing a quick scan through their LVals (potentially to
// invalidate their bindings). Just return Undefined.
- return UndefinedVal();
-
- case lval::ArrayOffsetKind:
- case lval::FieldOffsetKind:
- return UnknownVal();
-
+ return UndefinedVal();
case lval::FuncValKind:
return LV;
return UnknownVal();
}
-
-RVal BasicStoreManager::getLValue(const GRState* St, const ObjCIvarDecl* D,
- RVal Base) {
- return UnknownVal();
-}
Store BasicStoreManager::SetRVal(Store store, LVal LV, RVal V) {
switch (LV.getSubKind()) {
GRExprEngine& Eng, GRBugReporter& BR,
bool isNSErrorWarning) {
- RVal ParamRVal = rootState.GetRVal(Eng.getLVal(Param));
+ RVal ParamRVal = rootState.GetLValue(Param);
// FIXME: For now assume that ParamRVal is symbolic. We need to generalize
// this later.
return;
}
- RVal V = GetLValue(St, Ex);
+ RVal V = StateMgr.GetLValue(St, VD);
+
if (asLValue)
MakeNode(Dst, Ex, Pred, SetRVal(St, Ex, V));
else
Expr* Base = A->getBase()->IgnoreParens();
Expr* Idx = A->getIdx()->IgnoreParens();
-
NodeSet Tmp;
-
- // Get Base's rvalue, which should be an LocVal.
- Visit(Base, Pred, Tmp);
+ Visit(Base, Pred, Tmp); // Get Base's rvalue, which should be an LocVal.
- for (NodeSet::iterator I1=Tmp.begin(), E1=Tmp.end(); I1!=E1; ++I1) {
-
- // Evaluate the index.
+ for (NodeSet::iterator I1=Tmp.begin(), E1=Tmp.end(); I1!=E1; ++I1) {
NodeSet Tmp2;
- Visit(Idx, *I1, Tmp2);
+ Visit(Idx, *I1, Tmp2); // Evaluate the index.
for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) {
-
const GRState* St = GetState(*I2);
- RVal V = GetLValue(St, A);
+ RVal V = StateMgr.GetLValue(St, GetRVal(St, Base), GetRVal(St, Idx));
if (asLValue)
MakeNode(Dst, A, *I2, SetRVal(St, A, V));
NodeSet& Dst, bool asLValue) {
Expr* Base = M->getBase()->IgnoreParens();
-
NodeSet Tmp;
-
- // Get Base expr's rvalue.
Visit(Base, Pred, Tmp);
for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
const GRState* St = GetState(*I);
- RVal L = GetLValue(St, M);
+ // FIXME: Should we insert some assumption logic in here to determine
+ // if "Base" is a valid piece of memory? Before we put this assumption
+ // later when using FieldOffset lvals (which we no longer have).
+ RVal L = StateMgr.GetLValue(St, M->getMemberDecl(), GetRVal(St, Base));
+
if (asLValue)
MakeNode(Dst, M, *I, SetRVal(St, M, L));
else
return UnknownVal();
}
- // FIXME: Different offsets can map to the same memory cell.
- case lval::ArrayOffsetKind:
- case lval::FieldOffsetKind:
- // Fall-through.
-
case lval::MemRegionKind:
case lval::FuncValKind:
case lval::GotoLabelKind:
break;
}
- // FIXME: Different offsets can map to the same memory cell.
- case lval::ArrayOffsetKind:
- case lval::FieldOffsetKind:
- // Fall-through.
-
case lval::MemRegionKind:
case lval::FuncValKind:
case lval::GotoLabelKind:
const nonlval::LValAsInteger& V = cast<nonlval::LValAsInteger>(*this);
return V.getPersistentLVal().symbol_begin();
}
- else if (isa<lval::FieldOffset>(this)) {
- const lval::FieldOffset& V = cast<lval::FieldOffset>(*this);
- return V.getPersistentBase().symbol_begin();
- }
+
+ // FIXME: We need to iterate over the symbols of regions.
+
return NULL;
}
return lval::StringLiteralVal(S);
}
-//===----------------------------------------------------------------------===//
-// Utility methods for constructing RVals (both NonLVals and LVals).
-//===----------------------------------------------------------------------===//
-
-// Remove this method?
-RVal RVal::MakeVal(GRStateManager& SMgr, DeclRefExpr* E) {
-
- ValueDecl* D = cast<DeclRefExpr>(E)->getDecl();
-
- if (VarDecl* VD = dyn_cast<VarDecl>(D)) {
- return SMgr.getLVal(VD);
- }
- else if (EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
-
- // FIXME: Do we need to cache a copy of this enum, since it
- // already has persistent storage? We do this because we
- // are comparing states using pointer equality. Perhaps there is
- // a better way, since APInts are fairly lightweight.
- BasicValueFactory& BasicVals = SMgr.getBasicVals();
- return nonlval::ConcreteInt(BasicVals.getValue(ED->getInitVal()));
- }
- else if (FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
- return lval::FuncVal(FD);
- }
-
- assert (false &&
- "ValueDecl support for this ValueDecl not implemented.");
-
- return UnknownVal();
-}
-
//===----------------------------------------------------------------------===//
// Pretty-Printing.
//===----------------------------------------------------------------------===//
<< "\"";
break;
- case lval::FieldOffsetKind: {
- const lval::FieldOffset& C = *cast<lval::FieldOffset>(this);
- C.getBase().print(Out);
- Out << "." << C.getFieldDecl()->getName() << " (field LVal)";
- break;
- }
-
- case lval::ArrayOffsetKind: {
- const lval::ArrayOffset& C = *cast<lval::ArrayOffset>(this);
- C.getBase().print(Out);
- Out << "[";
- C.getOffset().print(Out);
- Out << "] (lval array entry)";
- break;
- }
-
default:
assert (false && "Pretty-printing not implemented for this LVal.");
break;