public override void Binary(BinaryOperator binaryOperator, BoxedExpression left, BoxedExpression right, BoxedExpression parent) { left.Dispatch(this); if (this.Overflow) { return; } right.Dispatch(this); if (this.Overflow) { return; } switch (binaryOperator) { case BinaryOperator.Add: case BinaryOperator.Add_Ovf: case BinaryOperator.Add_Ovf_Un: { // different signs, or both positive ==> no overflow int leftSign, rightSign; if (Facts.TrySign(pc, left, out leftSign) && Facts.TrySign(pc, right, out rightSign)) { if (leftSign >= 0 || rightSign >= 0) { this.Overflow = false; return; } } // TODO: improve using upper bounds this.Overflow = true; return; } case BinaryOperator.Div: case BinaryOperator.Div_Un: case BinaryOperator.Rem: case BinaryOperator.Rem_Un: { // TODO: improve using upper bounds if (Facts.IsNonZero(pc, right) == ProofOutcome.True) { this.Overflow = false; } this.Overflow = true; return; } case BinaryOperator.Mul: case BinaryOperator.Mul_Ovf: case BinaryOperator.Mul_Ovf_Un: { // TODO: improve using upper bounds this.Overflow = true; return; } case BinaryOperator.Sub: case BinaryOperator.Sub_Ovf: case BinaryOperator.Sub_Ovf_Un: { int leftSign, rightSign; // if left is non-negative or right is non-positive ==> no undeflow if (Facts.TrySign(pc, left, out leftSign) && Facts.TrySign(pc, right, out rightSign)) { if (leftSign >= 0 || rightSign <= 0) { this.Overflow = false; return; } } this.Overflow = true; return; } case BinaryOperator.And: case BinaryOperator.Ceq: case BinaryOperator.Cge: case BinaryOperator.Cge_Un: case BinaryOperator.Cgt: case BinaryOperator.Cgt_Un: case BinaryOperator.Cle: case BinaryOperator.Cle_Un: case BinaryOperator.Clt: case BinaryOperator.Clt_Un: case BinaryOperator.Cne_Un: case BinaryOperator.Cobjeq: case BinaryOperator.LogicalAnd: case BinaryOperator.LogicalOr: case BinaryOperator.Or: case BinaryOperator.Shl: case BinaryOperator.Shr: case BinaryOperator.Shr_Un: case BinaryOperator.Xor: { this.Overflow = false; return; } default: { this.Overflow = true; return; } } }