From: Ted Kremenek Date: Thu, 14 Feb 2008 19:37:24 +0000 (+0000) Subject: Migrated transfer functions for binary operators for simple value tracking X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6cb0b541fee2cac9b242b1666cecc464feaabaf5;p=clang Migrated transfer functions for binary operators for simple value tracking from RValues to GRTransferFuncs/GRSimpleVals. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47131 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp index 9ec43d911c..73ae7286eb 100644 --- a/Analysis/GRExprEngine.cpp +++ b/Analysis/GRExprEngine.cpp @@ -333,6 +333,16 @@ public: inline NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X) { return TF.EvalComplement(ValMgr, X); } + + inline NonLValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, + NonLValue LHS, NonLValue RHS) { + return TF.EvalBinaryOp(ValMgr, Op, LHS, RHS); + } + + inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, + LValue LHS, LValue RHS) { + return TF.EvalBinaryOp(ValMgr, Op, LHS, RHS); + } }; } // end anonymous namespace @@ -555,13 +565,12 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { do { nonlval::ConcreteInt CaseVal(ValMgr.getValue(V1)); - NonLValue Result = - CondV.EvalBinaryOp(ValMgr, BinaryOperator::EQ, CaseVal); + NonLValue Res = EvalBinaryOp(ValMgr, BinaryOperator::EQ, CondV, CaseVal); // Now "assume" that the case matches. bool isFeasible; - StateTy StNew = Assume(St, Result, true, isFeasible); + StateTy StNew = Assume(St, Res, true, isFeasible); if (isFeasible) { builder.generateCaseStmtNode(I, StNew); @@ -576,7 +585,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { // Now "assume" that the case doesn't match. Add this state // to the default state (if it is feasible). - StNew = Assume(DefaultSt, Result, false, isFeasible); + StNew = Assume(DefaultSt, Res, false, isFeasible); if (isFeasible) DefaultSt = StNew; @@ -805,8 +814,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, const LValue& L1 = GetLValue(St, U->getSubExpr()); NonLValue R1 = cast(GetValue(St, L1)); - NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Add, - GetRValueConstant(1U, U)); + NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Add, + R1, GetRValueConstant(1U, U)); Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result)); break; @@ -816,8 +825,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, const LValue& L1 = GetLValue(St, U->getSubExpr()); NonLValue R1 = cast(GetValue(St, L1)); - NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Sub, - GetRValueConstant(1U, U)); + NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Sub, + R1, GetRValueConstant(1U, U)); Nodify(Dst, U, N1, SetValue(SetValue(St, U, R1), L1, Result)); break; @@ -827,8 +836,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, const LValue& L1 = GetLValue(St, U->getSubExpr()); NonLValue R1 = cast(GetValue(St, L1)); - NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Add, - GetRValueConstant(1U, U)); + NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Add, + R1, GetRValueConstant(1U, U)); Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result)); break; @@ -838,8 +847,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, const LValue& L1 = GetLValue(St, U->getSubExpr()); NonLValue R1 = cast(GetValue(St, L1)); - NonLValue Result = R1.EvalBinaryOp(ValMgr, BinaryOperator::Sub, - GetRValueConstant(1U, U)); + NonLValue Result = EvalBinaryOp(ValMgr, BinaryOperator::Sub, + R1, GetRValueConstant(1U, U)); Nodify(Dst, U, N1, SetValue(SetValue(St, U, Result), L1, Result)); break; @@ -869,15 +878,15 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, const LValue& L1 = cast(V1); lval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth()); Nodify(Dst, U, N1, - SetValue(St, U, L1.EvalBinaryOp(ValMgr, BinaryOperator::EQ, - V2))); + SetValue(St, U, EvalBinaryOp(ValMgr, BinaryOperator::EQ, + L1, V2))); } else { const NonLValue& R1 = cast(V1); nonlval::ConcreteInt V2(ValMgr.getZeroWithPtrWidth()); Nodify(Dst, U, N1, - SetValue(St, U, R1.EvalBinaryOp(ValMgr, BinaryOperator::EQ, - V2))); + SetValue(St, U, EvalBinaryOp(ValMgr, BinaryOperator::EQ, + R1, V2))); } break; @@ -1023,13 +1032,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, const LValue& L1 = cast(V1); const LValue& L2 = cast(V2); - Nodify(Dst, B, N2, SetValue(St, B, L1.EvalBinaryOp(ValMgr, Op, L2))); + Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(ValMgr, Op, L1, L2))); } else { const NonLValue& R1 = cast(V1); const NonLValue& R2 = cast(V2); - Nodify(Dst, B, N2, SetValue(St, B, R1.EvalBinaryOp(ValMgr, Op, R2))); + Nodify(Dst, B, N2, SetValue(St, B, EvalBinaryOp(ValMgr, Op, R1, R2))); } continue; @@ -1058,12 +1067,12 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, if (isa(V2)) { // FIXME: Add support for Non-LValues on RHS. const LValue& L2 = cast(V2); - Result = L1.EvalBinaryOp(ValMgr, Op, L2); + Result = EvalBinaryOp(ValMgr, Op, L1, L2); } else { const NonLValue& R1 = cast(GetValue(N1->getState(), L1)); const NonLValue& R2 = cast(V2); - Result = R1.EvalBinaryOp(ValMgr, Op, R2); + Result = EvalBinaryOp(ValMgr, Op, R1, R2); } Nodify(Dst, B, N2, SetValue(SetValue(St, B, Result), L1, Result)); diff --git a/Analysis/GRSimpleVals.cpp b/Analysis/GRSimpleVals.cpp index a2711c73b4..200c9a39c6 100644 --- a/Analysis/GRSimpleVals.cpp +++ b/Analysis/GRSimpleVals.cpp @@ -79,3 +79,161 @@ NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) { return cast(UnknownVal()); } } + +// Binary operators. + +NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + NonLValue LHS, NonLValue RHS) { + + if (isa(LHS) || isa(RHS)) + return cast(UnknownVal()); + + if (isa(LHS) || isa(RHS)) + return cast(UninitializedVal()); + + while(1) { + + switch (LHS.getSubKind()) { + default: + return cast(UnknownVal()); + + case nonlval::ConcreteIntKind: + + if (isa(RHS)) { + const nonlval::ConcreteInt& LHS_CI = cast(LHS); + const nonlval::ConcreteInt& RHS_CI = cast(RHS); + return LHS_CI.EvalBinaryOp(ValMgr, Op, RHS_CI); + } + else if(isa(RHS)) + return cast(UnknownVal()); + else { + NonLValue tmp = RHS; + RHS = LHS; + LHS = tmp; + continue; + } + + case nonlval::SymbolValKind: { + if (isa(RHS)) { + const SymIntConstraint& C = + ValMgr.getConstraint(cast(LHS).getSymbol(), Op, + cast(RHS).getValue()); + + return nonlval::SymIntConstraintVal(C); + } + else + return cast(UnknownVal()); + } + } + } +} + +// Equality operators for LValues. + + +NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) { + + switch (LHS.getSubKind()) { + default: + assert(false && "EQ not implemented for this LValue."); + return cast(UnknownVal()); + + case lval::ConcreteIntKind: + if (isa(RHS)) { + bool b = cast(LHS).getValue() == + cast(RHS).getValue(); + + return NonLValue::GetIntTruthValue(ValMgr, b); + } + else if (isa(RHS)) { + + const SymIntConstraint& C = + ValMgr.getConstraint(cast(RHS).getSymbol(), + BinaryOperator::EQ, + cast(LHS).getValue()); + + return nonlval::SymIntConstraintVal(C); + } + + break; + + case lval::SymbolValKind: { + if (isa(RHS)) { + const SymIntConstraint& C = + ValMgr.getConstraint(cast(LHS).getSymbol(), + BinaryOperator::EQ, + cast(RHS).getValue()); + + return nonlval::SymIntConstraintVal(C); + } + + assert (!isa(RHS) && "FIXME: Implement unification."); + + break; + } + + case lval::DeclValKind: + + if (isa(RHS)) { + bool b = cast(LHS) == cast(RHS); + return NonLValue::GetIntTruthValue(ValMgr, b); + } + + break; + } + + return NonLValue::GetIntTruthValue(ValMgr, false); +} + +NonLValue GRSimpleVals::EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) { + + switch (LHS.getSubKind()) { + default: + assert(false && "NE not implemented for this LValue."); + return cast(UnknownVal()); + + case lval::ConcreteIntKind: + if (isa(RHS)) { + bool b = cast(LHS).getValue() != + cast(RHS).getValue(); + + return NonLValue::GetIntTruthValue(ValMgr, b); + } + else if (isa(RHS)) { + const SymIntConstraint& C = + ValMgr.getConstraint(cast(RHS).getSymbol(), + BinaryOperator::NE, + cast(LHS).getValue()); + + return nonlval::SymIntConstraintVal(C); + } + + break; + + case lval::SymbolValKind: { + if (isa(RHS)) { + const SymIntConstraint& C = + ValMgr.getConstraint(cast(LHS).getSymbol(), + BinaryOperator::NE, + cast(RHS).getValue()); + + return nonlval::SymIntConstraintVal(C); + } + + assert (!isa(RHS) && "FIXME: Implement sym !=."); + + break; + } + + case lval::DeclValKind: + if (isa(RHS)) { + bool b = cast(LHS) == cast(RHS); + return NonLValue::GetIntTruthValue(ValMgr, b); + } + + break; + } + + return NonLValue::GetIntTruthValue(ValMgr, true); +} diff --git a/Analysis/GRSimpleVals.h b/Analysis/GRSimpleVals.h index 373be305ea..1ed69688b8 100644 --- a/Analysis/GRSimpleVals.h +++ b/Analysis/GRSimpleVals.h @@ -36,6 +36,16 @@ public: NonLValue X); virtual NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X); + + // Binary Operators. + + virtual NonLValue EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + NonLValue LHS, NonLValue RHS); + + // Equality operators for LValues. + virtual NonLValue EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS); + virtual NonLValue EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS); }; diff --git a/Analysis/GRTransferFuncs.cpp b/Analysis/GRTransferFuncs.cpp index 3716ed9691..33663d6c60 100644 --- a/Analysis/GRTransferFuncs.cpp +++ b/Analysis/GRTransferFuncs.cpp @@ -39,3 +39,21 @@ RValue GRTransferFuncs::EvalCast(ValueManager& ValMgr, RValue X, return X; } + +// Binary Operators (except assignments and comma). + +RValue GRTransferFuncs::EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + LValue LHS, LValue RHS) { + + switch (Op) { + default: + assert (false && "Not yet implemented."); + + case BinaryOperator::EQ: + return EvalEQ(ValMgr, LHS, RHS); + + case BinaryOperator::NE: + return EvalNE(ValMgr, LHS, RHS); + } +} \ No newline at end of file diff --git a/Analysis/RValues.cpp b/Analysis/RValues.cpp index 17425aff5a..8d16f12d32 100644 --- a/Analysis/RValues.cpp +++ b/Analysis/RValues.cpp @@ -129,51 +129,6 @@ ValueManager::getConstraint(SymbolID sym, BinaryOperator::Opcode Op, //===----------------------------------------------------------------------===// // Transfer function dispatch for Non-LValues. //===----------------------------------------------------------------------===// - - // Binary Operators (except assignments and comma). - -NonLValue NonLValue::EvalBinaryOp(ValueManager& ValMgr, - BinaryOperator::Opcode Op, - const NonLValue& RHS) const { - - if (isa(this) || isa(RHS)) - return cast(UnknownVal()); - - if (isa(this) || isa(RHS)) - return cast(UninitializedVal()); - - switch (getSubKind()) { - default: - assert (false && "Binary Operators not implemented for this NonLValue"); - - case nonlval::ConcreteIntKind: - - if (isa(RHS)) { - nonlval::ConcreteInt& self = cast(*this); - return self.EvalBinaryOp(ValMgr, Op, - cast(RHS)); - } - else if(isa(RHS)) - return cast(UnknownVal()); - else - return RHS.EvalBinaryOp(ValMgr, Op, *this); - - case nonlval::SymbolValKind: { - const nonlval::SymbolVal& self = cast(*this); - - switch (RHS.getSubKind()) { - default: assert ("Not Implemented." && false); - case nonlval::ConcreteIntKind: { - const SymIntConstraint& C = - ValMgr.getConstraint(self.getSymbol(), Op, - cast(RHS).getValue()); - - return nonlval::SymIntConstraintVal(C); - } - } - } - } -} static const llvm::APSInt& EvaluateAPSInt(ValueManager& ValMgr, BinaryOperator::Opcode Op, @@ -262,25 +217,6 @@ nonlval::ConcreteInt::EvalMinus(ValueManager& ValMgr, UnaryOperator* U) const { // Transfer function dispatch for LValues. //===----------------------------------------------------------------------===// - // Binary Operators (except assignments and comma). - -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); - } -} - - lval::ConcreteInt lval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 54f118bf80..b38ac0c91a 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -37,7 +37,19 @@ public: virtual NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X) = 0; + // Binary Operators. + virtual NonLValue EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + NonLValue LHS, NonLValue RHS) = 0; + + RValue EvalBinaryOp(ValueManager& ValMgr, + BinaryOperator::Opcode Op, + LValue LHS, LValue RHS); + + // Equality operators for LValues. + virtual NonLValue EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) = 0; + virtual NonLValue EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) = 0; }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/RValues.h b/include/clang/Analysis/PathSensitive/RValues.h index d3b958366f..3eb08ff37e 100644 --- a/include/clang/Analysis/PathSensitive/RValues.h +++ b/include/clang/Analysis/PathSensitive/RValues.h @@ -322,10 +322,6 @@ protected: public: void print(std::ostream& Out) const; - NonLValue EvalBinaryOp(ValueManager& ValMgr, - BinaryOperator::Opcode Op, - const NonLValue& RHS) const; - // Utility methods to create NonLValues. static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T, SourceLocation Loc = SourceLocation()); @@ -351,9 +347,6 @@ protected: public: void print(std::ostream& Out) const; - - RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, - const LValue& RHS) const; static LValue GetValue(AddrLabelExpr* E);