This patch adds two more SymbolData subclasses: SymIntExpr and SymSymExpr, for

representing symbolic expressions like 'x'+3 and 'x'+'y'. The design is
subjected to change later when we fix the class hierarchy of symbolic
expressions.

llvm-svn: 67678
This commit is contained in:
Zhongxing Xu 2009-03-25 05:58:37 +00:00
parent b2304ee0d1
commit 24e7eade19
7 changed files with 152 additions and 28 deletions

View File

@ -181,6 +181,12 @@ public:
static NonLoc MakeVal(SymbolRef sym); static NonLoc MakeVal(SymbolRef sym);
static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
BinaryOperator::Opcode op, const llvm::APSInt& v);
static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
BinaryOperator::Opcode op, SymbolRef rhs);
static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X, static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
bool isUnsigned); bool isUnsigned);

View File

@ -85,7 +85,7 @@ namespace clang {
class SymbolData : public llvm::FoldingSetNode { class SymbolData : public llvm::FoldingSetNode {
public: public:
enum Kind { RegionRValue, ConjuredKind }; enum Kind { RegionRValue, ConjuredKind, SymIntKind, SymSymKind };
private: private:
Kind K; Kind K;
@ -171,6 +171,65 @@ public:
} }
}; };
// SymIntExpr - Represents symbolic expression like 'x' + 3.
class SymIntExpr : public SymbolData {
SymbolRef LHS;
BinaryOperator::Opcode Op;
const llvm::APSInt& Val;
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) {}
QualType getType(ASTContext& C) const {
return T;
}
static void Profile(llvm::FoldingSetNodeID& ID, SymbolRef lhs,
BinaryOperator::Opcode op, const llvm::APSInt& V,
QualType t) {
lhs.Profile(ID);
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.Add(t);
}
void Profile(llvm::FoldingSetNodeID& ID) {
Profile(ID, LHS, Op, RHS, T);
}
};
// Constraints on symbols. Usually wrapped by SValues. // Constraints on symbols. Usually wrapped by SValues.
class SymIntConstraint : public llvm::FoldingSetNode { class SymIntConstraint : public llvm::FoldingSetNode {
@ -230,6 +289,12 @@ public:
const void* SymbolTag = 0) { const void* SymbolTag = 0) {
return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag); return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag);
} }
SymbolRef getSymIntExpr(SymbolRef lhs, BinaryOperator::Opcode op,
const llvm::APSInt& v, QualType t);
SymbolRef getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op,
SymbolRef rhs, QualType t);
const SymbolData& getSymbolData(SymbolRef ID) const; const SymbolData& getSymbolData(SymbolRef ID) const;

View File

@ -230,11 +230,16 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
case nonloc::SymbolValKind: case nonloc::SymbolValKind:
if (isa<nonloc::ConcreteInt>(R)) { if (isa<nonloc::ConcreteInt>(R)) {
const SymIntConstraint& C = if (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE) {
BasicVals.getConstraint(cast<nonloc::SymbolVal>(L).getSymbol(), Op, const SymIntConstraint& C =
cast<nonloc::ConcreteInt>(R).getValue()); BasicVals.getConstraint(cast<nonloc::SymbolVal>(L).getSymbol(),
Op, cast<nonloc::ConcreteInt>(R).getValue());
return nonloc::SymIntConstraintVal(C); return nonloc::SymIntConstraintVal(C);
} else {
return NonLoc::MakeVal(Eng.getSymbolManager(),
cast<nonloc::SymbolVal>(L).getSymbol(),
Op, cast<nonloc::ConcreteInt>(R).getValue());
}
} }
else else
return UnknownVal(); return UnknownVal();

View File

