зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
4cbe82c7c8
Коммит
e0e4ebf6bf
|
@ -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() {}
|
||||
|
|
Загрузка…
Ссылка в новой задаче