analyzer infrastructure: make a bunch of changes to symbolic expressions that

Zhongxing and I discussed by email.

Main changes:
- Removed SymIntConstraintVal and SymIntConstraint
- Added SymExpr as a parent class to SymbolData, SymSymExpr, SymIntExpr
- Added nonloc::SymExprVal to wrap SymExpr
- SymbolRef is now just a typedef of 'const SymbolData*'
- Bunch of minor code cleanups in how some methods were invoked (no functionality change)

This changes are part of a long-term plan to have full symbolic expression
trees. This will be useful for lazily evaluating complicated expressions.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67731 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ted Kremenek 2009-03-26 03:35:11 +00:00
Родитель 4cbe82c7c8
Коммит e0e4ebf6bf
22 изменённых файлов: 583 добавлений и 591 удалений

Просмотреть файл

@ -47,15 +47,10 @@ class BasicValueFactory {
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;
@ -135,9 +130,6 @@ public:
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);

Просмотреть файл

@ -26,7 +26,6 @@ namespace clang {
class GRState;
class GRStateManager;
class SVal;
class SymbolRef;
class ConstraintManager {
public:

Просмотреть файл

@ -642,24 +642,24 @@ protected:
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.");

Просмотреть файл

@ -310,7 +310,7 @@ public:
ISetFactory(alloc),
GDMFactory(alloc),
BasicVals(Ctx, alloc),
SymMgr(Ctx, alloc),
SymMgr(Ctx, BasicVals, alloc),
Alloc(alloc),
cfg(c),
codedecl(cd),

Просмотреть файл

@ -32,7 +32,7 @@ class GRTransferFuncs {
protected:
virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng,
BinaryOperator::Opcode Op,
NonLoc L, NonLoc R) {
NonLoc L, NonLoc R, QualType T) {
return UnknownVal();
}
@ -59,7 +59,8 @@ public:
// 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;

Просмотреть файл

@ -182,11 +182,10 @@ public:
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;
@ -539,7 +538,7 @@ public:
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);

Просмотреть файл

@ -96,54 +96,45 @@ public:
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; }
@ -178,14 +169,15 @@ public:
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);
@ -219,8 +211,8 @@ protected:
: 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;
@ -248,17 +240,15 @@ public:
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) {
@ -271,22 +261,22 @@ public:
}
};
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;
}
};
@ -387,12 +377,9 @@ enum Kind { SymbolValKind, GotoLabelKind, MemRegionKind, FuncValKind,
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 &&

Просмотреть файл

@ -28,92 +28,64 @@ namespace llvm {
class raw_ostream;
}
namespace clang {
class MemRegion;
class SymbolManager;
class ASTContext;
class SymbolRef {
unsigned Data;
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 clang {
class MemRegion;
class ASTContext;
class BasicValueFactory;
}
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.
namespace clang {
class SymbolData : public llvm::FoldingSetNode {
class SymExpr : public llvm::FoldingSetNode {
public:
enum Kind { RegionRValue, ConjuredKind, SymIntKind, SymSymKind };
enum Kind { BEGIN_SYMBOLS, RegionRValue, ConjuredKind, END_SYMBOLS,
SymIntKind, SymSymKind };
private:
Kind K;
SymbolRef Sym;
protected:
SymExpr(Kind k) : K(k) {}
public:
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:
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; }
@ -129,8 +101,8 @@ public:
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;
}
};
@ -141,9 +113,9 @@ class SymbolConjured : public SymbolData {
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; }
@ -166,143 +138,135 @@ public:
}
// 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.Add(t);
}
void Profile(llvm::FoldingSetNodeID& ID) {
Profile(ID, LHS, Op, Val, T);
}
};
// SymSymExpr - Represents symbolic expression like 'x' + 'y'.
class SymSymExpr : public SymbolData {
SymbolRef LHS;
BinaryOperator::Opcode Op;
SymbolRef 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) {}
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);
ID.AddInteger(op);
rhs.Profile(ID);
ID.AddPointer(&rhs);
ID.Add(t);
}
void Profile(llvm::FoldingSetNodeID& ID) {
Profile(ID, LHS, Op, RHS, T);
}
// Implement isa<T> support.
static inline bool classof(const SymExpr* SE) {
return SE->getKind() == SymIntKind;
}
};
// Constraints on symbols. Usually wrapped by SValues.
class SymIntConstraint : public llvm::FoldingSetNode {
SymbolRef Symbol;
// SymSymExpr - Represents symbolic expression like 'x' + 'y'.
class SymSymExpr : public SymExpr {
const SymExpr *LHS;
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);
}
};
const SymExpr *RHS;
QualType T;
public:
SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
QualType t)
: SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(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, const SymExpr *lhs,
BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
ID.AddInteger((unsigned) SymSymKind);
ID.AddPointer(lhs);
ID.AddInteger(op);
ID.AddPointer(rhs);
ID.Add(t);
}
void Profile(llvm::FoldingSetNodeID& ID) {
Profile(ID, LHS, Op, RHS, T);
}
// 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);
const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType t);
const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType t) {
return getSymIntExpr(&lhs, op, rhs, t);
}
SymbolRef getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op,
SymbolRef rhs, QualType t);
const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType t);
const SymbolData& getSymbolData(SymbolRef ID) const;
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 {
@ -353,4 +317,13 @@ public:
} // 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

Просмотреть файл

@ -197,8 +197,8 @@ SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
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:
@ -243,8 +243,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
// 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);