@ -283,6 +283,23 @@ NonLoc NonLoc::MakeVal(SymbolRef sym) {
return nonloc::SymbolVal(sym); return nonloc::SymbolVal(sym);
} }
NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
BinaryOperator::Opcode op, const APSInt& v) {
// 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);
}
NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs,
BinaryOperator::Opcode op, SymbolRef rhs) {
assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
SymbolRef sym = SymMgr.getSymSymExpr(lhs, op, rhs, SymMgr.getType(lhs));
return nonloc::SymbolVal(sym);
}
NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X, NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
bool isUnsigned) { bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned)); return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned));

View File

@ -21,28 +21,11 @@ namespace clang {
SimpleConstraintManager::~SimpleConstraintManager() {} SimpleConstraintManager::~SimpleConstraintManager() {}
bool SimpleConstraintManager::canReasonAbout(SVal X) const { bool SimpleConstraintManager::canReasonAbout(SVal X) const {
if (nonloc::SymIntConstraintVal *Y = dyn_cast<nonloc::SymIntConstraintVal>(&X)) { if (nonloc::SymbolVal* SymVal = dyn_cast<nonloc::SymbolVal>(&X)) {
const SymIntConstraint& C = Y->getConstraint(); const SymbolData& data
switch (C.getOpcode()) { = getSymbolManager().getSymbolData(SymVal->getSymbol());
// We don't reason yet about bitwise-constraints on symbolic values. return !(data.getKind() == SymbolData::SymIntKind ||
case BinaryOperator::And: data.getKind() == SymbolData::SymSymKind );
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 true; return true;
@ -143,6 +126,12 @@ SimpleConstraintManager::Assume(const GRState* St, NonLoc Cond, bool Assumption,
const GRState* const GRState*
SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond, SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
bool Assumption, bool& isFeasible) { bool Assumption, bool& isFeasible) {
// We cannot reason about SymIntExpr and SymSymExpr.
if (!canReasonAbout(Cond)) {
isFeasible = true;
return St;
}
BasicValueFactory& BasicVals = StateMgr.getBasicVals(); BasicValueFactory& BasicVals = StateMgr.getBasicVals();
SymbolManager& SymMgr = StateMgr.getSymbolManager(); SymbolManager& SymMgr = StateMgr.getSymbolManager();

View File

@ -76,6 +76,7 @@ public:
private: private:
BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); } BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
SymbolManager& getSymbolManager() const { return StateMgr.getSymbolManager(); }
}; };
} // end clang namespace } // end clang namespace

View File

@ -74,6 +74,47 @@ SymbolRef SymbolManager::getConjuredSymbol(const Stmt* E, QualType T,
return SymbolCounter++; return SymbolCounter++;
} }
SymbolRef SymbolManager::getSymIntExpr(SymbolRef lhs,BinaryOperator::Opcode op,
const llvm::APSInt& v, QualType t) {
llvm::FoldingSetNodeID ID;
SymIntExpr::Profile(ID, lhs, op, v, t);
void* InsertPos;
SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
if (data)
return data->getSymbol();
data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
new (data) SymIntExpr(SymbolCounter, lhs, op, v, t);
DataSet.InsertNode(data, InsertPos);
DataMap[SymbolCounter] = data;
return SymbolCounter++;
}
SymbolRef SymbolManager::getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op,
SymbolRef rhs, QualType t) {
llvm::FoldingSetNodeID ID;
SymSymExpr::Profile(ID, lhs, op, rhs, t);
void* InsertPos;
SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
if (data)
return data->getSymbol();
data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
new (data) SymSymExpr(SymbolCounter, lhs, op, rhs, t);
DataSet.InsertNode(data, InsertPos);
DataMap[SymbolCounter] = data;
return SymbolCounter++;
}
const SymbolData& SymbolManager::getSymbolData(SymbolRef Sym) const { const SymbolData& SymbolManager::getSymbolData(SymbolRef Sym) const {
DataMapTy::const_iterator I = DataMap.find(Sym); DataMapTy::const_iterator I = DataMap.find(Sym);
assert (I != DataMap.end()); assert (I != DataMap.end());