protected ArrayState AssumeWithArrayRefinement(APC pc, bool positive, BoxedExpression comparison, ArrayState prevState) { Contract.Requires(comparison != null); Contract.Requires(prevState != null); Contract.Ensures(Contract.Result <ArrayState>() != null); // Default NonRelational values var interval = DisInterval.UnknownInterval; var symbExpression = SymbolicExpressionTracker <BoxedVariable <Variable>, BoxedExpression> .Unknown; var equalities = SetOfConstraints <BoxedVariable <Variable> > .Unknown; var disequalities = SetOfConstraints <BoxedVariable <Variable> > .Unknown; var weakUpperBounds = SetOfConstraints <BoxedVariable <Variable> > .Unknown; var strictUpperBounds = SetOfConstraints <BoxedVariable <Variable> > .Unknown; var existential = SetOfConstraints <BoxedVariable <Variable> > .Unknown; Pair <BoxedVariable <Variable>, BoxedVariable <Variable> > refined; Variable left, right; int k; #region left != right ? if (positive && comparison.IsCheckExp1NotEqExp2(out left, out right)) { // refined.One[refined.Two] != right var b = prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(left), out refined); if (!b) { // left != refined.One[refined.Two] b = prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(right), out refined); // Swap roles var tmp = left; left = right; right = tmp; } if (b) { // invariant: "left" is the one to refine. // TODO: right now we are ignoring the case when both are arrays interval = prevState.IntervalIfNotNull(left); var ael = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> (interval, symbExpression, equalities, new SetOfConstraints <BoxedVariable <Variable> >(new BoxedVariable <Variable>(right)), weakUpperBounds, strictUpperBounds, existential); var index = ToBoxedExpression(pc, refined.Two).ToNormalizedExpression <Variable>(); return(UpdateArrayAbstractValue(pc, refined.One, index, ael, prevState)); } } #endregion #region left != k ? BinaryOperator bop; if (comparison.IsCheckExpOpConst(out bop, out left, out k) && prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(left), out refined)) { switch (bop) { case BinaryOperator.Ceq: { interval = positive ? DisInterval.For(k) : DisInterval.NotInThisInterval(DisInterval.For(k)); break; } case BinaryOperator.Cne_Un: { interval = positive ? DisInterval.NotInThisInterval(DisInterval.For(k)) : DisInterval.For(k); break; } default: { return(prevState); } } var ael = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> (interval, symbExpression, equalities, disequalities, weakUpperBounds, strictUpperBounds, existential); var index = ToBoxedExpression(pc, refined.Two).Stripped().ToNormalizedExpression <Variable>(); return(UpdateArrayAbstractValue(pc, refined.One, index, ael, prevState)); } #endregion #region left == 0 if (comparison.TryGetFrameworkVariable(out left) && prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(left), out refined)) { interval = !positive ? DisInterval.Zero : DisInterval.NotZero; var ael = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> (interval, symbExpression, equalities, disequalities, weakUpperBounds, strictUpperBounds, existential); var index = ToBoxedExpression(pc, refined.Two).Stripped().ToNormalizedExpression <Variable>(); return(UpdateArrayAbstractValue(pc, refined.One, index, ael, prevState)); } #endregion return(prevState); }