Просмотреть файл

@ -97,25 +97,6 @@ const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
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) {

Просмотреть файл

@ -443,7 +443,7 @@ public:
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();
@ -545,7 +545,7 @@ public:
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();
@ -554,7 +554,7 @@ public:
else
return true;
assert (ScanSym.isValid());
assert (ScanSym);
if (!BR.isNotable(ScanSym))
return true;

Просмотреть файл

@ -1591,8 +1591,8 @@ public:
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 << ":{";
@ -1705,7 +1705,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
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) {
@ -1746,7 +1746,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
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.
@ -1833,7 +1833,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
// 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) {
@ -1977,7 +1977,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
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();
@ -2127,7 +2127,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
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).
@ -2824,9 +2824,9 @@ class VISIBILITY_HIDDEN FindUniqueBinding :
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) {

Просмотреть файл

@ -782,7 +782,8 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
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;
@ -1449,7 +1450,7 @@ void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) {
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);
@ -1940,8 +1941,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
}
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.
@ -2394,7 +2394,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
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 {
@ -2403,7 +2404,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
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
}
@ -2449,7 +2451,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
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))
@ -2643,7 +2645,6 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
return;
}
if (B->isAssignmentOp())
VisitLValue(LHS, Pred, Tmp1);
else
@ -2716,7 +2717,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// 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) {
@ -2828,7 +2829,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
}
// 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.
@ -2882,10 +2883,10 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
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);
@ -2893,13 +2894,14 @@ void GRExprEngine::EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex,
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();
@ -2926,7 +2928,7 @@ SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R) {
}
else
return getTF().DetermEvalBinOpNN(*this, Op, cast<NonLoc>(L),
cast<NonLoc>(R));
cast<NonLoc>(R), T);
}
//===----------------------------------------------------------------------===//

Просмотреть файл

@ -131,7 +131,8 @@ static unsigned char LNotOpMap[] = {
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();
@ -173,34 +174,35 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
}
}
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:
@ -231,14 +233,18 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
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
@ -308,25 +314,28 @@ TryAgain:
}
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
@ -378,25 +387,27 @@ TryAgain:
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

Просмотреть файл

@ -29,7 +29,7 @@ protected:
virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng,
BinaryOperator::Opcode Op,
NonLoc L, NonLoc R);
NonLoc L, NonLoc R, QualType T);
public:
GRSimpleVals() {}

Просмотреть файл

@ -21,7 +21,8 @@ void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates,
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)));
}

Просмотреть файл

@ -112,10 +112,8 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
//===----------------------------------------------------------------------===//
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();
@ -132,8 +130,7 @@ QualType SymbolicRegion::getRValueType(ASTContext& C) const {
}
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 {
@ -332,12 +329,9 @@ MemRegionManager::getElementRegion(SVal Idx, const TypedRegion* superRegion){
}
/// 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);
@ -345,7 +339,7 @@ SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym,
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);
}

Просмотреть файл

@ -367,8 +367,7 @@ SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base,
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:
@ -412,11 +411,9 @@ SVal RegionStoreManager::getLValueElement(const GRState* St,
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);
@ -862,8 +859,7 @@ Store RegionStoreManager::Remove(Store store, Loc L) {
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);

Просмотреть файл

@ -22,37 +22,13 @@ using llvm::cast;
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
@ -78,7 +54,7 @@ SymbolRef SVal::getAsLocSymbol() const {
}
}
return SymbolRef();
return 0;
}
/// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
@ -87,9 +63,66 @@ SymbolRef SVal::getAsSymbol() const {
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.
//===----------------------------------------------------------------------===//
@ -168,7 +201,7 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
return UndefinedVal();
}
NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const {
NonLoc Loc::EQ(SymbolManager& SymMgr, const Loc& R) const {
switch (getSubKind()) {
default:
@ -180,49 +213,48 @@ NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const {
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.");
@ -233,46 +265,43 @@ NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const {
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);
}
//===----------------------------------------------------------------------===//
@ -283,21 +312,21 @@ NonLoc NonLoc::MakeVal(SymbolRef sym) {
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,
@ -419,30 +448,6 @@ void SVal::print(llvm::raw_ostream& Out) const {
}
}
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()) {
@ -459,17 +464,10 @@ void NonLoc::print(llvm::raw_ostream& Out) const {
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;
}

Просмотреть файл

@ -21,11 +21,35 @@ namespace clang {
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;
@ -150,11 +174,14 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
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;
@ -170,50 +197,43 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
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
}

Просмотреть файл

@ -45,7 +45,7 @@ public:
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,

Просмотреть файл

@ -18,110 +18,149 @@
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;
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;
}
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;
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;
void *InsertPos;
SymExpr *data = DataSet.FindNodeOrInsertPos(ID, 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++;
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;
void *InsertPos;
SymExpr *data = DataSet.FindNodeOrInsertPos(ID, 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++;
if (!data) {
data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
new (data) SymSymExpr(lhs, op, rhs, t);
DataSet.InsertNode(data, InsertPos);
}
return cast<SymSymExpr>(data);
}
const SymbolData& SymbolManager::getSymbolData(SymbolRef Sym) const {
DataMapTy::const_iterator I = DataMap.find(Sym);
assert (I != DataMap.end());
return *I->second;
}
QualType SymbolConjured::getType(ASTContext&) const {
return T;
}
@ -158,7 +197,7 @@ bool SymbolReaper::isLive(SymbolRef sym) {
// 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() {}