typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
APSIntSetTy;
- typedef llvm::FoldingSet<SymIntConstraint>
- SymIntCSetTy;
-
-
ASTContext& Ctx;
llvm::BumpPtrAllocator& BPAlloc;
APSIntSetTy APSIntSet;
- SymIntCSetTy SymIntCSet;
void* PersistentSVals;
void* PersistentSValPairs;
return getValue(b ? 1 : 0, Ctx.getTypeSize(Ctx.IntTy), false);
}
- const SymIntConstraint& getConstraint(SymbolRef sym, BinaryOperator::Opcode Op,
- const llvm::APSInt& V);
-
const CompoundValData* getCompoundValData(QualType T,
llvm::ImmutableList<SVal> Vals);
class GRState;
class GRStateManager;
class SVal;
-class SymbolRef;
class ConstraintManager {
public:
return X.isValid() ? getTF().EvalComplement(*this, cast<NonLoc>(X)) : X;
}
- SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, NonLoc R) {
- return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, R)
+ SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T) {
+ return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, R, T)
: R;
}
- SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, SVal R) {
+ SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, SVal R, QualType T) {
return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L,
- cast<NonLoc>(R)) : R;
+ cast<NonLoc>(R), T) : R;
}
void EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex,
BinaryOperator::Opcode Op, NonLoc L, NonLoc R,
- ExplodedNode<GRState>* Pred);
+ ExplodedNode<GRState>* Pred, QualType T);
void EvalBinOp(GRStateSet& OStates, const GRState* St, Expr* Ex,
- BinaryOperator::Opcode Op, NonLoc L, NonLoc R);
+ BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T);
- SVal EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R);
+ SVal EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, QualType T);
void EvalCall(NodeSet& Dst, CallExpr* CE, SVal L, NodeTy* Pred) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
ISetFactory(alloc),
GDMFactory(alloc),
BasicVals(Ctx, alloc),
- SymMgr(Ctx, alloc),
+ SymMgr(Ctx, BasicVals, alloc),
Alloc(alloc),
cfg(c),
codedecl(cd),
protected:
virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng,
BinaryOperator::Opcode Op,
- NonLoc L, NonLoc R) {
+ NonLoc L, NonLoc R, QualType T) {
return UnknownVal();
}
// for OStates
virtual void EvalBinOpNN(GRStateSet& OStates, GRExprEngine& Eng,
const GRState* St, Expr* Ex,
- BinaryOperator::Opcode Op, NonLoc L, NonLoc R);
+ BinaryOperator::Opcode Op, NonLoc L, NonLoc R,
+ QualType T);
virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
Loc L, Loc R) = 0;
class SymbolicRegion : public TypedRegion {
protected:
const SymbolRef sym;
- const SymbolManager& SymMgr;
public:
- SymbolicRegion(const SymbolRef s, const SymbolManager& mgr, MemRegion* sreg)
- : TypedRegion(sreg, SymbolicRegionKind), sym(s), SymMgr(mgr) {}
+ SymbolicRegion(const SymbolRef s, const MemRegion* sreg)
+ : TypedRegion(sreg, SymbolicRegionKind), sym(s) {}
SymbolRef getSymbol() const {
return sym;
getCompoundLiteralRegion(const CompoundLiteralExpr* CL);
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
- SymbolicRegion* getSymbolicRegion(const SymbolRef sym, const SymbolManager&);
+ SymbolicRegion* getSymbolicRegion(SymbolRef sym);
StringRegion* getStringRegion(const StringLiteral* Str);
bool isZeroConstant() const;
/// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
- /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolRef
- /// where 'isValid()' returns false.
+ /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolData*
SymbolRef getAsLocSymbol() const;
/// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
/// Otherwise return a SymbolRef where 'isValid()' returns false.
SymbolRef getAsSymbol() const;
+
+ /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
+ /// return that expression. Otherwise return NULL.
+ const SymExpr *getAsSymbolicExpression() const;
void print(std::ostream& OS) const;
void print(llvm::raw_ostream& OS) const;
void printStdErr() const;
-
+
+ // Iterators.
class symbol_iterator {
- SymbolRef SingleRef;
- const SymbolRef* sptr;
+ llvm::SmallVector<const SymExpr*, 5> itr;
+ void expand();
public:
+ symbol_iterator() {}
+ symbol_iterator(const SymExpr* SE);
- bool operator==(const symbol_iterator& X) {
- return SingleRef == X.SingleRef && sptr == X.sptr;
- }
-
- bool operator!=(const symbol_iterator& X) {
- return SingleRef != X.SingleRef || sptr != X.sptr;
- }
-
- symbol_iterator& operator++() {
- if (sptr)
- ++sptr;
- else
- SingleRef = SymbolRef();
+ symbol_iterator& operator++();
+ SymbolRef operator*();
- return *this;
- }
-
- SymbolRef operator*() const {
- if (sptr)
- return *sptr;
-
- return SingleRef;
- }
-
- symbol_iterator(SymbolRef x) : SingleRef(x), sptr(0) {}
- symbol_iterator() : sptr(0) {}
- symbol_iterator(const SymbolRef* x) : sptr(x) {}
+ bool operator==(const symbol_iterator& X) const;
+ bool operator!=(const symbol_iterator& X) const;
};
- symbol_iterator symbol_begin() const;
- symbol_iterator symbol_end() const;
+ symbol_iterator symbol_begin() const {
+ const SymExpr *SE = getAsSymbolicExpression();
+ if (SE)
+ return symbol_iterator(SE);
+ else
+ return symbol_iterator();
+ }
+
+ symbol_iterator symbol_end() const { return symbol_iterator(); }
// Implement isa<T> support.
static inline bool classof(const SVal*) { return true; }
void print(llvm::raw_ostream& Out) const;
// Utility methods to create NonLocs.
-
static NonLoc MakeVal(SymbolRef sym);
- static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
- BinaryOperator::Opcode op, const llvm::APSInt& v);
+ static NonLoc MakeVal(SymbolManager& SymMgr, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const llvm::APSInt& rhs,
+ QualType T);
- static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
- BinaryOperator::Opcode op, SymbolRef rhs);
+ static NonLoc MakeVal(SymbolManager& SymMgr, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const SymExpr *rhs,
+ QualType T);
static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
bool isUnsigned);
: SVal(const_cast<void*>(D), true, SubKind) {}
// Equality operators.
- NonLoc EQ(BasicValueFactory& BasicVals, const Loc& R) const;
- NonLoc NE(BasicValueFactory& BasicVals, const Loc& R) const;
+ NonLoc EQ(SymbolManager& SM, const Loc& R) const;
+ NonLoc NE(SymbolManager& SM, const Loc& R) const;
public:
void print(llvm::raw_ostream& Out) const;
namespace nonloc {
-enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind,
+enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
LocAsIntegerKind, CompoundValKind };
class SymbolVal : public NonLoc {
public:
- SymbolVal(SymbolRef SymID)
- : NonLoc(SymbolValKind,
- reinterpret_cast<void*>((uintptr_t) SymID.getNumber())) {}
+ SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
SymbolRef getSymbol() const {
- return (SymbolRef) reinterpret_cast<uintptr_t>(Data);
+ return (const SymbolData*) Data;
}
static inline bool classof(const SVal* V) {
}
};
-class SymIntConstraintVal : public NonLoc {
+class SymExprVal : public NonLoc {
public:
- SymIntConstraintVal(const SymIntConstraint& C)
- : NonLoc(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
+ SymExprVal(const SymExpr *SE)
+ : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
- const SymIntConstraint& getConstraint() const {
- return *reinterpret_cast<SymIntConstraint*>(Data);
+ const SymExpr *getSymbolicExpression() const {
+ return reinterpret_cast<SymExpr*>(Data);
}
static inline bool classof(const SVal* V) {
return V->getBaseKind() == NonLocKind &&
- V->getSubKind() == SymIntConstraintValKind;
+ V->getSubKind() == SymExprValKind;
}
static inline bool classof(const NonLoc* V) {
- return V->getSubKind() == SymIntConstraintValKind;
+ return V->getSubKind() == SymExprValKind;
}
};
class SymbolVal : public Loc {
public:
- SymbolVal(SymbolRef SymID)
- : Loc(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID.getNumber())){}
+ SymbolVal(SymbolRef sym) : Loc(SymbolValKind, sym) {}
- SymbolRef getSymbol() const {
- return (SymbolRef) reinterpret_cast<uintptr_t>(Data);
- }
+ SymbolRef getSymbol() const { return (SymbolRef) Data; }
static inline bool classof(const SVal* V) {
return V->getBaseKind() == LocKind &&
class raw_ostream;
}
+namespace clang {
+ class MemRegion;
+ class ASTContext;
+ class BasicValueFactory;
+}
+
namespace clang {
-class MemRegion;
-class SymbolManager;
-class ASTContext;
-
-class SymbolRef {
- unsigned Data;
+class SymExpr : public llvm::FoldingSetNode {
public:
- SymbolRef() : Data(~0U - 2) {}
- SymbolRef(unsigned x) : Data(x) {}
-
- bool isValid() const { return Data != (unsigned) (~0U - 2); }
- unsigned getNumber() const { assert (isValid()); return Data; }
-
- bool operator<(const SymbolRef& X) const { return Data < X.Data; }
- bool operator>(const SymbolRef& X) const { return Data > X.Data; }
- bool operator==(const SymbolRef& X) const { return Data == X.Data; }
- bool operator!=(const SymbolRef& X) const { return Data != X.Data; }
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
- ID.AddInteger(Data);
- }
-};
-} // end clang namespace
-
-namespace llvm {
- llvm::raw_ostream& operator<<(llvm::raw_ostream& Out, clang::SymbolRef Sym);
-}
-namespace std {
- std::ostream& operator<<(std::ostream& Out, clang::SymbolRef Sym);
-}
-
-namespace llvm {
-template <> struct DenseMapInfo<clang::SymbolRef> {
- static inline clang::SymbolRef getEmptyKey() {
- return clang::SymbolRef(~0U);
- }
- static inline clang::SymbolRef getTombstoneKey() {
- return clang::SymbolRef(~0U - 1);
- }
- static unsigned getHashValue(clang::SymbolRef X) {
- return X.getNumber();
- }
- static bool isEqual(clang::SymbolRef X, clang::SymbolRef Y) {
- return X == Y;
- }
- static bool isPod() { return true; }
-};
-}
-
-// SymbolData: Used to record meta data about symbols.
+ enum Kind { BEGIN_SYMBOLS, RegionRValue, ConjuredKind, END_SYMBOLS,
+ SymIntKind, SymSymKind };
+private:
+ Kind K;
-namespace clang {
+protected:
+ SymExpr(Kind k) : K(k) {}
-class SymbolData : public llvm::FoldingSetNode {
public:
- enum Kind { RegionRValue, ConjuredKind, SymIntKind, SymSymKind };
+ virtual ~SymExpr() {}
+
+ Kind getKind() const { return K; }
+
+ virtual QualType getType(ASTContext&) const = 0;
+ virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr*) { return true; }
+};
+
+typedef unsigned SymbolID;
+class SymbolData : public SymExpr {
private:
- Kind K;
- SymbolRef Sym;
+ const SymbolID Sym;
protected:
- SymbolData(Kind k, SymbolRef sym) : K(k), Sym(sym) {}
+ SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}
public:
virtual ~SymbolData() {}
- Kind getKind() const { return K; }
-
- SymbolRef getSymbol() const { return Sym; }
+ SymbolID getSymbolID() const { return Sym; }
- virtual QualType getType(ASTContext&) const = 0;
-
- virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
-
// Implement isa<T> support.
- static inline bool classof(const SymbolData*) { return true; }
+ static inline bool classof(const SymExpr* SE) {
+ Kind k = SE->getKind();
+ return k > BEGIN_SYMBOLS && k < END_SYMBOLS;
+ }
};
+
+typedef const SymbolData* SymbolRef;
class SymbolRegionRValue : public SymbolData {
const MemRegion *R;
public:
- SymbolRegionRValue(SymbolRef MySym, const MemRegion *r)
- : SymbolData(RegionRValue, MySym), R(r) {}
+ SymbolRegionRValue(SymbolID sym, const MemRegion *r)
+ : SymbolData(RegionRValue, sym), R(r) {}
const MemRegion* getRegion() const { return R; }
QualType getType(ASTContext&) const;
// Implement isa<T> support.
- static inline bool classof(const SymbolData* D) {
- return D->getKind() == RegionRValue;
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == RegionRValue;
}
};
const void* SymbolTag;
public:
- SymbolConjured(SymbolRef Sym, const Stmt* s, QualType t, unsigned count,
+ SymbolConjured(SymbolID sym, const Stmt* s, QualType t, unsigned count,
const void* symbolTag)
- : SymbolData(ConjuredKind, Sym), S(s), T(t), Count(count),
+ : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
SymbolTag(symbolTag) {}
const Stmt* getStmt() const { return S; }
}
// Implement isa<T> support.
- static inline bool classof(const SymbolData* D) {
- return D->getKind() == ConjuredKind;
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == ConjuredKind;
}
};
// SymIntExpr - Represents symbolic expression like 'x' + 3.
-class SymIntExpr : public SymbolData {
- SymbolRef LHS;
+class SymIntExpr : public SymExpr {
+ const SymExpr *LHS;
BinaryOperator::Opcode Op;
- const llvm::APSInt& Val;
+ const llvm::APSInt& RHS;
QualType T;
public:
- SymIntExpr(SymbolRef sym, SymbolRef lhs, BinaryOperator::Opcode op,
- const llvm::APSInt& V, QualType t)
- : SymbolData(SymIntKind, sym), LHS(lhs), Op(op), Val(V), T(t) {}
+ SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t)
+ : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
- QualType getType(ASTContext& C) const {
- return T;
- }
+ // FIXME: We probably need to make this out-of-line to avoid redundant
+ // generation of virtual functions.
+ QualType getType(ASTContext& C) const { return T; }
+
+ BinaryOperator::Opcode getOpcode() const { return Op; }
+
+ const SymExpr *getLHS() const { return LHS; }
+ const llvm::APSInt &getRHS() const { return RHS; }
- static void Profile(llvm::FoldingSetNodeID& ID, SymbolRef lhs,
- BinaryOperator::Opcode op, const llvm::APSInt& V,
+ static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const llvm::APSInt& rhs,
QualType t) {
- lhs.Profile(ID);
+ ID.AddInteger((unsigned) SymIntKind);
+ ID.AddPointer(lhs);
ID.AddInteger(op);
- ID.AddPointer(&V);
+ ID.AddPointer(&rhs);
ID.Add(t);
}
void Profile(llvm::FoldingSetNodeID& ID) {
- Profile(ID, LHS, Op, Val, T);
+ Profile(ID, LHS, Op, RHS, T);
}
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == SymIntKind;
+ }
};
// SymSymExpr - Represents symbolic expression like 'x' + 'y'.
-class SymSymExpr : public SymbolData {
- SymbolRef LHS;
+class SymSymExpr : public SymExpr {
+ const SymExpr *LHS;
BinaryOperator::Opcode Op;
- SymbolRef RHS;
+ const SymExpr *RHS;
QualType T;
public:
- SymSymExpr(SymbolRef sym, SymbolRef lhs, BinaryOperator::Opcode op,
- SymbolRef rhs, QualType t)
- : SymbolData(SymSymKind, sym), LHS(lhs), Op(op), RHS(rhs), T(t) {}
+ SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
+ QualType t)
+ : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
- QualType getType(ASTContext& C) const {
- return T;
- }
+ const SymExpr *getLHS() const { return LHS; }
+ const SymExpr *getRHS() const { return RHS; }
+
+ // FIXME: We probably need to make this out-of-line to avoid redundant
+ // generation of virtual functions.
+ QualType getType(ASTContext& C) const { return T; }
- static void Profile(llvm::FoldingSetNodeID& ID, SymbolRef lhs,
- BinaryOperator::Opcode op, SymbolRef rhs, QualType t) {
- lhs.Profile(ID);
+ static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
+ ID.AddInteger((unsigned) SymSymKind);
+ ID.AddPointer(lhs);
ID.AddInteger(op);
- rhs.Profile(ID);
+ ID.AddPointer(rhs);
ID.Add(t);
}
void Profile(llvm::FoldingSetNodeID& ID) {
Profile(ID, LHS, Op, RHS, T);
}
-};
-
-// Constraints on symbols. Usually wrapped by SValues.
-
-class SymIntConstraint : public llvm::FoldingSetNode {
- SymbolRef Symbol;
- BinaryOperator::Opcode Op;
- const llvm::APSInt& Val;
-public:
- SymIntConstraint(SymbolRef sym, BinaryOperator::Opcode op,
- const llvm::APSInt& V)
- : Symbol(sym),
- Op(op), Val(V) {}
-
- BinaryOperator::Opcode getOpcode() const { return Op; }
- const SymbolRef& getSymbol() const { return Symbol; }
- const llvm::APSInt& getInt() const { return Val; }
-
- static inline void Profile(llvm::FoldingSetNodeID& ID,
- SymbolRef Symbol,
- BinaryOperator::Opcode Op,
- const llvm::APSInt& Val) {
- Symbol.Profile(ID);
- ID.AddInteger(Op);
- ID.AddPointer(&Val);
- }
- void Profile(llvm::FoldingSetNodeID& ID) {
- Profile(ID, Symbol, Op, Val);
- }
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == SymSymKind;
+ }
};
-
class SymbolManager {
- typedef llvm::FoldingSet<SymbolData> DataSetTy;
- typedef llvm::DenseMap<SymbolRef, SymbolData*> DataMapTy;
-
- DataSetTy DataSet;
- DataMapTy DataMap;
-
+ typedef llvm::FoldingSet<SymExpr> DataSetTy;
+ DataSetTy DataSet;
unsigned SymbolCounter;
llvm::BumpPtrAllocator& BPAlloc;
+ BasicValueFactory &BV;
ASTContext& Ctx;
public:
- SymbolManager(ASTContext& ctx, llvm::BumpPtrAllocator& bpalloc)
- : SymbolCounter(0), BPAlloc(bpalloc), Ctx(ctx) {}
+ SymbolManager(ASTContext& ctx, BasicValueFactory &bv,
+ llvm::BumpPtrAllocator& bpalloc)
+ : SymbolCounter(0), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
~SymbolManager();
static bool canSymbolicate(QualType T);
/// Make a unique symbol for MemRegion R according to its kind.
- SymbolRef getRegionRValueSymbol(const MemRegion* R);
- SymbolRef getConjuredSymbol(const Stmt* E, QualType T, unsigned VisitCount,
- const void* SymbolTag = 0);
+ const SymbolRegionRValue* getRegionRValueSymbol(const MemRegion* R);
+ const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
+ unsigned VisitCount,
+ const void* SymbolTag = 0);
- SymbolRef getConjuredSymbol(const Expr* E, unsigned VisitCount,
- const void* SymbolTag = 0) {
+ const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount,
+ const void* SymbolTag = 0) {
return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag);
}
- SymbolRef getSymIntExpr(SymbolRef lhs, BinaryOperator::Opcode op,
- const llvm::APSInt& v, QualType t);
-
- SymbolRef getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op,
- SymbolRef rhs, QualType t);
+ const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t);
- const SymbolData& getSymbolData(SymbolRef ID) const;
+ const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t) {
+ return getSymIntExpr(&lhs, op, rhs, t);
+ }
+
+ const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType t);
- QualType getType(SymbolRef ID) const {
- return getSymbolData(ID).getType(Ctx);
+ QualType getType(const SymExpr *SE) const {
+ return SE->getType(Ctx);
}
- ASTContext& getContext() { return Ctx; }
+ ASTContext &getContext() { return Ctx; }
+ BasicValueFactory &getBasicVals() { return BV; }
};
class SymbolReaper {
} // end clang namespace
+namespace llvm {
+ llvm::raw_ostream& operator<<(llvm::raw_ostream& Out,
+ const clang::SymExpr *SE);
+}
+namespace std {
+ std::ostream& operator<<(std::ostream& Out,
+ const clang::SymExpr *SE);
+}
+
#endif
switch(BaseL.getSubKind()) {
case loc::SymbolValKind:
- BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol(),
- StateMgr.getSymbolManager());
+ BaseR =
+ MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
break;
case loc::GotoLabelKind:
// Create a region to represent this symbol.
// FIXME: In the future we may just use symbolic regions instead of
// SymbolVals to reason about symbolic memory chunks.
- const MemRegion* SymR = MRMgr.getSymbolicRegion(Sym,
- StateMgr.getSymbolManager());
+ const MemRegion* SymR = MRMgr.getSymbolicRegion(Sym);
// Layered a typed region on top of this.
QualType T = StateMgr.getSymbolManager().getType(Sym);
BaseR = MRMgr.getTypedViewRegion(T, SymR);
return getValue(V);
}
-const SymIntConstraint&
-BasicValueFactory::getConstraint(SymbolRef sym, BinaryOperator::Opcode Op,
- const llvm::APSInt& V) {
-
- llvm::FoldingSetNodeID ID;
- SymIntConstraint::Profile(ID, sym, Op, V);
- void* InsertPos;
-
- SymIntConstraint* C = SymIntCSet.FindNodeOrInsertPos(ID, InsertPos);
-
- if (!C) {
- C = (SymIntConstraint*) BPAlloc.Allocate<SymIntConstraint>();
- new (C) SymIntConstraint(sym, Op, V);
- SymIntCSet.InsertNode(C, InsertPos);
- }
-
- return *C;
-}
-
const CompoundValData*
BasicValueFactory::getCompoundValData(QualType T,
llvm::ImmutableList<SVal> Vals) {
bool HandleBinding(StoreManager& SMgr, Store store,
const MemRegion* R, SVal V) {
- SymbolRef ScanSym;
+ SymbolRef ScanSym = 0;
if (loc::SymbolVal* SV = dyn_cast<loc::SymbolVal>(&V))
ScanSym = SV->getSymbol();
bool HandleBinding(StoreManager& SMgr, Store store,
const MemRegion* R, SVal V) {
- SymbolRef ScanSym;
+ SymbolRef ScanSym = 0;
if (loc::SymbolVal* SV = dyn_cast<loc::SymbolVal>(&V))
ScanSym = SV->getSymbol();
else
return true;
- assert (ScanSym.isValid());
+ assert (ScanSym);
if (!BR.isNotable(ScanSym))
return true;
static void PrintPool(std::ostream &Out, SymbolRef Sym, const GRState *state) {
Out << ' ';
- if (Sym.isValid())
- Out << Sym;
+ if (Sym)
+ Out << Sym->getSymbolID();
else
Out << "<pool>";
Out << ":{";
SVal V = state.GetSValAsScalarOrLoc(*I);
SymbolRef Sym = V.getAsLocSymbol();
- if (Sym.isValid())
+ if (Sym)
if (RefBindings::data_type* T = state.get<RefBindings>(Sym)) {
state = Update(state, Sym, *T, GetArgE(Summ, idx), hasErr);
if (hasErr) {
SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol();
// Remove any existing reference-count binding.
- if (Sym.isValid()) state = state.remove<RefBindings>(Sym);
+ if (Sym) state = state.remove<RefBindings>(Sym);
if (R->isBoundable(Ctx)) {
// Set the value of the variable to be a conjured symbol.
// Evaluate the effect on the message receiver.
if (!ErrorExpr && Receiver) {
SymbolRef Sym = state.GetSValAsScalarOrLoc(Receiver).getAsLocSymbol();
- if (Sym.isValid()) {
+ if (Sym) {
if (const RefVal* T = state.get<RefBindings>(Sym)) {
state = Update(state, Sym, *T, GetReceiverE(Summ), hasErr);
if (hasErr) {
SVal V = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver);
SymbolRef Sym = V.getAsLocSymbol();
- if (Sym.isValid()) {
+ if (Sym) {
if (const RefVal* T = St->get<RefBindings>(Sym)) {
QualType Ty = T->getType();
GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
SymbolRef Sym = state.GetSValAsScalarOrLoc(RetE).getAsLocSymbol();
- if (!Sym.isValid())
+ if (!Sym)
return;
// Get the reference count binding (if any).
bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
SVal val) {
- SymbolRef SymV = val.getAsSymbol();
-
- if (!SymV.isValid() || SymV != Sym)
+
+ SymbolRef SymV = val.getAsSymbol();
+ if (!SymV || SymV != Sym)
return true;
if (Binding) {
do {
nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));
- SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal);
+ SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal,
+ getContext().IntTy);
// Now "assume" that the case matches.
bool isFeasible = false;
const GRState* state = Pred->getState();
SVal V = GetSVal(state, Ex);
- if (isa<nonloc::SymIntConstraintVal>(V)) {
+ if (isa<nonloc::SymExprVal>(V)) {
// First assume that the condition is true.
bool isFeasible = false;
const GRState *stateTrue = Assume(state, V, true, isFeasible);
}
StoreManager& StoreMgr = getStoreManager();
- const MemRegion* R =
- StoreMgr.getRegionManager().getSymbolicRegion(Sym, getSymbolManager());
+ const MemRegion* R = StoreMgr.getRegionManager().getSymbolicRegion(Sym);
// Delegate to store manager to get the result of casting a region
// to a different type.
if (isa<Loc>(V)) {
loc::ConcreteInt X(getBasicVals().getZeroWithPtrWidth());
- SVal Result = EvalBinOp(BinaryOperator::EQ, cast<Loc>(V), X);
+ SVal Result = EvalBinOp(BinaryOperator::EQ, cast<Loc>(V), X,
+ U->getType());
state = BindExpr(state, U, Result);
}
else {
SVal Result = EvalBinOp(BinaryOperator::EQ, cast<NonLoc>(V), X);
state = SetSVal(state, U, Result);
#else
- EvalBinOp(Dst, U, BinaryOperator::EQ, cast<NonLoc>(V), X, *I);
+ EvalBinOp(Dst, U, BinaryOperator::EQ, cast<NonLoc>(V), X, *I,
+ U->getType());
continue;
#endif
}
BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
: BinaryOperator::Sub;
- SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U));
+ SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U), U->getType());
// Conjure a new symbol if necessary to recover precision.
if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result))
return;
}
-
if (B->isAssignmentOp())
VisitLValue(LHS, Pred, Tmp1);
else
// Process non-assignements except commas or short-circuited
// logical expressions (LAnd and LOr).
- SVal Result = EvalBinOp(Op, LeftV, RightV);
+ SVal Result = EvalBinOp(Op, LeftV, RightV, B->getType());
if (Result.isUnknown()) {
if (OldSt != state) {
}
// Compute the result of the operation.
- SVal Result = EvalCast(EvalBinOp(Op, V, RightV), B->getType());
+ SVal Result = EvalCast(EvalBinOp(Op, V, RightV, CTy), B->getType());
if (Result.isUndef()) {
// The operands were not undefined, but the result is undefined.
void GRExprEngine::EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex,
BinaryOperator::Opcode Op,
NonLoc L, NonLoc R,
- ExplodedNode<GRState>* Pred) {
+ ExplodedNode<GRState>* Pred, QualType T) {
GRStateSet OStates;
- EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R);
+ EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R, T);
for (GRStateSet::iterator I=OStates.begin(), E=OStates.end(); I!=E; ++I)
MakeNode(Dst, Ex, Pred, *I);
void GRExprEngine::EvalBinOp(GRStateSet& OStates, const GRState* state,
Expr* Ex, BinaryOperator::Opcode Op,
- NonLoc L, NonLoc R) {
+ NonLoc L, NonLoc R, QualType T) {
GRStateSet::AutoPopulate AP(OStates, state);
- if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R);
+ if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R, T);
}
-SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R) {
+SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R,
+ QualType T) {
if (L.isUndef() || R.isUndef())
return UndefinedVal();
}
else
return getTF().DetermEvalBinOpNN(*this, Op, cast<NonLoc>(L),
- cast<NonLoc>(R));
+ cast<NonLoc>(R), T);
}
//===----------------------------------------------------------------------===//
SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
BinaryOperator::Opcode Op,
- NonLoc L, NonLoc R) {
+ NonLoc L, NonLoc R,
+ QualType T) {
BasicValueFactory& BasicVals = Eng.getBasicVals();
unsigned subkind = L.getSubKind();
}
}
- case nonloc::SymIntConstraintValKind: {
-
+ case nonloc::SymExprValKind: {
// Logical not?
if (!(Op == BinaryOperator::EQ && R.isZeroConstant()))
return UnknownVal();
-
- const SymIntConstraint& C =
- cast<nonloc::SymIntConstraintVal>(L).getConstraint();
-
- BinaryOperator::Opcode Opc = C.getOpcode();
-
- if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE)
- return UnknownVal();
- // For comparison operators, translate the constraint by
- // changing the opcode.
+ const SymExpr &SE=*cast<nonloc::SymExprVal>(L).getSymbolicExpression();
- int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT;
+ // Only handle ($sym op constant) for now.
+ if (const SymIntExpr *E = dyn_cast<SymIntExpr>(&SE)) {
+ BinaryOperator::Opcode Opc = E->getOpcode();
- assert (idx >= 0 &&
- (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char));
+ if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE)
+ return UnknownVal();
+
+ // For comparison operators, translate the constraint by
+ // changing the opcode.
+ int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT;
- Opc = (BinaryOperator::Opcode) LNotOpMap[idx];
+ assert (idx >= 0 &&
+ (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char));
- const SymIntConstraint& CNew =
- BasicVals.getConstraint(C.getSymbol(), Opc, C.getInt());
+ Opc = (BinaryOperator::Opcode) LNotOpMap[idx];
+ assert(E->getType(Eng.getContext()) == T);
+ E = Eng.getSymbolManager().getSymIntExpr(E->getLHS(), Opc,
+ E->getRHS(), T);
+ return nonloc::SymExprVal(E);
+ }
- return nonloc::SymIntConstraintVal(CNew);
+ return UnknownVal();
}
case nonloc::ConcreteIntKind:
case nonloc::SymbolValKind:
if (isa<nonloc::ConcreteInt>(R)) {
if (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE) {
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<nonloc::SymbolVal>(L).getSymbol(),
- Op, cast<nonloc::ConcreteInt>(R).getValue());
- return nonloc::SymIntConstraintVal(C);
+ const SymIntExpr *SE =
+ Eng.getSymbolManager().getSymIntExpr(
+ cast<nonloc::SymbolVal>(L).getSymbol(), Op,
+ cast<nonloc::ConcreteInt>(R).getValue(),T);
+
+
+ return nonloc::SymExprVal(SE);
} else {
return NonLoc::MakeVal(Eng.getSymbolManager(),
cast<nonloc::SymbolVal>(L).getSymbol(),
- Op, cast<nonloc::ConcreteInt>(R).getValue());
+ Op, cast<nonloc::ConcreteInt>(R).getValue(),
+ T);
}
}
else
}
else if (isa<loc::SymbolVal>(R)) {
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
- BinaryOperator::EQ,
- cast<loc::ConcreteInt>(L).getValue());
+ const SymIntExpr *SE =
+ Eng.getSymbolManager().getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(),
+ BinaryOperator::EQ,
+ cast<loc::ConcreteInt>(L).getValue(),
+ Eng.getContext().IntTy);
- return nonloc::SymIntConstraintVal(C);
+ return nonloc::SymExprVal(SE);
}
break;
case loc::SymbolValKind: {
- if (isa<loc::ConcreteInt>(R)) {
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(L).getSymbol(),
- BinaryOperator::EQ,
- cast<loc::ConcreteInt>(R).getValue());
+ if (isa<loc::ConcreteInt>(R)) {
+ const SymIntExpr *SE =
+ Eng.getSymbolManager().getSymIntExpr(
+ cast<loc::SymbolVal>(L).getSymbol(),
+ BinaryOperator::EQ,
+ cast<loc::ConcreteInt>(R).getValue(),
+ Eng.getContext().IntTy);
- return nonloc::SymIntConstraintVal(C);
+ return nonloc::SymExprVal(SE);
}
// FIXME: Implement == for lval Symbols. This is mainly useful
return NonLoc::MakeIntTruthVal(BasicVals, b);
}
- else if (isa<loc::SymbolVal>(R)) {
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
- BinaryOperator::NE,
- cast<loc::ConcreteInt>(L).getValue());
-
- return nonloc::SymIntConstraintVal(C);
+ else if (isa<loc::SymbolVal>(R)) {
+ const SymIntExpr * SE =
+ Eng.getSymbolManager().getSymIntExpr(
+ cast<loc::SymbolVal>(R).getSymbol(),
+ BinaryOperator::NE,
+ cast<loc::ConcreteInt>(L).getValue(),
+ Eng.getContext().IntTy);
+ return nonloc::SymExprVal(SE);
}
break;
case loc::SymbolValKind: {
- if (isa<loc::ConcreteInt>(R)) {
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(L).getSymbol(),
- BinaryOperator::NE,
- cast<loc::ConcreteInt>(R).getValue());
-
- return nonloc::SymIntConstraintVal(C);
+ if (isa<loc::ConcreteInt>(R)) {
+ const SymIntExpr *SE =
+ Eng.getSymbolManager().getSymIntExpr(
+ cast<loc::SymbolVal>(L).getSymbol(),
+ BinaryOperator::NE,
+ cast<loc::ConcreteInt>(R).getValue(),
+ Eng.getContext().IntTy);
+ return nonloc::SymExprVal(SE);
}
// FIXME: Implement != for lval Symbols. This is mainly useful
virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng,
BinaryOperator::Opcode Op,
- NonLoc L, NonLoc R);
+ NonLoc L, NonLoc R, QualType T);
public:
GRSimpleVals() {}
GRExprEngine& Eng,
const GRState *St, Expr* Ex,
BinaryOperator::Opcode Op,
- NonLoc L, NonLoc R) {
+ NonLoc L, NonLoc R, QualType T) {
- OStates.Add(Eng.getStateManager().BindExpr(St, Ex, DetermEvalBinOpNN(Eng, Op, L, R)));
+ OStates.Add(Eng.getStateManager().BindExpr(St, Ex,
+ DetermEvalBinOpNN(Eng, Op, L, R, T)));
}
//===----------------------------------------------------------------------===//
QualType SymbolicRegion::getRValueType(ASTContext& C) const {
- const SymbolData& data = SymMgr.getSymbolData(sym);
-
// Get the type of the symbol.
- QualType T = data.getType(C);
+ QualType T = sym->getType(C);
if (const PointerType* PTy = T->getAsPointerType())
return PTy->getPointeeType();
}
QualType SymbolicRegion::getLValueType(ASTContext& C) const {
- const SymbolData& data = SymMgr.getSymbolData(sym);
- return data.getType(C);
+ return sym->getType(C);
}
QualType ElementRegion::getRValueType(ASTContext& C) const {
}
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
-SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym,
- const SymbolManager& mgr) {
-
+SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) {
llvm::FoldingSetNodeID ID;
SymbolicRegion::ProfileRegion(ID, sym);
-
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
if (!R) {
R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
// SymbolicRegion's storage class is usually unknown.
- new (R) SymbolicRegion(sym, mgr, getUnknownRegion());
+ new (R) SymbolicRegion(sym, getUnknownRegion());
Regions.InsertNode(R, InsertPos);
}
break;
case loc::SymbolValKind:
- BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol(),
- StateMgr.getSymbolManager());
+ BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
break;
case loc::GotoLabelKind:
const TypedRegion* BaseRegion = 0;
- if (isa<loc::SymbolVal>(Base))
- BaseRegion = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(Base).getSymbol(),
- StateMgr.getSymbolManager());
- else
- BaseRegion = cast<TypedRegion>(cast<loc::MemRegionVal>(Base).getRegion());
+ BaseRegion = isa<loc::SymbolVal>(Base)
+ ? MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(Base).getSymbol())
+ : cast<TypedRegion>(cast<loc::MemRegionVal>(Base).getRegion());
// Pointer of any type can be cast and used as array base.
const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion);
if (isa<loc::MemRegionVal>(L))
R = cast<loc::MemRegionVal>(L).getRegion();
else if (isa<loc::SymbolVal>(L))
- R = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(L).getSymbol(),
- StateMgr.getSymbolManager());
+ R = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(L).getSymbol());
if (R) {
RegionBindingsTy B = GetRegionBindings(store);
using llvm::APSInt;
//===----------------------------------------------------------------------===//
-// Symbol Iteration.
+// Symbol iteration within an SVal.
//===----------------------------------------------------------------------===//
-SVal::symbol_iterator SVal::symbol_begin() const {
- // FIXME: This is a rat's nest. Cleanup.
-
- if (isa<loc::SymbolVal>(this))
- return symbol_iterator(SymbolRef((uintptr_t)Data));
- else if (isa<nonloc::SymbolVal>(this))
- return symbol_iterator(SymbolRef((uintptr_t)Data));
- else if (isa<nonloc::SymIntConstraintVal>(this)) {
- const SymIntConstraint& C =
- cast<nonloc::SymIntConstraintVal>(this)->getConstraint();
- return symbol_iterator(C.getSymbol());
- }
- else if (isa<nonloc::LocAsInteger>(this)) {
- const nonloc::LocAsInteger& V = cast<nonloc::LocAsInteger>(*this);
- return V.getPersistentLoc().symbol_begin();
- }
- else if (isa<loc::MemRegionVal>(this)) {
- const MemRegion* R = cast<loc::MemRegionVal>(this)->getRegion();
- if (const SymbolicRegion* S = dyn_cast<SymbolicRegion>(R))
- return symbol_iterator(S->getSymbol());
- }
-
- return symbol_iterator();
-}
-SVal::symbol_iterator SVal::symbol_end() const {
- return symbol_iterator();
-}
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
/// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
/// wraps a symbol, return that SymbolRef. Otherwise return a SymbolRef
}
}
- return SymbolRef();
+ return 0;
}
/// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
return X->getSymbol();
+ if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
+ if (SymbolRef Y = dyn_cast<SymbolData>(X->getSymbolicExpression()))
+ return Y;
+
return getAsLocSymbol();
}
+/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
+/// return that expression. Otherwise return NULL.
+const SymExpr *SVal::getAsSymbolicExpression() const {
+ if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
+ return X->getSymbolicExpression();
+
+ return getAsSymbol();
+}
+
+bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
+ return itr == X.itr;
+}
+
+bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const {
+ return itr != X.itr;
+}
+
+SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) {
+ itr.push_back(SE);
+ while (!isa<SymbolData>(itr.back())) expand();
+}
+
+SVal::symbol_iterator& SVal::symbol_iterator::operator++() {
+ assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
+ assert(isa<SymbolData>(itr.back()));
+ itr.pop_back();
+ if (!itr.empty())
+ while (!isa<SymbolData>(itr.back())) expand();
+ return *this;
+}
+
+SymbolRef SVal::symbol_iterator::operator*() {
+ assert(!itr.empty() && "attempting to dereference an 'end' iterator");
+ return cast<SymbolData>(itr.back());
+}
+
+void SVal::symbol_iterator::expand() {
+ const SymExpr *SE = itr.back();
+ itr.pop_back();
+
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
+ itr.push_back(SIE->getLHS());
+ return;
+ }
+ else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
+ itr.push_back(SSE->getLHS());
+ itr.push_back(SSE->getRHS());
+ return;
+ }
+
+ assert(false && "unhandled expansion case");
+}
+
//===----------------------------------------------------------------------===//
// Other Iterators.
//===----------------------------------------------------------------------===//
return UndefinedVal();
}
-NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const {
+NonLoc Loc::EQ(SymbolManager& SymMgr, const Loc& R) const {
switch (getSubKind()) {
default:
bool b = cast<loc::ConcreteInt>(this)->getValue() ==
cast<loc::ConcreteInt>(R).getValue();
- return NonLoc::MakeIntTruthVal(BasicVals, b);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
}
else if (isa<loc::SymbolVal>(R)) {
-
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
+ const SymIntExpr *SE =
+ SymMgr.getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(),
BinaryOperator::EQ,
- cast<loc::ConcreteInt>(this)->getValue());
+ cast<loc::ConcreteInt>(this)->getValue(),
+ SymMgr.getContext().IntTy);
- return nonloc::SymIntConstraintVal(C);
+ return nonloc::SymExprVal(SE);
}
break;
case loc::SymbolValKind: {
if (isa<loc::ConcreteInt>(R)) {
-
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(),
+ const SymIntExpr *SE =
+ SymMgr.getSymIntExpr(cast<loc::SymbolVal>(this)->getSymbol(),
BinaryOperator::EQ,
- cast<loc::ConcreteInt>(R).getValue());
+ cast<loc::ConcreteInt>(R).getValue(),
+ SymMgr.getContext().IntTy);
- return nonloc::SymIntConstraintVal(C);
+ return nonloc::SymExprVal(SE);
}
-
- assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement unification.");
-
+
+ assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement unification.");
break;
}
case loc::MemRegionKind:
if (isa<loc::MemRegionVal>(R)) {
bool b = cast<loc::MemRegionVal>(*this) == cast<loc::MemRegionVal>(R);
- return NonLoc::MakeIntTruthVal(BasicVals, b);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
}
break;
}
- return NonLoc::MakeIntTruthVal(BasicVals, false);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), false);
}
-NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const {
+NonLoc Loc::NE(SymbolManager& SymMgr, const Loc& R) const {
switch (getSubKind()) {
default:
assert(false && "NE not implemented for this Loc.");
bool b = cast<loc::ConcreteInt>(this)->getValue() !=
cast<loc::ConcreteInt>(R).getValue();
- return NonLoc::MakeIntTruthVal(BasicVals, b);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
}
else if (isa<loc::SymbolVal>(R)) {
-
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
- BinaryOperator::NE,
- cast<loc::ConcreteInt>(this)->getValue());
-
- return nonloc::SymIntConstraintVal(C);
+ const SymIntExpr *SE =
+ SymMgr.getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(),
+ BinaryOperator::NE,
+ cast<loc::ConcreteInt>(this)->getValue(),
+ SymMgr.getContext().IntTy);
+ return nonloc::SymExprVal(SE);
}
-
break;
case loc::SymbolValKind: {
if (isa<loc::ConcreteInt>(R)) {
+ const SymIntExpr *SE =
+ SymMgr.getSymIntExpr(cast<loc::SymbolVal>(this)->getSymbol(),
+ BinaryOperator::NE,
+ cast<loc::ConcreteInt>(R).getValue(),
+ SymMgr.getContext().IntTy);
- const SymIntConstraint& C =
- BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(),
- BinaryOperator::NE,
- cast<loc::ConcreteInt>(R).getValue());
-
- return nonloc::SymIntConstraintVal(C);
+ return nonloc::SymExprVal(SE);
}
assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement sym !=.");
-
break;
}
case loc::MemRegionKind:
if (isa<loc::MemRegionVal>(R)) {
bool b = cast<loc::MemRegionVal>(*this)==cast<loc::MemRegionVal>(R);
- return NonLoc::MakeIntTruthVal(BasicVals, b);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b);
}
break;
}
- return NonLoc::MakeIntTruthVal(BasicVals, true);
+ return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), true);
}
//===----------------------------------------------------------------------===//
return nonloc::SymbolVal(sym);
}
-NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
- BinaryOperator::Opcode op, const APSInt& v) {
+NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const APSInt& v, QualType T) {
// The Environment ensures we always get a persistent APSInt in
// BasicValueFactory, so we don't need to get the APSInt from
// BasicValueFactory again.
-
- SymbolRef sym = SymMgr.getSymIntExpr(lhs, op, v, SymMgr.getType(lhs));
- return nonloc::SymbolVal(sym);
+ assert(!Loc::IsLocType(T));
+ return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T));
}
-NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
- BinaryOperator::Opcode op, SymbolRef rhs) {
+NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const SymExpr *rhs,
+QualType T) {
assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
- SymbolRef sym = SymMgr.getSymSymExpr(lhs, op, rhs, SymMgr.getType(lhs));
- return nonloc::SymbolVal(sym);
+ assert(!Loc::IsLocType(T));
+ return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T));
}
NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
}
}
-static void printOpcode(llvm::raw_ostream& Out, BinaryOperator::Opcode Op) {
-
- switch (Op) {
- case BinaryOperator::Mul: Out << '*' ; break;
- case BinaryOperator::Div: Out << '/' ; break;
- case BinaryOperator::Rem: Out << '%' ; break;
- case BinaryOperator::Add: Out << '+' ; break;
- case BinaryOperator::Sub: Out << '-' ; break;
- case BinaryOperator::Shl: Out << "<<" ; break;
- case BinaryOperator::Shr: Out << ">>" ; break;
- case BinaryOperator::LT: Out << "<" ; break;
- case BinaryOperator::GT: Out << '>' ; break;
- case BinaryOperator::LE: Out << "<=" ; break;
- case BinaryOperator::GE: Out << ">=" ; break;
- case BinaryOperator::EQ: Out << "==" ; break;
- case BinaryOperator::NE: Out << "!=" ; break;
- case BinaryOperator::And: Out << '&' ; break;
- case BinaryOperator::Xor: Out << '^' ; break;
- case BinaryOperator::Or: Out << '|' ; break;
-
- default: assert(false && "Not yet implemented.");
- }
-}
-
void NonLoc::print(llvm::raw_ostream& Out) const {
switch (getSubKind()) {
Out << '$' << cast<nonloc::SymbolVal>(this)->getSymbol();
break;
- case nonloc::SymIntConstraintValKind: {
- const nonloc::SymIntConstraintVal& C =
- *cast<nonloc::SymIntConstraintVal>(this);
-
- Out << '$' << C.getConstraint().getSymbol() << ' ';
- printOpcode(Out, C.getConstraint().getOpcode());
- Out << ' ' << C.getConstraint().getInt().getZExtValue();
-
- if (C.getConstraint().getInt().isUnsigned())
- Out << 'U';
-
+ case nonloc::SymExprValKind: {
+ const nonloc::SymExprVal& C = *cast<nonloc::SymExprVal>(this);
+ const SymExpr *SE = C.getSymbolicExpression();
+ Out << SE;
break;
}
SimpleConstraintManager::~SimpleConstraintManager() {}
bool SimpleConstraintManager::canReasonAbout(SVal X) const {
- if (nonloc::SymbolVal* SymVal = dyn_cast<nonloc::SymbolVal>(&X)) {
- const SymbolData& data
- = getSymbolManager().getSymbolData(SymVal->getSymbol());
- return !(data.getKind() == SymbolData::SymIntKind ||
- data.getKind() == SymbolData::SymSymKind );
+ if (nonloc::SymExprVal *SymVal = dyn_cast<nonloc::SymExprVal>(&X)) {
+ const SymExpr *SE = SymVal->getSymbolicExpression();
+
+ if (isa<SymbolData>(SE))
+ return true;
+
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
+ switch (SIE->getOpcode()) {
+ // We don't reason yet about bitwise-constraints on symbolic values.
+ case BinaryOperator::And:
+ case BinaryOperator::Or:
+ case BinaryOperator::Xor:
+ return false;
+ // We don't reason yet about arithmetic constraints on symbolic values.
+ case BinaryOperator::Mul:
+ case BinaryOperator::Div:
+ case BinaryOperator::Rem:
+ case BinaryOperator::Add:
+ case BinaryOperator::Sub:
+ case BinaryOperator::Shl:
+ case BinaryOperator::Shr:
+ return false;
+ // All other cases.
+ default:
+ return true;
+ }
+ }
+
+ return false;
}
return true;
return AssumeSymEQ(St, sym, BasicVals.getValue(0, T), isFeasible);
}
- case nonloc::SymIntConstraintValKind:
- return
- AssumeSymInt(St, Assumption,
- cast<nonloc::SymIntConstraintVal>(Cond).getConstraint(),
- isFeasible);
+ case nonloc::SymExprValKind: {
+ nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
+ if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression()))
+ return AssumeSymInt(St, Assumption, SE, isFeasible);
+
+ isFeasible = true;
+ return St;
+ }
case nonloc::ConcreteIntKind: {
bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
const GRState*
SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
- const SymIntConstraint& C,
- bool& isFeasible) {
+ const SymIntExpr *SE, bool& isFeasible) {
+
- switch (C.getOpcode()) {
+ // Here we assume that LHS is a symbol. This is consistent with the
+ // rest of the constraint manager logic.
+ SymbolRef Sym = cast<SymbolData>(SE->getLHS());
+ const llvm::APSInt &Int = SE->getRHS();
+
+ switch (SE->getOpcode()) {
default:
// No logic yet for other operators.
isFeasible = true;
return St;
case BinaryOperator::EQ:
- if (Assumption)
- return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
- else
- return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
+ return Assumption ? AssumeSymEQ(St, Sym, Int, isFeasible)
+ : AssumeSymNE(St, Sym, Int, isFeasible);
case BinaryOperator::NE:
- if (Assumption)
- return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
- else
- return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
+ return Assumption ? AssumeSymNE(St, Sym, Int, isFeasible)
+ : AssumeSymEQ(St, Sym, Int, isFeasible);
case BinaryOperator::GT:
- if (Assumption)
- return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
- else
- return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
+ return Assumption ? AssumeSymGT(St, Sym, Int, isFeasible)
+ : AssumeSymLE(St, Sym, Int, isFeasible);
case BinaryOperator::GE:
- if (Assumption)
- return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
- else
- return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
+ return Assumption ? AssumeSymGE(St, Sym, Int, isFeasible)
+ : AssumeSymLT(St, Sym, Int, isFeasible);
case BinaryOperator::LT:
- if (Assumption)
- return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
- else
- return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
+ return Assumption ? AssumeSymLT(St, Sym, Int, isFeasible)
+ : AssumeSymGE(St, Sym, Int, isFeasible);
case BinaryOperator::LE:
- if (Assumption)
- return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
- else
- return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
+ return Assumption ? AssumeSymLE(St, Sym, Int, isFeasible)
+ : AssumeSymGT(St, Sym, Int, isFeasible);
} // end switch
}
bool& isFeasible);
const GRState* AssumeSymInt(const GRState* St, bool Assumption,
- const SymIntConstraint& C, bool& isFeasible);
+ const SymIntExpr *SE, bool& isFeasible);
virtual const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V,
using namespace clang;
-llvm::raw_ostream& llvm::operator<<(llvm::raw_ostream& os,
- clang::SymbolRef sym) {
- if (sym.isValid())
- os << sym.getNumber();
- else
- os << "(Invalid)";
+static void print(llvm::raw_ostream& os, const SymExpr *SE);
+
+static void print(llvm::raw_ostream& os, BinaryOperator::Opcode Op) {
+ switch (Op) {
+ default:
+ assert(false && "operator printing not implemented");
+ break;
+ case BinaryOperator::Mul: os << '*' ; break;
+ case BinaryOperator::Div: os << '/' ; break;
+ case BinaryOperator::Rem: os << '%' ; break;
+ case BinaryOperator::Add: os << '+' ; break;
+ case BinaryOperator::Sub: os << '-' ; break;
+ case BinaryOperator::Shl: os << "<<" ; break;
+ case BinaryOperator::Shr: os << ">>" ; break;
+ case BinaryOperator::LT: os << "<" ; break;
+ case BinaryOperator::GT: os << '>' ; break;
+ case BinaryOperator::LE: os << "<=" ; break;
+ case BinaryOperator::GE: os << ">=" ; break;
+ case BinaryOperator::EQ: os << "==" ; break;
+ case BinaryOperator::NE: os << "!=" ; break;
+ case BinaryOperator::And: os << '&' ; break;
+ case BinaryOperator::Xor: os << '^' ; break;
+ case BinaryOperator::Or: os << '|' ; break;
+ }
+}
+
+static void print(llvm::raw_ostream& os, const SymIntExpr *SE) {
+ os << '(';
+ print(os, SE->getLHS());
+ os << ") ";
+ print(os, SE->getOpcode());
+ os << ' ' << SE->getRHS().getZExtValue();
+ if (SE->getRHS().isUnsigned()) os << 'U';
+}
+static void print(llvm::raw_ostream& os, const SymSymExpr *SE) {
+ os << '(';
+ print(os, SE->getLHS());
+ os << ") ";
+ os << '(';
+ print(os, SE->getRHS());
+ os << ')';
+}
+
+static void print(llvm::raw_ostream& os, const SymExpr *SE) {
+ switch (SE->getKind()) {
+ case SymExpr::BEGIN_SYMBOLS:
+ case SymExpr::RegionRValue:
+ case SymExpr::ConjuredKind:
+ case SymExpr::END_SYMBOLS:
+ os << '$' << cast<SymbolData>(SE)->getSymbolID();
+ return;
+ case SymExpr::SymIntKind:
+ print(os, cast<SymIntExpr>(SE));
+ return;
+ case SymExpr::SymSymKind:
+ print(os, cast<SymSymExpr>(SE));
+ return;
+ }
+}
+
+
+llvm::raw_ostream& llvm::operator<<(llvm::raw_ostream& os, const SymExpr *SE) {
+ print(os, SE);
return os;
}
-std::ostream& std::operator<<(std::ostream& os, clang::SymbolRef sym) {
- if (sym.isValid())
- os << sym.getNumber();
- else
- os << "(Invalid)";
-
+std::ostream& std::operator<<(std::ostream& os, const SymExpr *SE) {
+ llvm::raw_os_ostream O(os);
+ print(O, SE);
return os;
}
-SymbolRef SymbolManager::getRegionRValueSymbol(const MemRegion* R) {
+const SymbolRegionRValue*
+SymbolManager::getRegionRValueSymbol(const MemRegion* R) {
llvm::FoldingSetNodeID profile;
-
SymbolRegionRValue::Profile(profile, R);
void* InsertPos;
- SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
- if (SD) return SD->getSymbol();
+ SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+ if (!SD) {
+ SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionRValue>();
+ new (SD) SymbolRegionRValue(SymbolCounter, R);
+ DataSet.InsertNode(SD, InsertPos);
+ ++SymbolCounter;
+ }
- SD = (SymbolData*) BPAlloc.Allocate<SymbolRegionRValue>();
- new (SD) SymbolRegionRValue(SymbolCounter, R);
- DataSet.InsertNode(SD, InsertPos);
- DataMap[SymbolCounter] = SD;
- return SymbolCounter++;
+ return cast<SymbolRegionRValue>(SD);
}
-SymbolRef SymbolManager::getConjuredSymbol(const Stmt* E, QualType T,
- unsigned Count,
- const void* SymbolTag) {
+const SymbolConjured*
+SymbolManager::getConjuredSymbol(const Stmt* E, QualType T, unsigned Count,
+ const void* SymbolTag) {
llvm::FoldingSetNodeID profile;
SymbolConjured::Profile(profile, E, T, Count, SymbolTag);
- void* InsertPos;
-
- SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
-
- if (SD)
- return SD->getSymbol();
-
- SD = (SymbolData*) BPAlloc.Allocate<SymbolConjured>();
- new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag);
-
- DataSet.InsertNode(SD, InsertPos);
- DataMap[SymbolCounter] = SD;
+ void* InsertPos;
+ SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+ if (!SD) {
+ SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
+ new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag);
+ DataSet.InsertNode(SD, InsertPos);
+ ++SymbolCounter;
+ }
- return SymbolCounter++;
+ return cast<SymbolConjured>(SD);
}
-SymbolRef SymbolManager::getSymIntExpr(SymbolRef lhs,BinaryOperator::Opcode op,
- const llvm::APSInt& v, QualType t) {
+const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
+ BinaryOperator::Opcode op,
+ const llvm::APSInt& v,
+ QualType t) {
llvm::FoldingSetNodeID ID;
SymIntExpr::Profile(ID, lhs, op, v, t);
- void* InsertPos;
-
- SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
-
- if (data)
- return data->getSymbol();
-
- data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
- new (data) SymIntExpr(SymbolCounter, lhs, op, v, t);
-
- DataSet.InsertNode(data, InsertPos);
- DataMap[SymbolCounter] = data;
-
- return SymbolCounter++;
+ void *InsertPos;
+ SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!data) {
+ data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
+ new (data) SymIntExpr(lhs, op, v, t);
+ DataSet.InsertNode(data, InsertPos);
+ }
+
+ return cast<SymIntExpr>(data);
}
-SymbolRef SymbolManager::getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op,
- SymbolRef rhs, QualType t) {
+const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
+ BinaryOperator::Opcode op,
+ const SymExpr *rhs,
+ QualType t) {
llvm::FoldingSetNodeID ID;
SymSymExpr::Profile(ID, lhs, op, rhs, t);
- void* InsertPos;
-
- SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
-
- if (data)
- return data->getSymbol();
-
- data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
- new (data) SymSymExpr(SymbolCounter, lhs, op, rhs, t);
-
- DataSet.InsertNode(data, InsertPos);
- DataMap[SymbolCounter] = data;
-
- return SymbolCounter++;
-}
-
-
-const SymbolData& SymbolManager::getSymbolData(SymbolRef Sym) const {
- DataMapTy::const_iterator I = DataMap.find(Sym);
- assert (I != DataMap.end());
- return *I->second;
+ void *InsertPos;
+ SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!data) {
+ data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
+ new (data) SymSymExpr(lhs, op, rhs, t);
+ DataSet.InsertNode(data, InsertPos);
+ }
+
+ return cast<SymSymExpr>(data);
}
-
QualType SymbolConjured::getType(ASTContext&) const {
return T;
}
// Interogate the symbol. It may derive from an input value to
// the analyzed function/method.
- return isa<SymbolRegionRValue>(SymMgr.getSymbolData(sym));
+ return isa<SymbolRegionRValue>(sym);
}
SymbolVisitor::~SymbolVisitor() {}