diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-02-06 22:50:25 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-02-06 22:50:25 +0000 |
commit | cf78b6a771bb4537d5ee8fa44e718e842c2f70c7 (patch) | |
tree | 5b29b3c10d3fc686738c29a676687c8e8717d240 | |
parent | 510190777c4bd53e960eea4665b204778fec1b64 (diff) |
Major code refactoring/cleanup with transfer function logic. Now the
code structure is more suitable for additional symbolic analysis.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46831 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | Analysis/GRConstants.cpp | 163 | ||||
-rw-r--r-- | Analysis/RValues.cpp | 314 | ||||
-rw-r--r-- | Analysis/RValues.h | 154 |
3 files changed, 331 insertions, 300 deletions
diff --git a/Analysis/GRConstants.cpp b/Analysis/GRConstants.cpp index 2b44bf7df6..516af280f4 100644 --- a/Analysis/GRConstants.cpp +++ b/Analysis/GRConstants.cpp @@ -537,7 +537,7 @@ void GRConstants::VisitCast(Expr* CastE, Expr* E, NodeTy* Pred, NodeSet& Dst) { NodeTy* N = *I1; StateTy St = N->getState(); const RValue& V = GetValue(St, E); - Nodify(Dst, CastE, N, SetValue(St, CastE, V.Cast(ValMgr, CastE))); + Nodify(Dst, CastE, N, SetValue(St, CastE, V.EvalCast(ValMgr, CastE))); } } @@ -585,7 +585,10 @@ void GRConstants::VisitUnaryOperator(UnaryOperator* U, case UnaryOperator::PostInc: { const LValue& L1 = GetLValue(St, U->getSubExpr()); NonLValue R1 = cast<NonLValue>(GetValue(St, L1)); - NonLValue Result = R1.Add(ValMgr, GetRValueConstant(1U, U)); + + NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Add, + GetRValueConstant(1U, U)); + Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result)); break; } @@ -593,7 +596,10 @@ void GRConstants::VisitUnaryOperator(UnaryOperator* U, case UnaryOperator::PostDec: { const LValue& L1 = GetLValue(St, U->getSubExpr()); NonLValue R1 = cast<NonLValue>(GetValue(St, L1)); - NonLValue Result = R1.Sub(ValMgr, GetRValueConstant(1U, U)); + + NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Sub, + GetRValueConstant(1U, U)); + Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result)); break; } @@ -601,7 +607,10 @@ void GRConstants::VisitUnaryOperator(UnaryOperator* U, case UnaryOperator::PreInc: { const LValue& L1 = GetLValue(St, U->getSubExpr()); NonLValue R1 = cast<NonLValue>(GetValue(St, L1)); - NonLValue Result = R1.Add(ValMgr, GetRValueConstant(1U, U)); + + NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Add, + GetRValueConstant(1U, U)); + Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result)); break; } @@ -609,20 +618,23 @@ void GRConstants::VisitUnaryOperator(UnaryOperator* U, case UnaryOperator::PreDec: { const LValue& L1 = GetLValue(St, U->getSubExpr()); NonLValue R1 = cast<NonLValue>(GetValue(St, L1)); - NonLValue Result = R1.Sub(ValMgr, GetRValueConstant(1U, U)); + + NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Sub, + GetRValueConstant(1U, U)); + Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result)); break; } case UnaryOperator::Minus: { const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr())); - Nodify(Dst, U, N1, SetValue(St, U, R1.UnaryMinus(ValMgr, U))); + Nodify(Dst, U, N1, SetValue(St, U, R1.EvalMinus(ValMgr, U))); break; } case UnaryOperator::Not: { const NonLValue& R1 = cast<NonLValue>(GetValue(St, U->getSubExpr())); - Nodify(Dst, U, N1, SetValue(St, U, R1.BitwiseComplement(ValMgr))); + Nodify(Dst, U, N1, SetValue(St, U, R1.EvalComplement(ValMgr))); break; } @@ -635,14 +647,18 @@ void GRConstants::VisitUnaryOperator(UnaryOperator* U, RValue V1 = GetValue(St, U->getSubExpr()); if (isa<LValue>(V1)) { - lval::ConcreteInt V2(ValMgr.getValue(0, U->getSubExpr()->getType())); - Nodify(Dst, U, N1, SetValue(St, U, - cast<LValue>(V1).EQ(ValMgr, V2))); + const LValue& L1 = cast<LValue>(V1); + lval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth()); + Nodify(Dst, U, N1, + SetValue(St, U, L1.EvalBinaryOp(ValMgr, BinaryOperator::EQ, + V2))); } else { + const NonLValue& R1 = cast<NonLValue>(V1); nonlval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth()); - Nodify(Dst, U, N1, SetValue(St, U, - cast<NonLValue>(V1).EQ(ValMgr, V2))); + Nodify(Dst, U, N1, + SetValue(St, U, R1.EvalBinaryOp(ValMgr, BinaryOperator::EQ, + V2))); } break; @@ -687,122 +703,63 @@ void GRConstants::VisitBinaryOperator(BinaryOperator* B, Visit(B->getRHS(), N1, S2); for (NodeSet::iterator I2=S2.begin(), E2=S2.end(); I2 != E2; ++I2) { + NodeTy* N2 = *I2; StateTy St = N2->getState(); const RValue& V2 = GetValue(St, B->getRHS()); - switch (B->getOpcode()) { - default: - Dst.Add(N2); - break; - - // Arithmetic operators. - - case BinaryOperator::Add: { - const NonLValue& R1 = cast<NonLValue>(V1); - const NonLValue& R2 = cast<NonLValue>(V2); - - Nodify(Dst, B, N2, SetValue(St, B, R1.Add(ValMgr, R2))); - break; - } - - case BinaryOperator::Sub: { - const NonLValue& R1 = cast<NonLValue>(V1); - const NonLValue& R2 = cast<NonLValue>(V2); - Nodify(Dst, B, N2, SetValue(St, B, R1.Sub(ValMgr, R2))); - break; - } - - case BinaryOperator::Mul: { - const NonLValue& R1 = cast<NonLValue>(V1); - const NonLValue& R2 = cast<NonLValue>(V2); - Nodify(Dst, B, N2, SetValue(St, B, R1.Mul(ValMgr, R2))); - break; - } + BinaryOperator::Opcode Op = B->getOpcode(); + + if (Op <= BinaryOperator::Or) { + + if (isa<LValue>(V1)) { + // FIXME: Add support for RHS being a non-lvalue. + const LValue& L1 = cast<LValue>(V1); + const LValue& L2 = cast<LValue>(V2); - case BinaryOperator::Div: { - const NonLValue& R1 = cast<NonLValue>(V1); - const NonLValue& R2 = cast<NonLValue>(V2); - Nodify(Dst, B, N2, SetValue(St, B, R1.Div(ValMgr, R2))); - break; + Nodify(Dst, B, N2, SetValue(St, B, L1.EvalBinaryOp(ValMgr, Op, L2))); } - - case BinaryOperator::Rem: { + else { const NonLValue& R1 = cast<NonLValue>(V1); const NonLValue& R2 = cast<NonLValue>(V2); - Nodify(Dst, B, N2, SetValue(St, B, R1.Rem(ValMgr, R2))); - break; + + Nodify(Dst, B, N2, SetValue(St, B, R1.EvalBinaryOp(ValMgr, Op, R2))); } - - // Assignment operators. - + + continue; + } + + switch (Op) { case BinaryOperator::Assign: { const LValue& L1 = cast<LValue>(V1); Nodify(Dst, B, N2, SetValue(SetValue(St, B, V2), L1, V2)); break; } + + default: { // Compound assignment operators. - case BinaryOperator::AddAssign: { - const LValue& L1 = cast<LValue>(V1); - NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1)); - NonLValue Result = R1.Add(ValMgr, cast<NonLValue>(V2)); - Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result)); - break; - } - - case BinaryOperator::SubAssign: { - const LValue& L1 = cast<LValue>(V1); - NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1)); - NonLValue Result = R1.Sub(ValMgr, cast<NonLValue>(V2)); - Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result)); - break; - } - - case BinaryOperator::MulAssign: { - const LValue& L1 = cast<LValue>(V1); - NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1)); - NonLValue Result = R1.Mul(ValMgr, cast<NonLValue>(V2)); - Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result)); - break; - } - - case BinaryOperator::DivAssign: { - const LValue& L1 = cast<LValue>(V1); - NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1)); - NonLValue Result = R1.Div(ValMgr, cast<NonLValue>(V2)); - Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result)); - break; - } - - case BinaryOperator::RemAssign: { + assert (B->isCompoundAssignmentOp()); + const LValue& L1 = cast<LValue>(V1); - NonLValue R1 = cast<NonLValue>(GetValue(N1->getState(), L1)); - NonLValue Result = R1.Rem(ValMgr, cast<NonLValue>(V2)); - Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result)); - break; - } + RValue Result = cast<NonLValue>(InvalidValue()); - // Equality operators. - - case BinaryOperator::EQ: - // FIXME: should we allow XX.EQ() to return a set of values, - // allowing state bifurcation? In such cases, they will also - // modify the state (meaning that a new state will be returned - // as well). - assert (B->getType() == getContext().IntTy); + Op = (BinaryOperator::Opcode) + (((unsigned) Op) - ((unsigned) BinaryOperator::MulAssign)); - if (isa<LValue>(V1)) { - const LValue& L1 = cast<LValue>(V1); + if (isa<LValue>(V2)) { + // FIXME: Add support for Non-LValues on RHS. const LValue& L2 = cast<LValue>(V2); - Nodify(Dst, B, N2, SetValue(St, B, L1.EQ(ValMgr, L2))); + Result = L1.EvalBinaryOp(ValMgr, Op, L2); } else { - const NonLValue& R1 = cast<NonLValue>(V1); + const NonLValue& R1 = cast<NonLValue>(GetValue(N1->getState(), L1)); const NonLValue& R2 = cast<NonLValue>(V2); - Nodify(Dst, B, N2, SetValue(St, B, R1.EQ(ValMgr, R2))); + Result = R1.EvalBinaryOp(ValMgr, Op, R2); } + Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result)); break; + } } } } diff --git a/Analysis/RValues.cpp b/Analysis/RValues.cpp index df6db08db2..bf6a0afdfd 100644 --- a/Analysis/RValues.cpp +++ b/Analysis/RValues.cpp @@ -115,37 +115,157 @@ ValueManager::getConstraint(SymbolID sym, BinaryOperator::Opcode Op, // Transfer function for Casts. //===----------------------------------------------------------------------===// -RValue RValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const { +RValue RValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const { switch (getBaseKind()) { default: assert(false && "Invalid RValue."); break; - case LValueKind: return cast<LValue>(this)->Cast(ValMgr, CastExpr); - case NonLValueKind: return cast<NonLValue>(this)->Cast(ValMgr, CastExpr); + case LValueKind: return cast<LValue>(this)->EvalCast(ValMgr, CastExpr); + case NonLValueKind: return cast<NonLValue>(this)->EvalCast(ValMgr, CastExpr); case UninitializedKind: case InvalidKind: break; } return *this; } -RValue LValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const { - if (CastExpr->getType()->isPointerType()) - return *this; + +//===----------------------------------------------------------------------===// +// Transfer function dispatch for Non-LValues. +//===----------------------------------------------------------------------===// - assert (CastExpr->getType()->isIntegerType()); + // Binary Operators (except assignments and comma). - if (!isa<lval::ConcreteInt>(*this)) - return InvalidValue(); +NonLValue NonLValue::EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + const NonLValue& RHS) const { - APSInt V = cast<lval::ConcreteInt>(this)->getValue(); - QualType T = CastExpr->getType(); - V.setIsUnsigned(T->isUnsignedIntegerType()); - V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart())); - return nonlval::ConcreteInt(ValMgr.getValue(V)); + if (isa<InvalidValue>(this) || isa<InvalidValue>(RHS)) + return cast<NonLValue>(InvalidValue()); + + if (isa<UninitializedValue>(this) || isa<UninitializedValue>(RHS)) + return cast<NonLValue>(UninitializedValue()); + + switch (getSubKind()) { + default: + assert (false && "Binary Operators not implemented for this NonLValue"); + + case nonlval::ConcreteIntKind: + + if (isa<nonlval::ConcreteInt>(RHS)) { + nonlval::ConcreteInt& self = cast<nonlval::ConcreteInt>(*this); + return self.EvalBinaryOp(ValMgr, Op, + cast<nonlval::ConcreteInt>(RHS)); + } + else if(isa<InvalidValue>(RHS)) + return cast<NonLValue>(InvalidValue()); + else + return RHS.EvalBinaryOp(ValMgr, Op, *this); + + case nonlval::SymbolValKind: { + const nonlval::SymbolVal& self = cast<nonlval::SymbolVal>(*this); + + switch (RHS.getSubKind()) { + default: assert ("Not Implemented." && false); + case nonlval::ConcreteIntKind: { + const SymIntConstraint& C = + ValMgr.getConstraint(self.getSymbol(), Op, + cast<nonlval::ConcreteInt>(RHS).getValue()); + + return nonlval::SymIntConstraintVal(C); + } + } + } + } +} + +static const +llvm::APSInt& EvaluateAPSInt(ValueManager& ValMgr, BinaryOperator::Opcode Op, + const llvm::APSInt& V1, const llvm::APSInt& V2) { + + switch (Op) { + default: + assert (false && "Invalid Opcode."); + + case BinaryOperator::Mul: + return ValMgr.getValue( V1 * V2 ); + + case BinaryOperator::Div: + return ValMgr.getValue( V1 / V2 ); + + case BinaryOperator::Rem: + return ValMgr.getValue( V1 % V2 ); + + case BinaryOperator::Add: + return ValMgr.getValue( V1 + V2 ); + + case BinaryOperator::Sub: + return ValMgr.getValue( V1 - V2 ); + +#if 0 + case BinaryOperator::Shl: + return ValMgr.getValue( V1 << V2 ); + + case BinaryOperator::Shr: + return ValMgr.getValue( V1 >> V2 ); +#endif + + case BinaryOperator::LT: + return ValMgr.getTruthValue( V1 < V2 ); + + case BinaryOperator::GT: + return ValMgr.getTruthValue( V1 > V2 ); + + case BinaryOperator::LE: + return ValMgr.getTruthValue( V1 <= V2 ); + + case BinaryOperator::GE: + return ValMgr.getTruthValue( V1 >= V2 ); + + case BinaryOperator::EQ: + return ValMgr.getTruthValue( V1 == V2 ); + + case BinaryOperator::NE: + return ValMgr.getTruthValue( V1 != V2 ); + + // Note: LAnd, LOr, Comma are handled specially by higher-level logic. + + case BinaryOperator::And: + return ValMgr.getValue( V1 & V2 ); + + case BinaryOperator::Or: + return ValMgr.getValue( V1 | V2 ); + } +} + +nonlval::ConcreteInt +nonlval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + const nonlval::ConcreteInt& RHS) const { + + return EvaluateAPSInt(ValMgr, Op, getValue(), RHS.getValue()); +} + + + // Bitwise-Complement. + +NonLValue NonLValue::EvalComplement(ValueManager& ValMgr) const { + switch (getSubKind()) { + case nonlval::ConcreteIntKind: + return cast<nonlval::ConcreteInt>(this)->EvalComplement(ValMgr); + default: + return cast<NonLValue>(InvalidValue()); + } } -RValue NonLValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const { +nonlval::ConcreteInt +nonlval::ConcreteInt::EvalComplement(ValueManager& ValMgr) const { + return ValMgr.getValue(~getValue()); +} + + // Casts. + +RValue NonLValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const { if (!isa<nonlval::ConcreteInt>(this)) return InvalidValue(); - + APSInt V = cast<nonlval::ConcreteInt>(this)->getValue(); QualType T = CastExpr->getType(); V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType()); @@ -157,123 +277,100 @@ RValue NonLValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const { return nonlval::ConcreteInt(ValMgr.getValue(V)); } -//===----------------------------------------------------------------------===// -// Transfer function dispatch for Non-LValues. -//===----------------------------------------------------------------------===// + // Unary Minus. -NonLValue NonLValue::UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const { +NonLValue NonLValue::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const { switch (getSubKind()) { case nonlval::ConcreteIntKind: - return cast<nonlval::ConcreteInt>(this)->UnaryMinus(ValMgr, U); + return cast<nonlval::ConcreteInt>(this)->EvalMinus(ValMgr, U); default: return cast<NonLValue>(InvalidValue()); } } -NonLValue NonLValue::BitwiseComplement(ValueManager& ValMgr) const { - switch (getSubKind()) { - case nonlval::ConcreteIntKind: - return cast<nonlval::ConcreteInt>(this)->BitwiseComplement(ValMgr); - default: - return cast<NonLValue>(InvalidValue()); - } +nonlval::ConcreteInt +nonlval::ConcreteInt::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const { + assert (U->getType() == U->getSubExpr()->getType()); + assert (U->getType()->isIntegerType()); + return ValMgr.getValue(-getValue()); } +//===----------------------------------------------------------------------===// +// Transfer function dispatch for LValues. +//===----------------------------------------------------------------------===// -#define NONLVALUE_DISPATCH_CASE(k1,k2,Op)\ -case (k1##Kind*nonlval::NumKind+k2##Kind):\ -return cast<k1>(*this).Op(ValMgr,cast<k2>(RHS)); - -#define NONLVALUE_DISPATCH(Op)\ -switch (getSubKind()*nonlval::NumKind+RHS.getSubKind()){\ -NONLVALUE_DISPATCH_CASE(nonlval::ConcreteInt,nonlval::ConcreteInt,Op)\ -default:\ -if (getBaseKind() == UninitializedKind ||\ -RHS.getBaseKind() == UninitializedKind)\ -return cast<NonLValue>(UninitializedValue());\ -assert (!isValid() || !RHS.isValid() && "Missing case.");\ -break;\ -}\ -return cast<NonLValue>(InvalidValue()); - -NonLValue NonLValue::Add(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Add) -} - -NonLValue NonLValue::Sub(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Sub) -} - -NonLValue NonLValue::Mul(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Mul) -} + // Binary Operators (except assignments and comma). -NonLValue NonLValue::Div(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Div) -} - -NonLValue NonLValue::Rem(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Rem) +RValue LValue::EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + const LValue& RHS) const { + + switch (Op) { + default: + assert (false && "Not yet implemented."); + + case BinaryOperator::EQ: + return EQ(ValMgr, RHS); + + case BinaryOperator::NE: + return NE(ValMgr, RHS); + } } -NonLValue NonLValue::EQ(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(EQ) -} -NonLValue NonLValue::NE(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(NE) +lval::ConcreteInt +lval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + const lval::ConcreteInt& RHS) const { + + assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub || + (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE)); + + return EvaluateAPSInt(ValMgr, Op, getValue(), RHS.getValue()); } -#undef NONLVALUE_DISPATCH_CASE -#undef NONLVALUE_DISPATCH - -//===----------------------------------------------------------------------===// -// Transfer function dispatch for LValues. -//===----------------------------------------------------------------------===// - - NonLValue LValue::EQ(ValueManager& ValMgr, const LValue& RHS) const { switch (getSubKind()) { default: assert(false && "EQ not implemented for this LValue."); return cast<NonLValue>(InvalidValue()); - + case lval::ConcreteIntKind: if (isa<lval::ConcreteInt>(RHS)) { bool b = cast<lval::ConcreteInt>(this)->getValue() == - cast<lval::ConcreteInt>(RHS).getValue(); - + cast<lval::ConcreteInt>(RHS).getValue(); + return NonLValue::GetIntTruthValue(ValMgr, b); } else if (isa<lval::SymbolVal>(RHS)) { - + const SymIntConstraint& C = - ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(), - BinaryOperator::EQ, - cast<lval::ConcreteInt>(this)->getValue()); + ValMgr.getConstraint(cast<lval::SymbolVal>(RHS).getSymbol(), + BinaryOperator::EQ, + cast<lval::ConcreteInt>(this)->getValue()); return nonlval::SymIntConstraintVal(C); } break; - case lval::SymbolValKind: { - if (isa<lval::ConcreteInt>(RHS)) { - - const SymIntConstraint& C = + case lval::SymbolValKind: { + if (isa<lval::ConcreteInt>(RHS)) { + + const SymIntConstraint& C = ValMgr.getConstraint(cast<lval::SymbolVal>(this)->getSymbol(), BinaryOperator::EQ, cast<lval::ConcreteInt>(RHS).getValue()); + + return nonlval::SymIntConstraintVal(C); + } + + assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification."); - return nonlval::SymIntConstraintVal(C); + break; } - - assert (!isa<lval::SymbolVal>(RHS) && "FIXME: Implement unification."); - break; - } - - case lval::DeclValKind: + case lval::DeclValKind: if (isa<lval::DeclVal>(RHS)) { bool b = cast<lval::DeclVal>(*this) == cast<lval::DeclVal>(RHS); return NonLValue::GetIntTruthValue(ValMgr, b); @@ -294,7 +391,7 @@ NonLValue LValue::NE(ValueManager& ValMgr, const LValue& RHS) const { case lval::ConcreteIntKind: if (isa<lval::ConcreteInt>(RHS)) { bool b = cast<lval::ConcreteInt>(this)->getValue() != - cast<lval::ConcreteInt>(RHS).getValue(); + cast<lval::ConcreteInt>(RHS).getValue(); return NonLValue::GetIntTruthValue(ValMgr, b); } @@ -338,6 +435,23 @@ NonLValue LValue::NE(ValueManager& ValMgr, const LValue& RHS) const { return NonLValue::GetIntTruthValue(ValMgr, true); } + // Casts. + +RValue LValue::EvalCast(ValueManager& ValMgr, Expr* CastExpr) const { + if (CastExpr->getType()->isPointerType()) + return *this; + + assert (CastExpr->getType()->isIntegerType()); + + if (!isa<lval::ConcreteInt>(*this)) + return InvalidValue(); + + APSInt V = cast<lval::ConcreteInt>(this)->getValue(); + QualType T = CastExpr->getType(); + V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType()); + V.extOrTrunc(ValMgr.getContext().getTypeSize(T, CastExpr->getLocStart())); + return nonlval::ConcreteInt(ValMgr.getValue(V)); +} //===----------------------------------------------------------------------===// // Utility methods for constructing Non-LValues. @@ -354,6 +468,10 @@ NonLValue NonLValue::GetValue(ValueManager& ValMgr, IntegerLiteral* I) { I->getType()->isUnsignedIntegerType()))); } +NonLValue NonLValue::GetIntTruthValue(ValueManager& ValMgr, bool b) { + return nonlval::ConcreteInt(ValMgr.getTruthValue(b)); +} + RValue RValue::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) { QualType T = D->getType(); @@ -363,6 +481,8 @@ RValue RValue::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) { return nonlval::SymbolVal(SymMgr.getSymbol(D)); } + + //===----------------------------------------------------------------------===// // Pretty-Printing. //===----------------------------------------------------------------------===// @@ -402,6 +522,10 @@ void NonLValue::print(std::ostream& Out) const { switch (getSubKind()) { case nonlval::ConcreteIntKind: Out << cast<nonlval::ConcreteInt>(this)->getValue().toString(); + + if (cast<nonlval::ConcreteInt>(this)->getValue().isUnsigned()) + Out << 'U'; + break; case nonlval::SymbolValKind: @@ -415,6 +539,10 @@ void NonLValue::print(std::ostream& Out) const { Out << '$' << C.getConstraint().getSymbol() << ' '; printOpcode(Out, C.getConstraint().getOpcode()); Out << ' ' << C.getConstraint().getInt().toString(); + + if (C.getConstraint().getInt().isUnsigned()) + Out << 'U'; + break; } diff --git a/Analysis/RValues.h b/Analysis/RValues.h index bf3fe0dec9..01df7dcd48 100644 --- a/Analysis/RValues.h +++ b/Analysis/RValues.h @@ -150,13 +150,23 @@ public: ~ValueManager(); ASTContext& getContext() const { return Ctx; } + const llvm::APSInt& getValue(const llvm::APSInt& X); const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); const llvm::APSInt& getValue(uint64_t X, QualType T, SourceLocation Loc = SourceLocation()); inline const llvm::APSInt& getZeroWithPtrWidth() { - return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()), true); + return getValue( 0, + Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()), + true ); + } + + inline const llvm::APSInt& getTruthValue(bool b) { + return getValue( b ? 1 : 0, + Ctx.getTypeSize(Ctx.IntTy, SourceLocation()), + false ); + } const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op, @@ -228,7 +238,7 @@ public: typedef llvm::SmallVector<RValue,5> BufferTy; - RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const; + RValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const; unsigned getRawKind() const { return Kind; } BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); } @@ -245,6 +255,7 @@ public: static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D); + inline bool isValid() const { return getRawKind() != InvalidKind; } inline bool isInvalid() const { return getRawKind() == InvalidKind; } @@ -280,21 +291,13 @@ protected: public: void print(std::ostream& Out) const; - RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const; + NonLValue EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + const NonLValue& RHS) const; - // Arithmetic operators. - NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const; - NonLValue BitwiseComplement(ValueManager& ValMgr) const; - - // Equality operators. - NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const; - + RValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const; + NonLValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const; + NonLValue EvalComplement(ValueManager& ValMgr) const; // Utility methods to create NonLValues. static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T, @@ -302,10 +305,8 @@ public: static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I); - static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) { - return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy); - } - + static NonLValue GetIntTruthValue(ValueManager& ValMgr, bool b); + // Implement isa<T> support. static inline bool classof(const RValue* V) { return V->getBaseKind() >= NonLValueKind; @@ -316,16 +317,19 @@ class LValue : public RValue { protected: LValue(unsigned SubKind, const void* D) : RValue(const_cast<void*>(D), true, SubKind) {} - -public: - void print(std::ostream& Out) const; - - RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const; // Equality operators. NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const; NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const; +public: + void print(std::ostream& Out) const; + + RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, + const LValue& RHS) const; + + RValue EvalCast(ValueManager& ValMgr, Expr* CastExpr) const; + // Implement isa<T> support. static inline bool classof(const RValue* V) { return V->getBaseKind() == LValueKind; @@ -380,67 +384,22 @@ namespace nonlval { return *static_cast<llvm::APSInt*>(getRawPtr()); } - // Arithmetic operators. - - ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() + V.getValue()); - } - - ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() - V.getValue()); - } - - ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() * V.getValue()); - } - - ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() / V.getValue()); - } - - ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() % V.getValue()); - } - - ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const { - assert (U->getType() == U->getSubExpr()->getType()); - assert (U->getType()->isIntegerType()); - return ValMgr.getValue(-getValue()); - } - - ConcreteInt BitwiseComplement(ValueManager& ValMgr) const { - return ValMgr.getValue(~getValue()); - } - - // Casting. - - ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const { - assert (CastExpr->getType()->isIntegerType()); - - llvm::APSInt X(getValue()); - X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(), - CastExpr->getLocStart())); - return ValMgr.getValue(X); - } - - // Equality operators. - - ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const { - const llvm::APSInt& Val = getValue(); - return ValMgr.getValue(Val == V.getValue() ? 1U : 0U, - Val.getBitWidth(), Val.isUnsigned()); - } + // Transfer functions for binary/unary operations on ConcreteInts. + ConcreteInt EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + const ConcreteInt& RHS) const; - ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const { - const llvm::APSInt& Val = getValue(); - return ValMgr.getValue(Val != V.getValue() ? 1U : 0U, - Val.getBitWidth(), Val.isUnsigned()); - } + ConcreteInt EvalComplement(ValueManager& ValMgr) const; + ConcreteInt EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const; // Implement isa<T> support. static inline bool classof(const RValue* V) { return isa<NonLValue>(V) && V->getSubKind() == ConcreteIntKind; } + + static inline bool classof(const NonLValue* V) { + return V->getSubKind() == ConcreteIntKind; + } }; } // end namespace clang::nonlval @@ -500,34 +459,21 @@ namespace lval { return *static_cast<llvm::APSInt*>(getRawPtr()); } - // Arithmetic operators. - - ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() + V.getValue()); - } - - ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() - V.getValue()); - } - - // Equality operators. - - ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const { - const llvm::APSInt& Val = getValue(); - return ValMgr.getValue(Val == V.getValue() ? 1U : 0U, - Val.getBitWidth(), Val.isUnsigned()); - } - - ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const { - const llvm::APSInt& Val = getValue(); - return ValMgr.getValue(Val != V.getValue() ? 1U : 0U, - Val.getBitWidth(), Val.isUnsigned()); - } - + + // Transfer functions for binary/unary operations on ConcreteInts. + ConcreteInt EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + const ConcreteInt& RHS) const; + // Implement isa<T> support. static inline bool classof(const RValue* V) { + return isa<LValue>(V) && V->getSubKind() == ConcreteIntKind; + } + + static inline bool classof(const LValue* V) { return V->getSubKind() == ConcreteIntKind; } + }; } // end clang::lval namespace |