From 9689a661ac5f48ead15a1fb92dd7b413c9b6217b Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Fri, 16 Jun 2017 13:58:31 +0100 Subject: [PATCH 01/59] (INT) Interval operations (INT) Interval values --- src/util/Makefile | 1 + src/util/interval.cpp | 1994 ++++++++++++++++++++++++++++ src/util/interval.h | 438 ++++++ src/util/irep_ids.def | 3 + unit/Makefile | 8 + unit/util/interval/add.cpp | 104 ++ unit/util/interval/bitwise.cpp | 42 + unit/util/interval/comparisons.cpp | 181 +++ unit/util/interval/divide.cpp | 0 unit/util/interval/get_extreme.cpp | 167 +++ unit/util/interval/modulo.cpp | 73 + unit/util/interval/multiply.cpp | 153 +++ unit/util/interval/shift.cpp | 44 + unit/util/interval/subtract.cpp | 104 ++ 14 files changed, 3312 insertions(+) create mode 100644 src/util/interval.cpp create mode 100644 src/util/interval.h create mode 100644 unit/util/interval/add.cpp create mode 100644 unit/util/interval/bitwise.cpp create mode 100644 unit/util/interval/comparisons.cpp create mode 100644 unit/util/interval/divide.cpp create mode 100644 unit/util/interval/get_extreme.cpp create mode 100644 unit/util/interval/modulo.cpp create mode 100644 unit/util/interval/multiply.cpp create mode 100644 unit/util/interval/shift.cpp create mode 100644 unit/util/interval/subtract.cpp diff --git a/src/util/Makefile b/src/util/Makefile index eceb2006668..1bef87393ee 100644 --- a/src/util/Makefile +++ b/src/util/Makefile @@ -107,6 +107,7 @@ SRC = allocate_objects.cpp \ version.cpp \ xml.cpp \ xml_irep.cpp \ + interval.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/util/interval.cpp b/src/util/interval.cpp new file mode 100644 index 00000000000..b41d17625df --- /dev/null +++ b/src/util/interval.cpp @@ -0,0 +1,1994 @@ +/* + * interval.cpp + * + * Created on: 16 Jun 2017 + * Author: dan + */ + +/* + * + * Types: Should we store a type for the entire interval? + * IMO: I think YES (for the case where we have -inf -> inf, we don't know otherwise + * + * This initial implementation only implements support for integers. + */ + +#include "interval.h" + +#include +#include +#include +#include +#include +#include + +const exprt &constant_interval_exprt::get_lower() const +{ + return op0(); +} + +const exprt &constant_interval_exprt::get_upper() const +{ + return op1(); +} + +//make clean -s && make -j 7 CXX="/usr/local/bin/ccache g++" -s && ./unit_tests + +const constant_interval_exprt constant_interval_exprt::unary_plus() const +{ + return *this; +} + +const constant_interval_exprt constant_interval_exprt::unary_minus() const +{ + if(is_constant()) + { + handle_constants(unary_minus_exprt()); + } + + exprt lower; + exprt upper; + + if(is_max()) + { + lower = min(); + } + else + { + lower = simplified_expr(unary_minus_exprt(get_upper())); + } + + if(is_min()) + { + upper = max(); + } + else + { + upper = simplified_expr(unary_minus_exprt(get_lower())); + } + + return constant_interval_exprt(lower, upper); +} + +const constant_interval_exprt +constant_interval_exprt::plus(const constant_interval_exprt &o) const +{ + if(o.is_constant() && is_constant()) + { + handle_constants(o, plus_exprt()); + } + + exprt lower = min(); + exprt upper = max(); + + if(is_max(get_upper()) || is_max(o.get_upper())) + { + upper = max_exprt(type()); + } + else + { + assert(!is_max(get_upper()) && !is_max(o.get_upper())); + upper = simplified_expr(plus_exprt(get_upper(), o.get_upper())); + } + + if(is_min(get_lower()) || is_min(o.get_lower())) + { + lower = min_exprt(type()); + } + else + { + assert(!is_min(get_lower()) && !is_min(o.get_lower())); + lower = simplified_expr(plus_exprt(get_lower(), o.get_lower())); + } + + return simplified_interval(lower, upper); +} + +const constant_interval_exprt +constant_interval_exprt::minus(const constant_interval_exprt &o) const +{ + if(o.is_constant() && is_constant()) + { + handle_constants(o, minus_exprt()); + } + + // e.g. [t.u - o.l, t.l - o.u] + return plus(o.unary_minus().swap()); +} + +const constant_interval_exprt +constant_interval_exprt::multiply(const constant_interval_exprt &o) const +{ + if(o.is_constant() && is_constant()) + { + handle_constants(o, mult_exprt()); + } + + mult_exprt operation; + operation.type() = type(); + return get_extremes(*this, o, operation); +} + +const constant_interval_exprt +constant_interval_exprt::divide(const constant_interval_exprt &o) const +{ + if(o.is_constant() && is_constant()) + { + handle_constants(o, div_exprt()); + } + + // If other might be division by zero, set everything to top. + if(o.contains_zero()) + { + return top(); + } + + div_exprt operation; + return get_extremes(*this, o, operation); +} + +const constant_interval_exprt +constant_interval_exprt::modulo(const constant_interval_exprt &o) const +{ + // SEE https://stackoverflow.com/questions/11720656/modulo-operation-with-negative-numbers + + if(o.is_constant() && is_constant()) + { + handle_constants(o, mod_exprt()); + } + + if(o.is_bottom()) + { + return top(); + } + + // If the RHS is 1, or -1 (signed only), then return zero. + if( + o == constant_interval_exprt(from_integer(1, o.type())) || + (o.is_signed() && o == constant_interval_exprt(from_integer(-1, o.type())))) + { + return constant_interval_exprt(zero()); + } + + // If other might be modulo by zero, set everything to top. + if(o.contains_zero()) + { + return top(); + } + + if(is_zero()) + { + return constant_interval_exprt(zero()); + } + + exprt lower = min(); + exprt upper = max(); + + // Positive case (cannot have zero on RHS). + // 10 % 5 = [0, 4], 3 % 5 = [0, 3] + if(!is_negative() && o.is_positive()) + { + lower = zero(); + upper = get_min(get_upper(), o.decrement().get_upper()); + } + + // [-5, 5] % [3] + if(is_negative(get_lower()) && is_positive(get_upper())) + { + assert(contains_zero()); + + // This can be done more accurately. + lower = get_min(o.get_lower(), get_lower()); + upper = get_max(o.get_upper(), get_upper()); + } + + if(is_negative() && o.is_negative()) + { + lower = get_min(o.get_lower(), o.get_lower()); + upper = zero(); + } + + return constant_interval_exprt(lower, upper); +} + +const tvt constant_interval_exprt::is_true() const +{ + // tvt not + return !is_false(); +} + +const tvt constant_interval_exprt::is_false() const +{ + if(equal(constant_interval_exprt(zero())).is_true()) + { + return tvt(true); + } + + if(contains(constant_interval_exprt(zero()))) + { + assert(is_positive(get_upper()) || is_negative(get_lower())); + return tvt::unknown(); + } + + return tvt(false); +} + +const tvt +constant_interval_exprt::logical_or(const constant_interval_exprt &o) const +{ + tvt a = is_true(); + tvt b = o.is_true(); + + return (a || b); +} + +const tvt +constant_interval_exprt::logical_and(const constant_interval_exprt &o) const +{ + return (is_true() && o.is_true()); +} + +const tvt +constant_interval_exprt::logical_xor(const constant_interval_exprt &o) const +{ + return ((is_true() && !o.is_true()) || (!is_true() && o.is_true())); +} + +const tvt constant_interval_exprt::logical_not() const +{ + if(is_true().is_true()) + { + return tvt(false); + } + + if(is_false().is_true()) + { + return tvt(true); + } + + return tvt::unknown(); +} + +const constant_interval_exprt +constant_interval_exprt::left_shift(const constant_interval_exprt &o) const +{ + if(o.is_constant() && is_constant()) + { + handle_constants(o, shl_exprt()); + } + + if(is_negative(o.get_lower())) + { + return top(); + } + + shl_exprt operation; + operation.type() = type(); + return get_extremes(*this, o, operation); +} + +// Arithmetic +const constant_interval_exprt +constant_interval_exprt::right_shift(const constant_interval_exprt &o) const +{ + if(o.is_constant() && is_constant()) + { + handle_constants(o, ashr_exprt()); + } + + if(is_negative(o.get_lower())) + { + return top(); + } + + ashr_exprt operation; + operation.type() = type(); + return get_extremes(*this, o, operation); +} + +const constant_interval_exprt +constant_interval_exprt::bitwise_xor(const constant_interval_exprt &o) const +{ + if(o.is_constant() && is_constant()) + { + handle_constants(o, bitxor_exprt()); + } + + return top(); +} + +const constant_interval_exprt +constant_interval_exprt::bitwise_or(const constant_interval_exprt &o) const +{ + if(o.is_constant() && is_constant()) + { + handle_constants(o, bitor_exprt()); + } + + return top(); +} + +const constant_interval_exprt +constant_interval_exprt::bitwise_and(const constant_interval_exprt &o) const +{ + if(o.is_constant() && is_constant()) + { + handle_constants(o, bitand_exprt()); + } + + return top(); +} + +const constant_interval_exprt constant_interval_exprt::bitwise_not() const +{ + if(is_constant()) + { + handle_constants(bitnot_exprt()); + } + + return top(); +} + +tvt constant_interval_exprt::less_than(const constant_interval_exprt &o) const +{ + // [get_lower, get_upper] < [o.get_lower(), o.get_upper()] + if(is_constant() && o.is_constant()) + { + return tvt(less_than(get_lower(), o.get_lower())); + } + + if(less_than(get_upper(), o.get_lower())) + { + return tvt(true); + } + + if(greater_than(get_lower(), o.get_upper())) + { + return tvt(false); + } + + return tvt::unknown(); +} + +tvt constant_interval_exprt::greater_than( + const constant_interval_exprt &o) const +{ + return o.less_than(*this); +} + +tvt constant_interval_exprt::less_than_or_equal( + const constant_interval_exprt &o) const +{ + if(is_constant() && o.is_constant()) + { + return tvt(less_than_or_equal(get_lower(), o.get_lower())); + } + + // [get_lower, get_upper] <= [o.get_lower(), o.get_upper()] + if(less_than_or_equal(get_upper(), o.get_lower())) + { + return tvt(true); + } + + if(greater_than(get_lower(), o.get_upper())) + { + return tvt(false); + } + + return tvt::unknown(); +} + +tvt constant_interval_exprt::greater_than_or_equal( + const constant_interval_exprt &o) const +{ + return o.less_than_or_equal(*this); +} + +tvt constant_interval_exprt::equal(const constant_interval_exprt &o) const +{ + if(is_constant() && o.is_constant()) + { + return tvt(equal(get_lower(), o.get_lower())); + } + + if(equal(get_upper(), o.get_upper()) && equal(get_upper(), o.get_upper())) + { + return tvt(true); + } + + if( + less_than(o).is_true() || greater_than(o).is_true() || + o.less_than(*this).is_true() || o.greater_than(*this).is_true()) + { + return tvt(false); + } + + // Don't know. Could have [3, 5] == [4] (not equal) + return tvt::unknown(); +} + +tvt constant_interval_exprt::not_equal(const constant_interval_exprt &o) const +{ + return !equal(o); +} + +const constant_interval_exprt constant_interval_exprt::increment() const +{ + return plus(constant_interval_exprt(from_integer(mp_integer(1), type()))); +} + +const constant_interval_exprt constant_interval_exprt::decrement() const +{ + return minus(constant_interval_exprt(from_integer(mp_integer(1), type()))); +} + +const constant_interval_exprt constant_interval_exprt::get_extremes( + const constant_interval_exprt &a, + const constant_interval_exprt &b, + const exprt operation) +{ + constant_interval_exprt result; + + std::vector results; + + results.push_back( + generate_expression(a.get_lower(), b.get_lower(), operation)); + results.push_back( + generate_expression(a.get_lower(), b.get_upper(), operation)); + results.push_back( + generate_expression(a.get_upper(), b.get_lower(), operation)); + results.push_back( + generate_expression(a.get_upper(), b.get_upper(), operation)); + + for(auto result : results) + { + if(!is_extreme(result) && contains_extreme(result)) + { + return constant_interval_exprt(result.type()); + } + } + + exprt min = get_min(results); + exprt max = get_max(results); + + return simplified_interval(min, max); +} + +exprt constant_interval_exprt::get_extreme( + std::vector values, + bool min_value) +{ + symbol_tablet symbol_table; + namespacet ns(symbol_table); // Empty + + if(values.size() == 0) + { + return nil_exprt(); + } + + if(values.size() == 1) + { + return *(values.begin()); + } + + if(values.size() == 2) + { + if(min_value) + { + return get_min(values.front(), values.back()); + } + else + { + return get_max(values.front(), values.back()); + } + } + + typet type = values.begin()->type(); + + for(auto v : values) + { + if((min_value && is_min(v)) || (!min_value && is_max(v))) + { + return v; + } + } + + for(auto left : values) + { + bool all_left_OP_right = true; + + for(auto right : values) + { + if( + (min_value && less_than_or_equal(left, right)) || + (!min_value && greater_than_or_equal(left, right))) + { + continue; + } + + all_left_OP_right = false; + break; + } + + if(all_left_OP_right) + { + return left; + } + } + + /* Return top */ + if(min_value) + { + return min_exprt(type); + } + else + { + return max_exprt(type); + } + + assert(0); +} + +exprt constant_interval_exprt::generate_expression( + const exprt &a, + const exprt &b, + const exprt &operation) +{ + if(operation.id() == ID_mult) + { + return generate_multiply_expression(a, b, operation); + } + + if(operation.id() == ID_div) + { + return generate_division_expression(a, b, operation); + } + + if(operation.id() == ID_mod) + { + return generate_modulo_expression(a, b, operation); + } + + if(operation.id() == ID_shl || operation.id() == ID_ashr) + { + return generate_shift_expression(a, b, operation); + } + + assert(0 && "Not yet implemented!"); +} + +exprt constant_interval_exprt::generate_multiply_expression( + const exprt &a, + const exprt &b, + exprt operation) +{ + assert(operation.id() == ID_mult); + assert(operation.type().is_not_nil() && is_numeric(operation.type())); + + if(is_max(a)) + { + return generate_multiply_expression_max(b); + } + + if(is_max(b)) + { + return generate_multiply_expression_max(a); + } + + if(is_min(a)) + { + return generate_multiply_expression_min(a, b); + } + + if(is_min(b)) + { + return generate_multiply_expression_min(b, a); + } + + assert(!is_extreme(a) && !is_extreme(b)); + + operation.copy_to_operands(a, b); + return simplified_expr(operation); +} + +exprt constant_interval_exprt::generate_multiply_expression_max( + const exprt &expr) +{ + if(is_max(expr)) + { + return max_exprt(expr); + } + + if(is_min(expr)) + { + if(is_negative(expr)) + { + return min_exprt(expr); + } + else + { + assert(!is_positive(expr) && "Min value cannot be >0."); + assert(is_zero(expr) && "Non-negative MIN must be zero."); + + return expr; + } + } + + assert(!is_extreme(expr)); + + if(is_negative(expr)) + { + return min_exprt(expr); + } + + if(is_zero(expr)) + { + return expr; + } + + if(is_positive(expr)) + { + return max_exprt(expr); + } + + assert(0 && "Unreachable."); + return nil_exprt(); +} + +exprt constant_interval_exprt::generate_multiply_expression_min( + const exprt &min, + const exprt &other) +{ + assert(is_min(min)); + + if(is_max(other)) + { + if(is_negative(min)) + { + return min_exprt(min); + } + else + { + assert(!is_positive(min) && "Min value cannot be >0."); + assert(is_zero(min) && "Non-negative MIN must be zero."); + + return min; + } + } + + if(is_min(other)) + { + assert( + !is_positive(min) && !is_positive(other) && "Min value cannot be >0."); + assert(is_negative(other) || is_zero(other)); + + if(is_negative(min) && is_negative(other)) + { + return max_exprt(min); + } + + assert(is_zero(min) || is_zero(other)); + return (is_zero(min) ? min : other); + } + + assert(0 && "Unreachable."); + return nil_exprt(); +} + +exprt constant_interval_exprt::generate_division_expression( + const exprt &a, + const exprt &b, + exprt operation) +{ + assert(operation.id() == ID_div); + assert(operation.type().is_not_nil() && is_numeric(operation.type())); + + assert(!is_zero(b)); + + if(b.is_one()) + { + return a; + } + + if(is_max(a)) + { + if(is_negative(b)) + { + return min_exprt(a); + } + + return a; + } + + if(is_min(a)) + { + if(is_negative(b)) + { + return max_exprt(a); + } + + return a; + } + + assert(!is_extreme(a)); + + if(is_max(b)) + { + return zero(b); + } + + if(is_min(b)) + { + assert(is_signed(b)); + return zero(b); + } + + assert(!is_extreme(a) && !is_extreme(b)); + + assert(!operation.has_operands()); + operation.copy_to_operands(a, b); + return simplified_expr(operation); +} + +exprt constant_interval_exprt::generate_modulo_expression( + const exprt &a, + const exprt &b, + exprt operation) +{ + assert(operation.id() == ID_mod); + assert(operation.type().is_not_nil() && is_numeric(operation.type())); + + assert(!is_zero(b)); + + if(b.is_one()) + { + return a; + } + + if(is_max(a)) + { + if(is_negative(b)) + { + return min_exprt(a); + } + + return a; + } + + if(is_min(a)) + { + if(is_negative(b)) + { + return max_exprt(a); + } + + return a; + } + + assert(!is_extreme(a)); + + if(is_max(b)) + { + return zero(b); + } + + if(is_min(b)) + { + assert(is_signed(b)); + return zero(b); + } + + assert(!is_extreme(a) && !is_extreme(b)); + + assert(!operation.has_operands()); + operation.copy_to_operands(a, b); + return simplified_expr(operation); +} + +const constant_interval_exprt constant_interval_exprt::eval(const exprt &expr) +{ + const irep_idt &id = expr.id(); + + if(id == ID_unary_plus) + { + return unary_plus(); + } + if(id == ID_unary_minus) + { + return unary_minus(); + } + if(id == ID_bitnot) + { + return bitwise_not(); + } + if(id == ID_not) + { + //return logical_not(); + return top(); + } + + return top(); +} + +const constant_interval_exprt constant_interval_exprt::eval( + const exprt &expr, + const constant_interval_exprt &o) +{ + const irep_idt &id = expr.id(); + + if(id == ID_plus) + { + return plus(o); + } + if(id == ID_minus) + { + return unary_minus(o); + } + if(id == ID_mult) + { + return multiply(o); + } + if(id == ID_div) + { + return divide(o); + } + if(id == ID_mod) + { + return modulo(o); + } + if(id == ID_shl) + { + return left_shift(o); + } + if(id == ID_ashr) + { + return right_shift(o); + } + if(id == ID_bitor) + { + return bitwise_or(o); + } + if(id == ID_bitand) + { + return bitwise_and(o); + } + if(id == ID_bitxor) + { + return bitwise_xor(o); + } + if(id == ID_lt) + { + return tv_to_interval(less_than(o)); + } + if(id == ID_le) + { + return tv_to_interval(less_than_or_equal(o)); + } + if(id == ID_gt) + { + return tv_to_interval(greater_than(o)); + } + if(id == ID_ge) + { + return tv_to_interval(greater_than_or_equal(o)); + } + if(id == ID_equal) + { + return tv_to_interval(equal(o)); + } + if(id == ID_notequal) + { + return tv_to_interval(not_equal(o)); + } + if(id == ID_and) + { + return tv_to_interval(logical_and(o)); + } + if(id == ID_or) + { + return tv_to_interval(logical_or(o)); + } + if(id == ID_xor) + { + return tv_to_interval(logical_xor(o)); + } + + return top(); +} + +const constant_interval_exprt +constant_interval_exprt::tv_to_interval(const tvt &tv) const +{ + if(tv.is_true()) + { + return constant_interval_exprt(from_integer(1, type())); + } + if(tv.is_false()) + { + return constant_interval_exprt(zero()); + } + + assert(tv.is_unknown()); + return top(); +} + +exprt constant_interval_exprt::generate_shift_expression( + const exprt &a, + const exprt &b, + exprt operation) +{ + assert(operation.id() == ID_shl || operation.id() == ID_ashr); + + if(is_zero(a) || is_zero(b)) + { + // Shifting zero does nothing. + // Shifting BY zero also does nothing. + return a; + } + + // Should be caught at an earlier stage. + assert(!is_negative(b)); + + if(is_max(a)) + { + return a; + } + + if(is_min(a)) + { + return a; + } + + if(is_max(b)) + { + return min_exprt(b); + } + + assert(!is_extreme(a) && !is_extreme(b)); + + operation.op0() = a; + operation.op1() = b; + return simplified_expr(operation); +} + +const constant_interval_exprt +constant_interval_exprt::handle_constants(exprt expr) const +{ + if(is_constant()) + { + expr.type() = type(); + expr.copy_to_operands(get_lower()); + + return constant_interval_exprt(simplified_expr(expr)); + } + + return top(); +} + +const constant_interval_exprt constant_interval_exprt::handle_constants( + const constant_interval_exprt &o, + exprt expr) const +{ + if(is_constant() && o.is_constant()) + { + expr.type() = type(); + expr.copy_to_operands(get_lower(), o.get_lower()); + return constant_interval_exprt(simplified_expr(expr)); + } + + return top(); +} + +exprt constant_interval_exprt::get_max(const exprt &a, const exprt &b) +{ + return greater_than(a, b) ? a : b; +} + +exprt constant_interval_exprt::get_min(const exprt &a, const exprt &b) +{ + return less_than(a, b) ? a : b; +} + +exprt constant_interval_exprt::get_min(std::vector &values) +{ + return get_extreme(values, true); +} + +exprt constant_interval_exprt::get_max(std::vector &values) +{ + return get_extreme(values, false); +} + +/* we don't simplify in the constructor otherwise */ +const constant_interval_exprt +constant_interval_exprt::simplified_interval(exprt &l, exprt &r) +{ + return constant_interval_exprt(simplified_expr(l), simplified_expr(r)); +} + +exprt constant_interval_exprt::simplified_expr(exprt expr) +{ + symbol_tablet symbol_table; + const namespacet ns(symbol_table); + + assert(!contains_extreme(expr)); + + return simplify_expr(expr, ns); +} + +constant_exprt constant_interval_exprt::zero(const typet &type) +{ + constant_exprt zero = from_integer(mp_integer(0), type); + assert(zero.is_zero()); // NOT is_zero(zero) (inf. recursion + return zero; +} + +constant_exprt constant_interval_exprt::zero(const exprt &expr) +{ + return zero(expr.type()); +} + +constant_exprt +constant_interval_exprt::zero(const constant_interval_exprt &interval) +{ + return zero(interval.type()); +} + +constant_exprt constant_interval_exprt::zero() const +{ + return zero(type()); +} + +min_exprt constant_interval_exprt::min() const +{ + return min_exprt(type()); +} + +max_exprt constant_interval_exprt::max() const +{ + return max_exprt(type()); +} + +bool constant_interval_exprt::is_top() const +{ + return (is_min() && is_max()); +} + +bool constant_interval_exprt::is_bottom() const +{ + // This should ONLY happen for bottom. + return is_min(get_upper()) || is_max(get_lower()); +} + +const constant_interval_exprt constant_interval_exprt::top(const typet &type) +{ + return constant_interval_exprt(type); +} + +const constant_interval_exprt constant_interval_exprt::bottom(const typet &type) +{ + return constant_interval_exprt(max_exprt(type), min_exprt(type)); +} + +const constant_interval_exprt constant_interval_exprt::top() const +{ + return constant_interval_exprt(type()); +} + +const constant_interval_exprt constant_interval_exprt::bottom() const +{ + return bottom(type()); +} + +const constant_interval_exprt +constant_interval_exprt::swap(constant_interval_exprt &i) +{ + return constant_interval_exprt(i.get_upper(), i.get_lower()); +} + +const constant_interval_exprt constant_interval_exprt::swap() const +{ + return constant_interval_exprt(get_lower(), get_upper()); +} + +/* Helpers */ + +bool constant_interval_exprt::is_int() const +{ + return is_int(type()); +} + +bool constant_interval_exprt::is_float() const +{ + return is_float(type()); +} + +bool constant_interval_exprt::is_numeric(const typet &type) +{ + return is_int(type) || is_float(type); +} + +bool constant_interval_exprt::is_numeric() const +{ + return is_numeric(type()); +} + +bool constant_interval_exprt::is_numeric(const exprt &expr) +{ + return is_numeric(expr.type()); +} + +bool constant_interval_exprt::is_numeric( + const constant_interval_exprt &interval) +{ + return interval.is_numeric(); +} + +bool constant_interval_exprt::is_int(const typet &type) +{ + return (is_signed(type) || is_unsigned(type)); +} + +bool constant_interval_exprt::is_float(const typet &src) +{ + return src.id() == ID_floatbv; +} + +bool constant_interval_exprt::is_int(const exprt &expr) +{ + return is_int(expr.type()); +} + +bool constant_interval_exprt::is_int(const constant_interval_exprt &interval) +{ + return interval.is_int(); +} + +bool constant_interval_exprt::is_float(const exprt &expr) +{ + return is_float(expr.type()); +} + +bool constant_interval_exprt::is_float(const constant_interval_exprt &interval) +{ + return interval.is_float(); +} + +bool constant_interval_exprt::is_bitvector(const typet &t) +{ + return t.id() == ID_bv || t.id() == ID_signedbv || t.id() == ID_unsignedbv || + t.id() == ID_pointer || t.id() == ID_bool; +} + +bool constant_interval_exprt::is_signed(const typet &t) +{ + return t.id() == ID_signedbv; +} + +bool constant_interval_exprt::is_unsigned(const typet &t) +{ + return t.id() == ID_bv || t.id() == ID_unsignedbv || t.id() == ID_pointer || + t.id() == ID_bool; +} + +bool constant_interval_exprt::is_signed(const constant_interval_exprt &interval) +{ + return is_signed(interval.type()); +} + +bool constant_interval_exprt::is_unsigned( + const constant_interval_exprt &interval) +{ + return is_unsigned(interval.type()); +} + +bool constant_interval_exprt::is_bitvector( + const constant_interval_exprt &interval) +{ + return is_bitvector(interval.type()); +} + +bool constant_interval_exprt::is_signed(const exprt &expr) +{ + return is_signed(expr.type()); +} + +bool constant_interval_exprt::is_unsigned(const exprt &expr) +{ + return is_unsigned(expr.type()); +} + +bool constant_interval_exprt::is_bitvector(const exprt &expr) +{ + return is_bitvector(expr.type()); +} + +bool constant_interval_exprt::is_signed() const +{ + return is_signed(type()); +} + +bool constant_interval_exprt::is_unsigned() const +{ + return is_unsigned(type()); +} + +bool constant_interval_exprt::is_bitvector() const +{ + return is_bitvector(type()); +} + +bool constant_interval_exprt::is_extreme(const exprt &expr) +{ + return (is_max(expr) || is_min(expr)); +} + +bool constant_interval_exprt::is_extreme(const exprt &expr1, const exprt &expr2) +{ + return is_extreme(expr1) || is_extreme(expr2); +} + +bool constant_interval_exprt::is_max() const +{ + return is_max(get_upper()); +} + +bool constant_interval_exprt::is_min() const +{ + return is_min(get_lower()); +} + +bool constant_interval_exprt::is_max(const exprt &expr) +{ + return expr.id() == ID_max; +} + +bool constant_interval_exprt::is_min(const exprt &expr) +{ + return expr.id() == ID_min; +} + +bool constant_interval_exprt::is_positive(const exprt &expr) +{ + exprt simplified = simplified_expr(expr); + + if(expr.is_nil() || !simplified.is_constant() || expr.get(ID_value) == "") + { + return false; + } + + if(is_unsigned(expr) || is_max(expr)) + { + return true; + } + + assert(is_signed(expr)); + // Floats later + + if(is_min(expr)) + { + return false; + } + + return greater_than(expr, zero(expr)); +} + +bool constant_interval_exprt::is_zero(const exprt &expr) +{ + if(is_min(expr)) + { + if(is_unsigned(expr)) + { + return true; + } + else + { + return false; + } + } + + if(is_max(expr)) + { + return false; + } + + assert(!is_max(expr) && !is_min(expr)); + + if(expr.is_zero()) + { + return true; + } + + return equal(expr, zero(expr)); +} + +bool constant_interval_exprt::is_negative(const exprt &expr) +{ + if(is_unsigned(expr) || is_max(expr)) + { + return false; + } + + assert(is_signed(expr)); + + if(is_min(expr)) + { + return true; + } + + assert(!is_extreme(expr)); + + return less_than(expr, zero(expr)); +} + +exprt constant_interval_exprt::abs(const exprt &expr) +{ + if(is_signed(expr) && is_min(expr)) + { + return max_exprt(expr); + } + + if(is_max(expr) || is_unsigned(expr) || is_zero(expr) || is_positive(expr)) + { + return expr; + } + + return simplified_expr(unary_minus_exprt(expr)); +} + +bool constant_interval_exprt::equal(const exprt &a, const exprt &b) +{ + if(a == b) + { + return true; + } + + if(!is_numeric(a) || !is_numeric(b)) + { + // Best we can do now is a==b?, but this is covered by the above, so always false. + assert(!(a == b)); + return false; + } + + if(is_max(a) && is_max(b)) + { + return true; + } + + exprt l = (is_min(a) && is_unsigned(a)) ? zero(a) : a; + exprt r = (is_min(b) && is_unsigned(b)) ? zero(b) : b; + + // CANNOT use is_zero(X) but can use X.is_zero(); + if((is_min(l) && is_min(r))) + { + return true; + } + + if( + (is_max(l) && !is_max(r)) || (is_min(l) && !is_min(r)) || + (is_max(r) && !is_max(l)) || (is_min(r) && !is_min(l))) + { + return false; + } + + assert(!is_extreme(l, r)); + + return simplified_expr(equal_exprt(l, r)).is_true(); +} + +// TODO: Signed/unsigned comparisons. +bool constant_interval_exprt::less_than(const exprt &a, const exprt &b) +{ + if(!is_numeric(a) || !is_numeric(b)) + { + return false; + } + + exprt l = (is_min(a) && is_unsigned(a)) ? zero(a) : a; + exprt r = (is_min(b) && is_unsigned(b)) ? zero(b) : b; + + if(is_max(l)) + { + return false; + } + + assert(!is_max(l)); + + if(is_min(r)) + { + // Can't be smaller than min. + return false; + } + + assert(!is_max(l) && !is_min(r)); + + if(is_min(l)) + { + assert(!is_min(r)); + return true; + } + + assert(!is_max(l) && !is_min(r) && !is_min(l)); + + if(is_max(r)) + { + // If r is max, then l is less, unless l is max. + return !is_max(l); + } + + assert(!is_max(l) && !is_min(r) && !is_min(l) && !is_max(r)); + + assert(!is_extreme(l, r)); + + return simplified_expr(binary_relation_exprt(l, ID_lt, r)).is_true(); +} + +bool constant_interval_exprt::greater_than(const exprt &a, const exprt &b) +{ + return less_than(b, a); + + // if(!is_numeric(a) || !is_numeric(b)) + // { + // return false; + // } + // + // exprt l=(is_min(a) && is_unsigned(a)) ? zero(a) : a; + // exprt r=(is_min(b) && is_unsigned(b)) ? zero(b) : b; + // + // if(is_max(l) && !is_max(r)) + // { + // return true; + // } + // + // if((is_max(l) && is_max(r)) || (is_min(l) && is_min(r))) + // { + // return false; + // } + // + // if(is_min(l) && is_max(r)) + // { + // return false; + // } + // + // assert(!is_extreme(l) && !is_extreme(r)); + // + // return simplified_expr(binary_relation_exprt(l, ID_gt, r)).is_true(); +} + +bool constant_interval_exprt::less_than_or_equal(const exprt &a, const exprt &b) +{ + return less_than(a, b) || equal(a, b); +} + +bool constant_interval_exprt::greater_than_or_equal( + const exprt &a, + const exprt &b) +{ + return greater_than(a, b) || equal(a, b); +} + +bool constant_interval_exprt::not_equal(const exprt &a, const exprt &b) +{ + return !equal(a, b); +} + +bool constant_interval_exprt::contains( + const constant_interval_exprt &interval) const +{ + // [a, b] Contains [c, d] If c >= a and d <= b. + return ( + less_than_or_equal(interval.get_upper(), get_upper()) && + greater_than_or_equal(interval.get_lower(), get_lower())); +} + +std::string constant_interval_exprt::to_string() const +{ + std::stringstream out; + + out << dstringt("["); + + if(!is_min()) + { + if(is_bitvector(get_lower())) + { + out << binary2integer(get_lower().get(ID_value).c_str(), 2); + } + else + { + out << get_lower().get(ID_value); + } + } + else + { + if(is_signed(get_lower())) + { + out << dstringt("MIN"); + } + else + { + out << dstringt("0"); + } + } + + out << dstringt(","); + + if(!is_max()) + { + if(is_bitvector(get_upper())) + { + out << binary2integer(get_upper().get(ID_value).c_str(), 2); + } + else + { + out << get_upper().get(ID_value); + } + } + else + out << dstringt("MAX"); + + out << dstringt("]"); + + return out.str(); +} + +std::ostream &operator<<(std::ostream &out, const constant_interval_exprt &i) +{ + out << i.to_string(); + + return out; +} + +bool operator<( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.less_than(rhs).is_true(); +} + +bool operator>( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.greater_than(rhs).is_true(); +} + +bool operator<=( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.less_than_or_equal(rhs).is_true(); +} + +bool operator>=( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.greater_than(rhs).is_true(); +} + +bool operator==( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.equal(rhs).is_true(); +} + +bool operator!=( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.not_equal(rhs).is_true(); +} + +const constant_interval_exprt operator+( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.unary_plus(rhs); +} + +const constant_interval_exprt operator-( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.minus(rhs); +} + +const constant_interval_exprt operator/( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.divide(rhs); +} + +const constant_interval_exprt operator*( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.multiply(rhs); +} + +const constant_interval_exprt operator%( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.modulo(rhs); +} + +const constant_interval_exprt operator&( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.bitwise_and(rhs); +} + +const constant_interval_exprt operator|( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.bitwise_or(rhs); +} + +const constant_interval_exprt operator^( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.bitwise_xor(rhs); +} + +const constant_interval_exprt operator!(const constant_interval_exprt &lhs) +{ + return lhs.bitwise_not(); +} + +const constant_interval_exprt operator<<( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.left_shift(rhs); +} + +const constant_interval_exprt operator>>( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs) +{ + return lhs.right_shift(rhs); +} + +const constant_interval_exprt +constant_interval_exprt::unary_plus(const constant_interval_exprt &a) +{ + return a.unary_plus(); +} + +const constant_interval_exprt +constant_interval_exprt::unary_minus(const constant_interval_exprt &a) +{ + return a.unary_minus(); +} + +/* Binary */ +const constant_interval_exprt constant_interval_exprt::plus( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.plus(b); +} + +const constant_interval_exprt constant_interval_exprt::minus( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.minus(b); +} + +const constant_interval_exprt constant_interval_exprt::multiply( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.multiply(b); +} + +const constant_interval_exprt constant_interval_exprt::divide( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.divide(b); +} + +const constant_interval_exprt constant_interval_exprt::modulo( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.modulo(b); +} + +/* Binary shifts */ +const constant_interval_exprt constant_interval_exprt::left_shift( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.left_shift(b); +} + +const constant_interval_exprt constant_interval_exprt::right_shift( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.right_shift(b); +} + +/* Unary bitwise */ +const constant_interval_exprt +constant_interval_exprt::bitwise_not(const constant_interval_exprt &a) +{ + return a.bitwise_not(); +} + +/* Binary bitwise */ +const constant_interval_exprt constant_interval_exprt::bitwise_xor( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.bitwise_xor(b); +} + +const constant_interval_exprt constant_interval_exprt::bitwise_or( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.bitwise_or(b); +} + +const constant_interval_exprt constant_interval_exprt::bitwise_and( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.bitwise_and(b); +} + +tvt constant_interval_exprt::less_than( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.less_than(b); +} + +tvt constant_interval_exprt::greater_than( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.greater_than(b); +} + +tvt constant_interval_exprt::less_than_or_equal( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.less_than_or_equal(b); +} + +tvt constant_interval_exprt::greater_than_or_equal( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.greater_than_or_equal(b); +} + +tvt constant_interval_exprt::equal( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.equal(b); +} + +tvt constant_interval_exprt::not_equal( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.equal(b); +} + +const constant_interval_exprt +constant_interval_exprt::increment(const constant_interval_exprt &a) +{ + return a.increment(); +} + +const constant_interval_exprt +constant_interval_exprt::decrement(const constant_interval_exprt &a) +{ + return a.decrement(); +} + +bool constant_interval_exprt::is_empty(const constant_interval_exprt &a) +{ + return a.is_empty(); +} + +bool constant_interval_exprt::is_constant(const constant_interval_exprt &a) +{ + return a.is_constant(); +} + +bool constant_interval_exprt::is_top(const constant_interval_exprt &a) +{ + return a.is_top(); +} + +bool constant_interval_exprt::is_bottom(const constant_interval_exprt &a) +{ + return a.is_bottom(); +} + +bool constant_interval_exprt::is_min(const constant_interval_exprt &a) +{ + return a.is_min(); +} + +bool constant_interval_exprt::is_max(const constant_interval_exprt &a) +{ + return a.is_max(); +} + +bool constant_interval_exprt::contains_extreme(const exprt expr) +{ + forall_operands(it, expr) + { + if(is_extreme(*it)) + { + return true; + } + + if(it->has_operands()) + { + return contains_extreme(*it); + } + } + + return false; +} + +bool constant_interval_exprt::contains_extreme( + const exprt expr1, + const exprt expr2) +{ + return contains_extreme(expr1) || contains_extreme(expr2); +} + +bool constant_interval_exprt::is_empty() const +{ + if(greater_than(get_lower(), get_upper())) + { + return false; + } + + return true; +} + +bool constant_interval_exprt::is_constant() const +{ + return !is_extreme(get_lower()) && !is_extreme(get_upper()) && + equal(get_lower(), get_upper()); +} + +bool constant_interval_exprt::contains_zero() const +{ + if(!is_numeric()) + { + return false; + } + + if(get_lower().is_zero() || get_upper().is_zero()) + { + return true; + } + + if(is_unsigned() && is_min(get_lower())) + { + return true; + } + + if( + less_than_or_equal(get_lower(), zero()) && + greater_than_or_equal(get_upper(), zero())) + { + return true; + } + + return false; +} + +bool constant_interval_exprt::is_positive( + const constant_interval_exprt &interval) +{ + return interval.is_positive(); +} + +bool constant_interval_exprt::is_zero(const constant_interval_exprt &interval) +{ + return interval.is_zero(); +} + +bool constant_interval_exprt::is_negative( + const constant_interval_exprt &interval) +{ + return interval.is_negative(); +} + +bool constant_interval_exprt::is_positive() const +{ + return is_positive(get_lower()) && is_positive(get_upper()); +} + +bool constant_interval_exprt::is_zero() const +{ + return is_zero(get_lower()) && is_zero(get_upper()); +} + +bool constant_interval_exprt::is_negative() const +{ + return is_negative(get_lower()) && is_negative(get_upper()); +} + +const constant_interval_exprt +tv_to_interval(const constant_interval_exprt &interval, const tvt &tv) +{ + return interval.tv_to_interval(tv); +} + +const tvt constant_interval_exprt::is_true(const constant_interval_exprt &a) +{ + return a.is_true(); +} + +const tvt constant_interval_exprt::is_false(const constant_interval_exprt &a) +{ + return a.is_false(); +} + +const tvt constant_interval_exprt::logical_and( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.logical_and(b); +} + +const tvt constant_interval_exprt::logical_or( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.logical_or(b); +} + +const tvt constant_interval_exprt::logical_xor( + const constant_interval_exprt &a, + const constant_interval_exprt &b) +{ + return a.logical_xor(b); +} + +const tvt constant_interval_exprt::logical_not(const constant_interval_exprt &a) +{ + return a.logical_not(); +} diff --git a/src/util/interval.h b/src/util/interval.h new file mode 100644 index 00000000000..e48314e5c89 --- /dev/null +++ b/src/util/interval.h @@ -0,0 +1,438 @@ +/* + * interval.h + * + * Created on: 16 Jun 2017 + * Author: dan + */ + +#ifndef SRC_ANALYSES_INTERVAL_H_ +#define SRC_ANALYSES_INTERVAL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * + * Upper set = Specific max (otherwise INF) + * Lower set = Specific min (otherwise INF) + */ + +class max_exprt : public exprt +{ +public: + explicit max_exprt(const typet &_type) : exprt(ID_max, _type) + { + } + + explicit max_exprt(const exprt &_expr) : exprt(ID_max, _expr.type()) + { + } +}; + +class min_exprt : public exprt +{ +public: + explicit min_exprt(const typet &_type) : exprt(ID_min, _type) + { + } + + explicit min_exprt(const exprt &_expr) : exprt(ID_min, _expr.type()) + { + } +}; + +class constant_interval_exprt : public binary_exprt +{ +public: + constant_interval_exprt(exprt lower, exprt upper, typet type) + : binary_exprt(lower, ID_constant_interval, upper, type) + { + PRECONDITION(lower.type() == upper.type() && type == lower.type()); + } + + constant_interval_exprt() + : constant_interval_exprt( + min_exprt(nil_typet()), + max_exprt(nil_typet()), + nil_typet()) + { + } + + explicit constant_interval_exprt(const exprt &x) + : constant_interval_exprt(x, x, x.type()) + { + } + + constant_interval_exprt(const typet type) + : constant_interval_exprt(min_exprt(type), max_exprt(type), type) + { + } + + constant_interval_exprt(const exprt &lower, const exprt &upper) + : constant_interval_exprt(lower, upper, lower.type()) + { + } + + /* Naming scheme + * is_[X]? Returns bool / tvt + * get_[X]? Returns relevant object + * [X] Generator of some object. + * generate_[X] generator used for evaluation + */ + + /* Getters */ + const exprt &get_lower() const; + const exprt &get_upper() const; + + /** SET OF ARITHMETIC OPERATORS */ + const constant_interval_exprt handle_constants(exprt expr) const; + const constant_interval_exprt + handle_constants(const constant_interval_exprt &o, exprt expr) const; + + const constant_interval_exprt eval(const exprt &expr); + const constant_interval_exprt + eval(const exprt &expr, const constant_interval_exprt &o); + + /* Unary arithmetic */ + const constant_interval_exprt unary_plus() const; + const constant_interval_exprt unary_minus() const; + + /* Logical */ + const tvt is_true() const; + const tvt is_false() const; + + const tvt logical_and(const constant_interval_exprt &o) const; + const tvt logical_or(const constant_interval_exprt &o) const; + const tvt logical_xor(const constant_interval_exprt &o) const; + const tvt logical_not() const; + + const constant_interval_exprt tv_to_interval(const tvt &tv) const; + + /* Binary */ + const constant_interval_exprt plus(const constant_interval_exprt &o) const; + const constant_interval_exprt minus(const constant_interval_exprt &o) const; + const constant_interval_exprt + multiply(const constant_interval_exprt &o) const; + const constant_interval_exprt divide(const constant_interval_exprt &o) const; + const constant_interval_exprt modulo(const constant_interval_exprt &o) const; + + /* Binary shifts */ + const constant_interval_exprt + left_shift(const constant_interval_exprt &o) const; + const constant_interval_exprt + right_shift(const constant_interval_exprt &o) const; + + /* Unary bitwise */ + const constant_interval_exprt bitwise_not() const; + + /* Binary bitwise */ + const constant_interval_exprt + bitwise_xor(const constant_interval_exprt &o) const; + const constant_interval_exprt + bitwise_or(const constant_interval_exprt &o) const; + const constant_interval_exprt + bitwise_and(const constant_interval_exprt &o) const; + + tvt less_than(const constant_interval_exprt &o) const; + tvt greater_than(const constant_interval_exprt &o) const; + tvt less_than_or_equal(const constant_interval_exprt &o) const; + tvt greater_than_or_equal(const constant_interval_exprt &o) const; + tvt equal(const constant_interval_exprt &o) const; + tvt not_equal(const constant_interval_exprt &o) const; + + const constant_interval_exprt increment() const; + const constant_interval_exprt decrement() const; + + bool is_empty() const; + bool is_constant() const; + /** END SET OF ARITHMETIC OPERATORS */ + + // tvt contains(constant_interval_exprt &o) const; + + /* SET OF EXPR COMPARATORS */ + static bool equal(const exprt &a, const exprt &b); + static bool not_equal(const exprt &a, const exprt &b); + static bool less_than(const exprt &a, const exprt &b); + static bool less_than_or_equal(const exprt &a, const exprt &b); + static bool greater_than(const exprt &a, const exprt &b); + static bool greater_than_or_equal(const exprt &a, const exprt &b); + /* END SET OF EXPR COMPS */ + + /* INTERVAL COMPARISONS, returns tvt.is_true(). False cannot be trusted + * (could be false or unknown, either use less_than, etc method or use the correct + * operator)! */ + friend bool operator<( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend bool operator>( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend bool operator<=( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend bool operator>=( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend bool operator==( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend bool operator!=( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + + /* Operator override for intervals */ + friend const constant_interval_exprt operator+( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend const constant_interval_exprt operator-( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend const constant_interval_exprt operator/( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend const constant_interval_exprt operator*( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend const constant_interval_exprt operator%( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend const constant_interval_exprt operator!( + const constant_interval_exprt &lhs); + friend const constant_interval_exprt operator&( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend const constant_interval_exprt operator|( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend const constant_interval_exprt operator^( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend const constant_interval_exprt operator<<( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + friend const constant_interval_exprt operator>>( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs); + + friend std::ostream & + operator<<(std::ostream &out, const constant_interval_exprt &i); + std::string to_string() const; + + /* Now static equivalents! */ + static const tvt is_true(const constant_interval_exprt &a); + static const tvt is_false(const constant_interval_exprt &a); + + static const tvt logical_and( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + static const tvt logical_or( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + static const tvt logical_xor( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + static const tvt logical_not(const constant_interval_exprt &a); + + static const constant_interval_exprt + tv_to_interval(const constant_interval_exprt &interval, const tvt &tv); + + static const constant_interval_exprt + unary_plus(const constant_interval_exprt &a); + static const constant_interval_exprt + unary_minus(const constant_interval_exprt &a); + + /* Binary */ + static const constant_interval_exprt + plus(const constant_interval_exprt &a, const constant_interval_exprt &b); + static const constant_interval_exprt + minus(const constant_interval_exprt &a, const constant_interval_exprt &b); + static const constant_interval_exprt + multiply(const constant_interval_exprt &a, const constant_interval_exprt &b); + static const constant_interval_exprt + divide(const constant_interval_exprt &a, const constant_interval_exprt &b); + static const constant_interval_exprt + modulo(const constant_interval_exprt &a, const constant_interval_exprt &b); + + /* Binary shifts */ + static const constant_interval_exprt left_shift( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + static const constant_interval_exprt right_shift( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + + /* Unary bitwise */ + static const constant_interval_exprt + bitwise_not(const constant_interval_exprt &a); + + /* Binary bitwise */ + static const constant_interval_exprt bitwise_xor( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + static const constant_interval_exprt bitwise_or( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + static const constant_interval_exprt bitwise_and( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + + static tvt + less_than(const constant_interval_exprt &a, const constant_interval_exprt &b); + static tvt greater_than( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + static tvt less_than_or_equal( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + static tvt greater_than_or_equal( + const constant_interval_exprt &a, + const constant_interval_exprt &b); + static tvt + equal(const constant_interval_exprt &a, const constant_interval_exprt &b); + static tvt + not_equal(const constant_interval_exprt &a, const constant_interval_exprt &b); + + static const constant_interval_exprt + increment(const constant_interval_exprt &a); + static const constant_interval_exprt + decrement(const constant_interval_exprt &a); + + static bool is_empty(const constant_interval_exprt &a); + static bool is_constant(const constant_interval_exprt &a); + + static bool is_top(const constant_interval_exprt &a); + static bool is_bottom(const constant_interval_exprt &a); + + static bool is_min(const constant_interval_exprt &a); + static bool is_max(const constant_interval_exprt &a); + /* End static equivalents */ + + bool is_top() const; + bool is_bottom() const; + static const constant_interval_exprt top(const typet &type); + static const constant_interval_exprt bottom(const typet &type); + const constant_interval_exprt top() const; + const constant_interval_exprt bottom() const; + + bool is_min() const; + bool is_max() const; + static bool is_min(const exprt &expr); + static bool is_max(const exprt &expr); + + /* Generate min and max exprt according to current type */ + min_exprt min() const; + max_exprt max() const; + + constant_exprt zero() const; + static constant_exprt zero(const typet &type); + static constant_exprt zero(const exprt &expr); + static constant_exprt zero(const constant_interval_exprt &interval); + + /* Private? */ + static const constant_interval_exprt get_extremes( + const constant_interval_exprt &lhs, + const constant_interval_exprt &rhs, + const exprt operation); + static exprt get_extreme(std::vector values, bool min = true); + static exprt get_max(const exprt &a, const exprt &b); + static exprt get_min(const exprt &a, const exprt &b); + static exprt get_min(std::vector &values); + static exprt get_max(std::vector &values); + + /* we don't simplify in the constructor otherwise */ + static const constant_interval_exprt simplified_interval(exprt &l, exprt &r); + static exprt simplified_expr(exprt expr); + + /* Swap lower and upper! */ + const constant_interval_exprt swap() const; + static const constant_interval_exprt swap(constant_interval_exprt &i); + /* Helpers */ + /* Four common params: self, static: type, expr, interval */ + + bool is_numeric() const; + static bool is_numeric(const typet &type); + static bool is_numeric(const exprt &expr); + static bool is_numeric(const constant_interval_exprt &interval); + + bool is_int() const; + static bool is_int(const typet &type); + static bool is_int(const exprt &expr); + static bool is_int(const constant_interval_exprt &interval); + + bool is_float() const; + static bool is_float(const typet &type); + static bool is_float(const exprt &expr); + static bool is_float(const constant_interval_exprt &interval); + + bool is_bitvector() const; + static bool is_bitvector(const typet &type); + static bool is_bitvector(const constant_interval_exprt &interval); + static bool is_bitvector(const exprt &expr); + + bool is_signed() const; + static bool is_signed(const typet &type); + static bool is_signed(const exprt &expr); + static bool is_signed(const constant_interval_exprt &interval); + + bool is_unsigned() const; + static bool is_unsigned(const typet &type); + static bool is_unsigned(const exprt &expr); + static bool is_unsigned(const constant_interval_exprt &interval); + + bool contains_zero() const; + bool contains(const constant_interval_exprt &interval) const; + + static bool is_extreme(const exprt &expr); + static bool is_extreme(const exprt &expr1, const exprt &expr2); + + static bool contains_extreme(const exprt expr); + static bool contains_extreme(const exprt expr1, const exprt expr2); + + bool is_positive() const; + static bool is_positive(const exprt &expr); + static bool is_positive(const constant_interval_exprt &interval); + + bool is_zero() const; + static bool is_zero(const exprt &expr); + static bool is_zero(const constant_interval_exprt &interval); + + bool is_negative() const; + static bool is_negative(const exprt &expr); + static bool is_negative(const constant_interval_exprt &interval); + + static exprt abs(const exprt &expr); + +private: + static exprt + generate_expression(const exprt &a, const exprt &b, const exprt &operation); + static exprt + generate_multiply_expression(const exprt &a, const exprt &b, exprt operation); + static exprt generate_multiply_expression_max(const exprt &expr); + static exprt + generate_multiply_expression_min(const exprt &min, const exprt &other); + static exprt + generate_division_expression(const exprt &a, const exprt &b, exprt operation); + static exprt + generate_modulo_expression(const exprt &a, const exprt &b, exprt operation); + static exprt + generate_shift_expression(const exprt &a, const exprt &b, exprt operation); +}; + +inline const constant_interval_exprt & +to_constant_interval_expr(const exprt &expr) +{ + PRECONDITION(expr.id() == ID_constant_interval); + return static_cast(expr); +} + +#endif /* SRC_ANALYSES_INTERVAL_H_ */ diff --git a/src/util/irep_ids.def b/src/util/irep_ids.def index 01634767857..84a2364a93d 100644 --- a/src/util/irep_ids.def +++ b/src/util/irep_ids.def @@ -837,6 +837,9 @@ IREP_ID_ONE(statement_list_reset) IREP_ID_ONE(statement_list_not) IREP_ID_ONE(statement_list_instruction) IREP_ID_ONE(statement_list_instructions) +IREP_ID_ONE(max) +IREP_ID_ONE(min) +IREP_ID_ONE(constant_interval) // Projects depending on this code base that wish to extend the list of // available ids should provide a file local_irep_ids.def in their source tree diff --git a/unit/Makefile b/unit/Makefile index 5ba0727175f..80e00dc5cb6 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -77,6 +77,14 @@ SRC += analyses/ai/ai.cpp \ util/format_number_range.cpp \ util/get_base_name.cpp \ util/graph.cpp \ + util/interval/multiply.cpp \ + util/interval/add.cpp \ + util/interval/get_extreme.cpp \ + util/interval/subtract.cpp \ + util/interval/modulo.cpp \ + util/interval/shift.cpp \ + util/interval/comparisons.cpp \ + util/interval/bitwise.cpp \ util/interval_constraint.cpp \ util/interval_union.cpp \ util/irep.cpp \ diff --git a/unit/util/interval/add.cpp b/unit/util/interval/add.cpp new file mode 100644 index 00000000000..0d6040a0c9b --- /dev/null +++ b/unit/util/interval/add.cpp @@ -0,0 +1,104 @@ +/*******************************************************************\ + Module: Unit tests for variable/sensitivity/abstract_object::merge + Author: DiffBlue Limited. All rights reserved. +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) +#define V_(X) (binary2integer(X.c_str(), 2)) + +SCENARIO("add interval domain", "[core][analyses][interval][add]") +{ + GIVEN("Two simple signed intervals") + { + const typet type = signedbv_typet(32); + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + source_locationt source_location; + + std::map values; + + for(int i = -100; i <= 100; i++) + { + values[i] = from_integer(mp_integer(i), type); + } + + WHEN("Both are positive [2,4]+[6,8]") + { + interval_exprt left(values[2], values[4]); + interval_exprt right(values[6], values[8]); + + interval_exprt result = left.plus(right); + + THEN("Domain is consistent") + { + REQUIRE(V(left.get_lower()) == 2); + REQUIRE(V(left.get_upper()) == 4); + REQUIRE(V(right.get_lower()) == 6); + REQUIRE(V(right.get_upper()) == 8); + } + + THEN("The result is [8, 12]") + { + REQUIRE(V(result.get_lower()) == 8); + REQUIRE(V(result.get_upper()) == 12); + } + } + + WHEN("One contains infinite [2,4]+[6,INF]") + { + interval_exprt left(values[2], values[4]); + interval_exprt right(values[6], max_exprt(type)); + + interval_exprt result = left.plus(right); + + THEN("Domain is consistent") + { + REQUIRE(V(left.get_lower()) == 2); + REQUIRE(V(left.get_upper()) == 4); + REQUIRE(V(right.get_lower()) == 6); + REQUIRE(right.is_max()); + } + + CAPTURE(result); + + THEN("The result is [8, MAX]") + { + REQUIRE(V(result.get_lower()) == 8); + REQUIRE(result.is_max()); + } + } + + WHEN("Both contain infinite [2,INF]+[6,INF]") + { + interval_exprt left(values[2], max_exprt(type)); + interval_exprt right(values[6], max_exprt(type)); + + interval_exprt result = left.plus(right); + + THEN("Domain is consistent") + { + REQUIRE(V(left.get_lower()) == 2); + REQUIRE(left.is_max()); + REQUIRE(V(right.get_lower()) == 6); + REQUIRE(right.is_max()); + } + + CAPTURE(result); + + THEN("The result is [8, MAX]") + { + REQUIRE(V(result.get_lower()) == 8); + REQUIRE(result.is_max()); + } + } + } +} diff --git a/unit/util/interval/bitwise.cpp b/unit/util/interval/bitwise.cpp new file mode 100644 index 00000000000..c45ec15d18c --- /dev/null +++ b/unit/util/interval/bitwise.cpp @@ -0,0 +1,42 @@ +/*******************************************************************\ + Module: Unit tests for variable/sensitivity/abstract_object::merge + Author: DiffBlue Limited. All rights reserved. +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) +#define V_(X) (binary2integer(X.c_str(), 2)) + +SCENARIO("bitwise interval domain", "[core][analyses][interval][bitwise]") +{ + GIVEN("Two simple signed intervals") + { + const typet type = signedbv_typet(32); + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + source_locationt source_location; + + std::map values; + + for(int i = -100; i <= 100; i++) + { + values[i] = from_integer(mp_integer(i), type); + } + + WHEN("Something") + { + THEN("Something else") + { + REQUIRE(true); + } + } + } +} diff --git a/unit/util/interval/comparisons.cpp b/unit/util/interval/comparisons.cpp new file mode 100644 index 00000000000..ffa054fd24f --- /dev/null +++ b/unit/util/interval/comparisons.cpp @@ -0,0 +1,181 @@ +/*******************************************************************\ + Module: Unit tests for variable/sensitivity/abstract_object::merge + Author: DiffBlue Limited. All rights reserved. +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) +#define V_(X) (binary2integer(X.c_str(), 2)) + +SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") +{ + GIVEN("Two simple signed intervals") + { + const typet type = signedbv_typet(32); + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + const typet t = type; + + source_locationt source_location; + + std::map v; + + for(int i = -100; i <= 100; i++) + { + v[i] = from_integer(mp_integer(i), type); + } + + WHEN("<, >, <=, >=, ==, != are tested on expressions") + { + THEN("Require correctness") + { + REQUIRE(interval_exprt::less_than(v[0], v[1])); + REQUIRE(interval_exprt::less_than(v[1], v[2])); + REQUIRE(interval_exprt::less_than(v[1], v[100])); + + REQUIRE(interval_exprt::less_than(v[-10], v[1])); + REQUIRE_FALSE(interval_exprt::less_than(v[-10], v[-100])); + REQUIRE(interval_exprt::less_than(v[-10], v[-5])); + REQUIRE(interval_exprt::less_than(v[-10], max_exprt(t))); + REQUIRE(interval_exprt::less_than(v[10], max_exprt(t))); + REQUIRE(interval_exprt::less_than(v[0], max_exprt(t))); + + REQUIRE_FALSE(interval_exprt::less_than(v[-10], min_exprt(t))); + REQUIRE_FALSE(interval_exprt::less_than(v[10], min_exprt(t))); + REQUIRE_FALSE(interval_exprt::less_than(v[0], min_exprt(t))); + + REQUIRE_FALSE(interval_exprt::less_than(min_exprt(t), min_exprt(t))); + REQUIRE_FALSE(interval_exprt::less_than(max_exprt(t), min_exprt(t))); + REQUIRE_FALSE(interval_exprt::less_than(max_exprt(t), max_exprt(t))); + REQUIRE(interval_exprt::less_than(min_exprt(t), max_exprt(t))); + + REQUIRE(interval_exprt::equal(min_exprt(t), min_exprt(t))); + REQUIRE(interval_exprt::not_equal(max_exprt(t), min_exprt(t))); + REQUIRE(interval_exprt::equal(max_exprt(t), max_exprt(t))); + REQUIRE(interval_exprt::not_equal(min_exprt(t), max_exprt(t))); + } + + THEN("") + { + REQUIRE_FALSE(interval_exprt::greater_than(v[0], v[1])); + REQUIRE_FALSE(interval_exprt::greater_than(v[1], v[2])); + REQUIRE_FALSE(interval_exprt::greater_than(v[1], v[100])); + + REQUIRE_FALSE(interval_exprt::greater_than(v[-10], v[1])); + REQUIRE(interval_exprt::greater_than(v[-10], v[-100])); + REQUIRE_FALSE(interval_exprt::greater_than(v[-10], v[-5])); + REQUIRE_FALSE(interval_exprt::greater_than(v[-10], max_exprt(t))); + REQUIRE_FALSE(interval_exprt::greater_than(v[10], max_exprt(t))); + REQUIRE_FALSE(interval_exprt::greater_than(v[0], max_exprt(t))); + + REQUIRE(interval_exprt::greater_than(v[-10], min_exprt(t))); + REQUIRE(interval_exprt::greater_than(v[10], min_exprt(t))); + REQUIRE(interval_exprt::greater_than(v[0], min_exprt(t))); + + REQUIRE_FALSE(interval_exprt::greater_than(min_exprt(t), min_exprt(t))); + REQUIRE( + interval_exprt::greater_than_or_equal(min_exprt(t), min_exprt(t))); + + REQUIRE(interval_exprt::greater_than(max_exprt(t), min_exprt(t))); + REQUIRE( + interval_exprt::greater_than_or_equal(max_exprt(t), min_exprt(t))); + + REQUIRE_FALSE(interval_exprt::greater_than(max_exprt(t), max_exprt(t))); + + REQUIRE_FALSE(interval_exprt::greater_than(min_exprt(t), max_exprt(t))); + } + } + + WHEN("<, >, <=, >=, ==, != are tested on intervals") + { + THEN("Require correctness") + { + CHECK(interval_exprt(v[10], v[20]) < interval_exprt(v[30], v[40])); + REQUIRE_FALSE( + interval_exprt(v[10], v[30]) < interval_exprt(v[30], v[40])); + REQUIRE_FALSE( + interval_exprt(v[10], v[20]) > interval_exprt(v[30], v[40])); + } + + THEN( + "[10, 29] < [30, 40] == true, [10, 30] < [30, 40] == unknown, [10, 31] " + "< [30, 40] == unknown") + { + CHECK( + interval_exprt(v[10], v[29]) + .less_than(interval_exprt(v[30], v[40])) == tvt(true)); + CHECK( + interval_exprt(v[10], v[30]) + .less_than(interval_exprt(v[30], v[40])) == tvt::unknown()); + CHECK( + interval_exprt(v[10], v[31]) + .less_than(interval_exprt(v[30], v[40])) == tvt::unknown()); + + CHECK( + interval_exprt(v[30], v[40]) + .less_than(interval_exprt(v[10], v[29])) == tvt(false)); + } + + THEN( + "[10, 29] > [30, 40] == false, [10, 30] > [30, 40] == unknown, [10, " + "31] > [30, 40] == unknown") + { + CHECK( + interval_exprt(v[10], v[29]) + .greater_than(interval_exprt(v[30], v[40])) == tvt(false)); + CHECK( + interval_exprt(v[10], v[29]) + .greater_than(interval_exprt(v[30], v[40])) == + interval_exprt(v[30], v[40]).less_than(interval_exprt(v[10], v[29]))); + + CHECK( + interval_exprt(v[10], v[30]) + .greater_than(interval_exprt(v[30], v[40])) == tvt::unknown()); + CHECK( + interval_exprt(v[10], v[31]) + .greater_than(interval_exprt(v[30], v[40])) == tvt::unknown()); + } + + THEN( + "[10, 29] <= [30, 40] == true, [10, 30] <= [30, 40] == true, [10, 31] " + "<- [30, 40] == unknown") + { + CHECK( + interval_exprt(v[10], v[29]) + .less_than_or_equal(interval_exprt(v[30], v[40])) == tvt(true)); + CHECK( + interval_exprt(v[10], v[30]) + .less_than_or_equal(interval_exprt(v[30], v[40])) == tvt(true)); + CHECK( + interval_exprt(v[10], v[31]) + .less_than_or_equal(interval_exprt(v[30], v[40])) == + tvt::unknown()); + } + + THEN( + "[10, 29] >= [30, 40] == false, [10, 30] >= [30, 40] == unknown, [10, " + "31] >= [30, 40] == unknown") + { + CHECK( + interval_exprt(v[10], v[29]) + .greater_than_or_equal(interval_exprt(v[30], v[40])) == tvt(false)); + CHECK( + interval_exprt(v[10], v[30]) + .greater_than_or_equal(interval_exprt(v[30], v[40])) == + tvt::unknown()); + CHECK( + interval_exprt(v[10], v[31]) + .greater_than_or_equal(interval_exprt(v[30], v[40])) == + tvt::unknown()); + } + } + } +} diff --git a/unit/util/interval/divide.cpp b/unit/util/interval/divide.cpp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/unit/util/interval/get_extreme.cpp b/unit/util/interval/get_extreme.cpp new file mode 100644 index 00000000000..d36516cfa9e --- /dev/null +++ b/unit/util/interval/get_extreme.cpp @@ -0,0 +1,167 @@ +/*******************************************************************\ + Module: Unit tests for variable/sensitivity/abstract_object::merge + Author: DiffBlue Limited. All rights reserved. +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) +#define V_(X) (binary2integer(X.c_str(), 2)) + +SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") +{ + GIVEN("A selection of constant_exprts in a std::vector and map") + { + const typet type = signedbv_typet(32); + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + std::map values; + std::vector ve; + + for(int i = -100; i <= 100; i++) + { + values[i] = from_integer(mp_integer(i), type); + ve.push_back(from_integer(mp_integer(i), type)); + // values[i] = constant_exprt(std::to_string(i), integer_typet());; + // ve.push_back(exprt(constant_exprt(std::to_string(i), integer_typet()))); + } + + WHEN("-20 <= 20 is tested") + { + binary_predicate_exprt op1(values[-20], ID_le, values[20]); + bool interval_eval = + interval_exprt::less_than_or_equal(values[-20], values[20]); + simplify(op1, ns); + + THEN("Require it is TRUE") + { + REQUIRE(op1.is_true()); + REQUIRE(interval_eval); + } + } + + WHEN("20 <= -20 is tested") + { + binary_predicate_exprt op1(values[20], ID_le, values[-20]); + bool interval_eval = + interval_exprt::less_than_or_equal(values[20], values[-20]); + simplify(op1, ns); + + THEN("Require it is FALSE") + { + REQUIRE(op1.is_false()); + REQUIRE_FALSE(interval_eval); + } + } + + WHEN("-20 <= -20 is tested") + { + binary_predicate_exprt op1(values[-20], ID_le, values[-20]); + bool interval_eval = + interval_exprt::less_than_or_equal(values[-20], values[-20]); + + simplify(op1, ns); + + THEN("Require it is TRUE") + { + REQUIRE(op1.is_true()); + REQUIRE(interval_eval); + REQUIRE(interval_exprt::equal(values[1], values[1])); + } + } + + WHEN("Two are selected and min found [20, -20]") + { + std::vector selected = {values[20], values[-20]}; + + exprt min = interval_exprt::get_extreme(selected, true); + exprt max = interval_exprt::get_extreme(selected, false); + + THEN("Min (-20) and max (20) are verified") + { + CAPTURE(min.pretty()); + + REQUIRE(V(min) == -20); + REQUIRE(V(max) == 20); + } + } + + WHEN("Four are selected and min found [-20, 0, 20, 50]") + { + std::vector selected = { + values[-20], values[0], values[50], values[20]}; + + exprt min = interval_exprt::get_extreme(selected, true); + exprt max = interval_exprt::get_extreme(selected, false); + + THEN("Min (-20) and max (50) are verified") + { + REQUIRE(V(min) == -20); + REQUIRE(V(max) == 50); + } + } + + WHEN("One is selected [-100]") + { + std::vector selected = {values[-100]}; + + exprt min = interval_exprt::get_extreme(selected, true); + exprt max = interval_exprt::get_extreme(selected, false); + + THEN("Max (-100) and min (-100) are verified") + { + REQUIRE(V(min) == -100); + REQUIRE(V(max) == -100); + } + } + + WHEN("Five are selected [20, 30, 15, 0, -100]") + { + std::vector selected = { + values[20], values[30], values[15], values[0], values[-100]}; + + exprt min = interval_exprt::get_extreme(selected, true); + exprt max = interval_exprt::get_extreme(selected, false); + + THEN("Max (30) and min (-100) are verified") + { + REQUIRE(V(min) == -100); + REQUIRE(V(max) == 30); + } + } + + WHEN("All from [-100:100] are selected") + { + exprt min = interval_exprt::get_extreme(ve, true); + exprt max = interval_exprt::get_extreme(ve, false); + + THEN("Max (100) and min (-100) are verified") + { + REQUIRE(V(min) == -100); + REQUIRE(V(max) == 100); + } + } + + WHEN("All from [-100:100] are shuffled and selected") + { + std::random_shuffle(ve.begin(), ve.end()); + + exprt min = interval_exprt::get_extreme(ve, true); + exprt max = interval_exprt::get_extreme(ve, false); + + THEN("Max (100) and min (-100) are verified") + { + REQUIRE(V(min) == -100); + REQUIRE(V(max) == 100); + } + } + } +} diff --git a/unit/util/interval/modulo.cpp b/unit/util/interval/modulo.cpp new file mode 100644 index 00000000000..bedace39767 --- /dev/null +++ b/unit/util/interval/modulo.cpp @@ -0,0 +1,73 @@ +/*******************************************************************\ + Module: Unit tests for variable/sensitivity/abstract_object::merge + Author: DiffBlue Limited. All rights reserved. +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) +#define V_(X) (binary2integer(X.c_str(), 2)) + +SCENARIO("modulo interval domain", "[core][analyses][interval][modulo]") +{ + GIVEN("Two simple signed intervals") + { + const typet type = signedbv_typet(32); + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + source_locationt source_location; + + std::map v; + + for(int i = -100; i <= 100; i++) + { + v[i] = from_integer(mp_integer(i), type); + } + + WHEN("Positive RHS") + { + THEN("Ensure result is consistent.") + { + REQUIRE( + interval_exprt(v[10], v[20]).modulo(interval_exprt(v[5], v[5])) == + interval_exprt(v[0], v[4])); + REQUIRE( + interval_exprt(v[10], v[20]).modulo(interval_exprt(v[4], v[5])) == + interval_exprt(v[0], v[4])); + REQUIRE( + interval_exprt(v[10], v[20]).modulo(interval_exprt(v[0], v[5])) == + interval_exprt::top(type)); + REQUIRE( + interval_exprt(v[10], v[20]).modulo(interval_exprt(v[-5], v[5])) == + interval_exprt::top(type)); + + REQUIRE( + interval_exprt(v[-10], v[20]).modulo(interval_exprt(v[0], v[5])) == + interval_exprt::top(type)); + REQUIRE( + interval_exprt(v[-20], v[-10]).modulo(interval_exprt(v[0], v[5])) == + interval_exprt::top(type)); + + REQUIRE( + interval_exprt(v[-20], v[-10]).modulo(interval_exprt(v[1], v[1])) == + interval_exprt(v[0])); + + REQUIRE( + interval_exprt(v[30], v[50]).modulo(interval_exprt(v[2], v[2])) == + interval_exprt(v[0], v[1])); + + // Problems + REQUIRE( + interval_exprt(v[30], max_exprt(type)) + .modulo(interval_exprt(v[2], v[2])) == interval_exprt(v[0], v[1])); + } + } + } +} diff --git a/unit/util/interval/multiply.cpp b/unit/util/interval/multiply.cpp new file mode 100644 index 00000000000..4566f949ee4 --- /dev/null +++ b/unit/util/interval/multiply.cpp @@ -0,0 +1,153 @@ +/*******************************************************************\ + Module: Unit tests for variable/sensitivity/abstract_object::merge + Author: DiffBlue Limited. All rights reserved. +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) +#define V_(X) (binary2integer(X.c_str(), 2)) + +SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") +{ + GIVEN("A selection of constant_exprts in a std::vector and map") + { + const typet type = signedbv_typet(32); + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + std::map values; + std::vector ve; + + for(int i = -100; i <= 100; i++) + { + values[i] = from_integer(mp_integer(i), type); + ve.push_back(exprt(from_integer(mp_integer(i), type))); + } + + WHEN("Both are positive [2,5]*[7,11]") + { + interval_exprt a(values[2], values[5]); + interval_exprt b(values[7], values[11]); + + interval_exprt result = a.multiply(b); + + THEN("Domain is consistent") + { + CHECK(V(a.get_lower()) == 2); + CHECK(V(a.get_upper()) == 5); + CHECK(V(b.get_lower()) == 7); + CHECK(V(b.get_upper()) == 11); + } + + CAPTURE(result); + + THEN("The result is [14, 55]") + { + CHECK(V(result.get_lower()) == 14); + CHECK(V(result.get_upper()) == 55); + } + } + + WHEN("One is entirely negative [-2,-5]*[7,11]") + { + interval_exprt a(values[-2], values[-5]); + interval_exprt b(values[7], values[11]); + + interval_exprt result = a.multiply(b); + + THEN("Domain is consistent") + { + CHECK(V(a.get_lower()) == -2); + CHECK(V(a.get_upper()) == -5); + CHECK(V(b.get_lower()) == 7); + CHECK(V(b.get_upper()) == 11); + } + + CAPTURE(result); + + THEN("The result is [-55, -14]") + { + CHECK(V(result.get_lower()) == mp_integer(-55)); + CHECK(V(result.get_upper()) == -14); + } + } + + WHEN("Range contains and extends from zero [-2,5]*[7,11]") + { + interval_exprt a(values[-2], values[5]); + interval_exprt b(values[7], values[11]); + + interval_exprt result = a.multiply(b); + + THEN("Domain is consistent") + { + CHECK(V(a.get_lower()) == -2); + CHECK(V(a.get_upper()) == 5); + CHECK(V(b.get_lower()) == 7); + CHECK(V(b.get_upper()) == 11); + } + + CAPTURE(result); + + THEN("The result is [-22, 55]") + { + CHECK(V(result.get_lower()) == mp_integer(-22)); + CHECK(V(result.get_upper()) == 55); + } + } + + WHEN("One domain is infinite and other crosses zero [-2,5]*[7,INF]") + { + interval_exprt a(values[-2], values[5]); + interval_exprt b(values[7], max_exprt(type)); + + interval_exprt result = a.multiply(b); + + THEN("Domain is consistent") + { + CHECK(V(a.get_lower()) == -2); + CHECK(V(a.get_upper()) == 5); + CHECK(V(b.get_lower()) == 7); + CHECK(interval_exprt::is_max(b.get_upper())); + } + + CAPTURE(result); + + THEN("The result is [-INF, INF]") + { + CHECK(interval_exprt::is_max(result.get_upper())); + CHECK(interval_exprt::is_min(result.get_lower())); + } + } + + WHEN("One domain is infinite and other is positive [2,5]*[7,INF]") + { + interval_exprt a(values[2], values[5]); + interval_exprt b(values[7], max_exprt(type)); + interval_exprt result = a.multiply(b); + + THEN("Domain is consistent") + { + CHECK(V(a.get_lower()) == 2); + CHECK(V(a.get_upper()) == 5); + CHECK(V(b.get_lower()) == 7); + CHECK(b.is_max()); + } + + THEN("The result is [14, INF]") + { + CAPTURE(result); + + CHECK(result.is_max()); + CHECK(V(result.get_lower()) == 14); + } + } + } +} diff --git a/unit/util/interval/shift.cpp b/unit/util/interval/shift.cpp new file mode 100644 index 00000000000..5ff8f37ee88 --- /dev/null +++ b/unit/util/interval/shift.cpp @@ -0,0 +1,44 @@ +/*******************************************************************\ + Module: Unit tests for variable/sensitivity/abstract_object::merge + Author: DiffBlue Limited. All rights reserved. +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) +#define V_(X) (binary2integer(X.c_str(), 2)) + +SCENARIO("shift interval domain", "[core][analyses][interval][shift]") +{ + GIVEN("Two simple signed intervals") + { + const typet type = signedbv_typet(32); + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + source_locationt source_location; + + std::map v; + + for(int i = -100; i <= 100; i++) + { + v[i] = from_integer(mp_integer(i), type); + } + + WHEN("Something") + { + THEN("Something else") + { + REQUIRE( + interval_exprt(v[4], v[8]).left_shift(interval_exprt(v[1])) == + interval_exprt(v[8], v[16])); + } + } + } +} diff --git a/unit/util/interval/subtract.cpp b/unit/util/interval/subtract.cpp new file mode 100644 index 00000000000..c29b79c1d75 --- /dev/null +++ b/unit/util/interval/subtract.cpp @@ -0,0 +1,104 @@ +/*******************************************************************\ + Module: Unit tests for variable/sensitivity/abstract_object::merge + Author: DiffBlue Limited. All rights reserved. +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) +#define V_(X) (binary2integer(X.c_str(), 2)) + +SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") +{ + GIVEN("Two simple signed intervals") + { + const typet type = signedbv_typet(32); + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + source_locationt source_location; + + std::map values; + + for(int i = -100; i <= 100; i++) + { + values[i] = from_integer(mp_integer(i), type); + } + + WHEN("The result is positive [6,8]-[2,4]") + { + interval_exprt left(values[6], values[8]); + interval_exprt right(values[2], values[4]); + + interval_exprt result = left.minus(right); + + THEN("Domain is consistent") + { + REQUIRE(V(left.get_lower()) == 6); + REQUIRE(V(left.get_upper()) == 8); + REQUIRE(V(right.get_lower()) == 2); + REQUIRE(V(right.get_upper()) == 4); + } + + THEN("The result is [2, 6]") + { + REQUIRE(V(result.get_lower()) == 2); + REQUIRE(V(result.get_upper()) == 6); + } + } + + WHEN("One contains infinite [2,4]-[6,INF]") + { + interval_exprt left(values[2], values[4]); + interval_exprt right(values[6], max_exprt(type)); + + interval_exprt result = left.minus(right); + + THEN("Domain is consistent") + { + REQUIRE(V(left.get_lower()) == 2); + REQUIRE(V(left.get_upper()) == 4); + REQUIRE(V(right.get_lower()) == 6); + REQUIRE(right.is_max()); + } + + CAPTURE(result); + + THEN("The result is [MIN, -2]") + { + REQUIRE(V(result.get_upper()) == -2); + REQUIRE(result.is_min()); + } + } + + WHEN("Both contain infinite [2,INF]-[6,INF]") + { + interval_exprt left(values[2], max_exprt(type)); + interval_exprt right(values[6], max_exprt(type)); + + interval_exprt result = left.minus(right); + + THEN("Domain is consistent") + { + REQUIRE(V(left.get_lower()) == 2); + REQUIRE(left.is_max()); + REQUIRE(V(right.get_lower()) == 6); + REQUIRE(right.is_max()); + } + + CAPTURE(result); + + THEN("The result is [MIN, MAX]") + { + REQUIRE(result.is_max()); + REQUIRE(result.is_min()); + } + } + } +} From eefe162ed6daa75246eb44a6122209b0c8659bda Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 9 May 2018 15:34:20 +0100 Subject: [PATCH 02/59] (INT) Fix broken interval unit tests --- unit/util/interval/add.cpp | 22 ++-- unit/util/interval/bitwise.cpp | 4 +- unit/util/interval/comparisons.cpp | 182 ++++++++++++++++------------- unit/util/interval/get_extreme.cpp | 36 +++--- unit/util/interval/modulo.cpp | 49 ++++---- unit/util/interval/multiply.cpp | 40 +++---- unit/util/interval/shift.cpp | 9 +- unit/util/interval/subtract.cpp | 22 ++-- 8 files changed, 198 insertions(+), 166 deletions(-) diff --git a/unit/util/interval/add.cpp b/unit/util/interval/add.cpp index 0d6040a0c9b..1f0a2bab786 100644 --- a/unit/util/interval/add.cpp +++ b/unit/util/interval/add.cpp @@ -3,10 +3,10 @@ Author: DiffBlue Limited. All rights reserved. \*******************************************************************/ -#include +#include -#include #include +#include #include #include #include @@ -33,10 +33,10 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") WHEN("Both are positive [2,4]+[6,8]") { - interval_exprt left(values[2], values[4]); - interval_exprt right(values[6], values[8]); + constant_interval_exprt left(values[2], values[4]); + constant_interval_exprt right(values[6], values[8]); - interval_exprt result = left.plus(right); + constant_interval_exprt result = left.plus(right); THEN("Domain is consistent") { @@ -55,10 +55,10 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") WHEN("One contains infinite [2,4]+[6,INF]") { - interval_exprt left(values[2], values[4]); - interval_exprt right(values[6], max_exprt(type)); + constant_interval_exprt left(values[2], values[4]); + constant_interval_exprt right(values[6], max_exprt(type)); - interval_exprt result = left.plus(right); + constant_interval_exprt result = left.plus(right); THEN("Domain is consistent") { @@ -79,10 +79,10 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") WHEN("Both contain infinite [2,INF]+[6,INF]") { - interval_exprt left(values[2], max_exprt(type)); - interval_exprt right(values[6], max_exprt(type)); + constant_interval_exprt left(values[2], max_exprt(type)); + constant_interval_exprt right(values[6], max_exprt(type)); - interval_exprt result = left.plus(right); + constant_interval_exprt result = left.plus(right); THEN("Domain is consistent") { diff --git a/unit/util/interval/bitwise.cpp b/unit/util/interval/bitwise.cpp index c45ec15d18c..88898fb413e 100644 --- a/unit/util/interval/bitwise.cpp +++ b/unit/util/interval/bitwise.cpp @@ -3,10 +3,10 @@ Author: DiffBlue Limited. All rights reserved. \*******************************************************************/ -#include +#include -#include #include +#include #include #include #include diff --git a/unit/util/interval/comparisons.cpp b/unit/util/interval/comparisons.cpp index ffa054fd24f..a20eb03ed66 100644 --- a/unit/util/interval/comparisons.cpp +++ b/unit/util/interval/comparisons.cpp @@ -3,10 +3,10 @@ Author: DiffBlue Limited. All rights reserved. \*******************************************************************/ -#include +#include -#include #include +#include #include #include #include @@ -37,60 +37,70 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") { THEN("Require correctness") { - REQUIRE(interval_exprt::less_than(v[0], v[1])); - REQUIRE(interval_exprt::less_than(v[1], v[2])); - REQUIRE(interval_exprt::less_than(v[1], v[100])); - - REQUIRE(interval_exprt::less_than(v[-10], v[1])); - REQUIRE_FALSE(interval_exprt::less_than(v[-10], v[-100])); - REQUIRE(interval_exprt::less_than(v[-10], v[-5])); - REQUIRE(interval_exprt::less_than(v[-10], max_exprt(t))); - REQUIRE(interval_exprt::less_than(v[10], max_exprt(t))); - REQUIRE(interval_exprt::less_than(v[0], max_exprt(t))); - - REQUIRE_FALSE(interval_exprt::less_than(v[-10], min_exprt(t))); - REQUIRE_FALSE(interval_exprt::less_than(v[10], min_exprt(t))); - REQUIRE_FALSE(interval_exprt::less_than(v[0], min_exprt(t))); - - REQUIRE_FALSE(interval_exprt::less_than(min_exprt(t), min_exprt(t))); - REQUIRE_FALSE(interval_exprt::less_than(max_exprt(t), min_exprt(t))); - REQUIRE_FALSE(interval_exprt::less_than(max_exprt(t), max_exprt(t))); - REQUIRE(interval_exprt::less_than(min_exprt(t), max_exprt(t))); - - REQUIRE(interval_exprt::equal(min_exprt(t), min_exprt(t))); - REQUIRE(interval_exprt::not_equal(max_exprt(t), min_exprt(t))); - REQUIRE(interval_exprt::equal(max_exprt(t), max_exprt(t))); - REQUIRE(interval_exprt::not_equal(min_exprt(t), max_exprt(t))); + REQUIRE(constant_interval_exprt::less_than(v[0], v[1])); + REQUIRE(constant_interval_exprt::less_than(v[1], v[2])); + REQUIRE(constant_interval_exprt::less_than(v[1], v[100])); + + REQUIRE(constant_interval_exprt::less_than(v[-10], v[1])); + REQUIRE_FALSE(constant_interval_exprt::less_than(v[-10], v[-100])); + REQUIRE(constant_interval_exprt::less_than(v[-10], v[-5])); + REQUIRE(constant_interval_exprt::less_than(v[-10], max_exprt(t))); + REQUIRE(constant_interval_exprt::less_than(v[10], max_exprt(t))); + REQUIRE(constant_interval_exprt::less_than(v[0], max_exprt(t))); + + REQUIRE_FALSE(constant_interval_exprt::less_than(v[-10], min_exprt(t))); + REQUIRE_FALSE(constant_interval_exprt::less_than(v[10], min_exprt(t))); + REQUIRE_FALSE(constant_interval_exprt::less_than(v[0], min_exprt(t))); + + REQUIRE_FALSE( + constant_interval_exprt::less_than(min_exprt(t), min_exprt(t))); + REQUIRE_FALSE( + constant_interval_exprt::less_than(max_exprt(t), min_exprt(t))); + REQUIRE_FALSE( + constant_interval_exprt::less_than(max_exprt(t), max_exprt(t))); + REQUIRE(constant_interval_exprt::less_than(min_exprt(t), max_exprt(t))); + + REQUIRE(constant_interval_exprt::equal(min_exprt(t), min_exprt(t))); + REQUIRE(constant_interval_exprt::not_equal(max_exprt(t), min_exprt(t))); + REQUIRE(constant_interval_exprt::equal(max_exprt(t), max_exprt(t))); + REQUIRE(constant_interval_exprt::not_equal(min_exprt(t), max_exprt(t))); } THEN("") { - REQUIRE_FALSE(interval_exprt::greater_than(v[0], v[1])); - REQUIRE_FALSE(interval_exprt::greater_than(v[1], v[2])); - REQUIRE_FALSE(interval_exprt::greater_than(v[1], v[100])); - - REQUIRE_FALSE(interval_exprt::greater_than(v[-10], v[1])); - REQUIRE(interval_exprt::greater_than(v[-10], v[-100])); - REQUIRE_FALSE(interval_exprt::greater_than(v[-10], v[-5])); - REQUIRE_FALSE(interval_exprt::greater_than(v[-10], max_exprt(t))); - REQUIRE_FALSE(interval_exprt::greater_than(v[10], max_exprt(t))); - REQUIRE_FALSE(interval_exprt::greater_than(v[0], max_exprt(t))); - - REQUIRE(interval_exprt::greater_than(v[-10], min_exprt(t))); - REQUIRE(interval_exprt::greater_than(v[10], min_exprt(t))); - REQUIRE(interval_exprt::greater_than(v[0], min_exprt(t))); - - REQUIRE_FALSE(interval_exprt::greater_than(min_exprt(t), min_exprt(t))); - REQUIRE( - interval_exprt::greater_than_or_equal(min_exprt(t), min_exprt(t))); + REQUIRE_FALSE(constant_interval_exprt::greater_than(v[0], v[1])); + REQUIRE_FALSE(constant_interval_exprt::greater_than(v[1], v[2])); + REQUIRE_FALSE(constant_interval_exprt::greater_than(v[1], v[100])); + + REQUIRE_FALSE(constant_interval_exprt::greater_than(v[-10], v[1])); + REQUIRE(constant_interval_exprt::greater_than(v[-10], v[-100])); + REQUIRE_FALSE(constant_interval_exprt::greater_than(v[-10], v[-5])); + REQUIRE_FALSE( + constant_interval_exprt::greater_than(v[-10], max_exprt(t))); + REQUIRE_FALSE( + constant_interval_exprt::greater_than(v[10], max_exprt(t))); + REQUIRE_FALSE( + constant_interval_exprt::greater_than(v[0], max_exprt(t))); + + REQUIRE(constant_interval_exprt::greater_than(v[-10], min_exprt(t))); + REQUIRE(constant_interval_exprt::greater_than(v[10], min_exprt(t))); + REQUIRE(constant_interval_exprt::greater_than(v[0], min_exprt(t))); + + REQUIRE_FALSE( + constant_interval_exprt::greater_than(min_exprt(t), min_exprt(t))); + REQUIRE(constant_interval_exprt::greater_than_or_equal( + min_exprt(t), min_exprt(t))); - REQUIRE(interval_exprt::greater_than(max_exprt(t), min_exprt(t))); REQUIRE( - interval_exprt::greater_than_or_equal(max_exprt(t), min_exprt(t))); + constant_interval_exprt::greater_than(max_exprt(t), min_exprt(t))); + REQUIRE(constant_interval_exprt::greater_than_or_equal( + max_exprt(t), min_exprt(t))); - REQUIRE_FALSE(interval_exprt::greater_than(max_exprt(t), max_exprt(t))); + REQUIRE_FALSE( + constant_interval_exprt::greater_than(max_exprt(t), max_exprt(t))); - REQUIRE_FALSE(interval_exprt::greater_than(min_exprt(t), max_exprt(t))); + REQUIRE_FALSE( + constant_interval_exprt::greater_than(min_exprt(t), max_exprt(t))); } } @@ -98,11 +108,15 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") { THEN("Require correctness") { - CHECK(interval_exprt(v[10], v[20]) < interval_exprt(v[30], v[40])); + CHECK( + constant_interval_exprt(v[10], v[20]) < + constant_interval_exprt(v[30], v[40])); REQUIRE_FALSE( - interval_exprt(v[10], v[30]) < interval_exprt(v[30], v[40])); + constant_interval_exprt(v[10], v[30]) < + constant_interval_exprt(v[30], v[40])); REQUIRE_FALSE( - interval_exprt(v[10], v[20]) > interval_exprt(v[30], v[40])); + constant_interval_exprt(v[10], v[20]) > + constant_interval_exprt(v[30], v[40])); } THEN( @@ -110,18 +124,20 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") "< [30, 40] == unknown") { CHECK( - interval_exprt(v[10], v[29]) - .less_than(interval_exprt(v[30], v[40])) == tvt(true)); + constant_interval_exprt(v[10], v[29]) + .less_than(constant_interval_exprt(v[30], v[40])) == tvt(true)); CHECK( - interval_exprt(v[10], v[30]) - .less_than(interval_exprt(v[30], v[40])) == tvt::unknown()); + constant_interval_exprt(v[10], v[30]) + .less_than(constant_interval_exprt(v[30], v[40])) == + tvt::unknown()); CHECK( - interval_exprt(v[10], v[31]) - .less_than(interval_exprt(v[30], v[40])) == tvt::unknown()); + constant_interval_exprt(v[10], v[31]) + .less_than(constant_interval_exprt(v[30], v[40])) == + tvt::unknown()); CHECK( - interval_exprt(v[30], v[40]) - .less_than(interval_exprt(v[10], v[29])) == tvt(false)); + constant_interval_exprt(v[30], v[40]) + .less_than(constant_interval_exprt(v[10], v[29])) == tvt(false)); } THEN( @@ -129,19 +145,22 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") "31] > [30, 40] == unknown") { CHECK( - interval_exprt(v[10], v[29]) - .greater_than(interval_exprt(v[30], v[40])) == tvt(false)); + constant_interval_exprt(v[10], v[29]) + .greater_than(constant_interval_exprt(v[30], v[40])) == tvt(false)); CHECK( - interval_exprt(v[10], v[29]) - .greater_than(interval_exprt(v[30], v[40])) == - interval_exprt(v[30], v[40]).less_than(interval_exprt(v[10], v[29]))); + constant_interval_exprt(v[10], v[29]) + .greater_than(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(v[30], v[40]) + .less_than(constant_interval_exprt(v[10], v[29]))); CHECK( - interval_exprt(v[10], v[30]) - .greater_than(interval_exprt(v[30], v[40])) == tvt::unknown()); + constant_interval_exprt(v[10], v[30]) + .greater_than(constant_interval_exprt(v[30], v[40])) == + tvt::unknown()); CHECK( - interval_exprt(v[10], v[31]) - .greater_than(interval_exprt(v[30], v[40])) == tvt::unknown()); + constant_interval_exprt(v[10], v[31]) + .greater_than(constant_interval_exprt(v[30], v[40])) == + tvt::unknown()); } THEN( @@ -149,14 +168,16 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") "<- [30, 40] == unknown") { CHECK( - interval_exprt(v[10], v[29]) - .less_than_or_equal(interval_exprt(v[30], v[40])) == tvt(true)); + constant_interval_exprt(v[10], v[29]) + .less_than_or_equal(constant_interval_exprt(v[30], v[40])) == + tvt(true)); CHECK( - interval_exprt(v[10], v[30]) - .less_than_or_equal(interval_exprt(v[30], v[40])) == tvt(true)); + constant_interval_exprt(v[10], v[30]) + .less_than_or_equal(constant_interval_exprt(v[30], v[40])) == + tvt(true)); CHECK( - interval_exprt(v[10], v[31]) - .less_than_or_equal(interval_exprt(v[30], v[40])) == + constant_interval_exprt(v[10], v[31]) + .less_than_or_equal(constant_interval_exprt(v[30], v[40])) == tvt::unknown()); } @@ -165,15 +186,16 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") "31] >= [30, 40] == unknown") { CHECK( - interval_exprt(v[10], v[29]) - .greater_than_or_equal(interval_exprt(v[30], v[40])) == tvt(false)); + constant_interval_exprt(v[10], v[29]) + .greater_than_or_equal(constant_interval_exprt(v[30], v[40])) == + tvt(false)); CHECK( - interval_exprt(v[10], v[30]) - .greater_than_or_equal(interval_exprt(v[30], v[40])) == + constant_interval_exprt(v[10], v[30]) + .greater_than_or_equal(constant_interval_exprt(v[30], v[40])) == tvt::unknown()); CHECK( - interval_exprt(v[10], v[31]) - .greater_than_or_equal(interval_exprt(v[30], v[40])) == + constant_interval_exprt(v[10], v[31]) + .greater_than_or_equal(constant_interval_exprt(v[30], v[40])) == tvt::unknown()); } } diff --git a/unit/util/interval/get_extreme.cpp b/unit/util/interval/get_extreme.cpp index d36516cfa9e..e10b8cfc5db 100644 --- a/unit/util/interval/get_extreme.cpp +++ b/unit/util/interval/get_extreme.cpp @@ -3,10 +3,10 @@ Author: DiffBlue Limited. All rights reserved. \*******************************************************************/ -#include +#include -#include #include +#include #include #include #include @@ -38,7 +38,7 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") { binary_predicate_exprt op1(values[-20], ID_le, values[20]); bool interval_eval = - interval_exprt::less_than_or_equal(values[-20], values[20]); + constant_interval_exprt::less_than_or_equal(values[-20], values[20]); simplify(op1, ns); THEN("Require it is TRUE") @@ -52,7 +52,7 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") { binary_predicate_exprt op1(values[20], ID_le, values[-20]); bool interval_eval = - interval_exprt::less_than_or_equal(values[20], values[-20]); + constant_interval_exprt::less_than_or_equal(values[20], values[-20]); simplify(op1, ns); THEN("Require it is FALSE") @@ -66,7 +66,7 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") { binary_predicate_exprt op1(values[-20], ID_le, values[-20]); bool interval_eval = - interval_exprt::less_than_or_equal(values[-20], values[-20]); + constant_interval_exprt::less_than_or_equal(values[-20], values[-20]); simplify(op1, ns); @@ -74,7 +74,7 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") { REQUIRE(op1.is_true()); REQUIRE(interval_eval); - REQUIRE(interval_exprt::equal(values[1], values[1])); + REQUIRE(constant_interval_exprt::equal(values[1], values[1])); } } @@ -82,8 +82,8 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") { std::vector selected = {values[20], values[-20]}; - exprt min = interval_exprt::get_extreme(selected, true); - exprt max = interval_exprt::get_extreme(selected, false); + exprt min = constant_interval_exprt::get_extreme(selected, true); + exprt max = constant_interval_exprt::get_extreme(selected, false); THEN("Min (-20) and max (20) are verified") { @@ -99,8 +99,8 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") std::vector selected = { values[-20], values[0], values[50], values[20]}; - exprt min = interval_exprt::get_extreme(selected, true); - exprt max = interval_exprt::get_extreme(selected, false); + exprt min = constant_interval_exprt::get_extreme(selected, true); + exprt max = constant_interval_exprt::get_extreme(selected, false); THEN("Min (-20) and max (50) are verified") { @@ -113,8 +113,8 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") { std::vector selected = {values[-100]}; - exprt min = interval_exprt::get_extreme(selected, true); - exprt max = interval_exprt::get_extreme(selected, false); + exprt min = constant_interval_exprt::get_extreme(selected, true); + exprt max = constant_interval_exprt::get_extreme(selected, false); THEN("Max (-100) and min (-100) are verified") { @@ -128,8 +128,8 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") std::vector selected = { values[20], values[30], values[15], values[0], values[-100]}; - exprt min = interval_exprt::get_extreme(selected, true); - exprt max = interval_exprt::get_extreme(selected, false); + exprt min = constant_interval_exprt::get_extreme(selected, true); + exprt max = constant_interval_exprt::get_extreme(selected, false); THEN("Max (30) and min (-100) are verified") { @@ -140,8 +140,8 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") WHEN("All from [-100:100] are selected") { - exprt min = interval_exprt::get_extreme(ve, true); - exprt max = interval_exprt::get_extreme(ve, false); + exprt min = constant_interval_exprt::get_extreme(ve, true); + exprt max = constant_interval_exprt::get_extreme(ve, false); THEN("Max (100) and min (-100) are verified") { @@ -154,8 +154,8 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") { std::random_shuffle(ve.begin(), ve.end()); - exprt min = interval_exprt::get_extreme(ve, true); - exprt max = interval_exprt::get_extreme(ve, false); + exprt min = constant_interval_exprt::get_extreme(ve, true); + exprt max = constant_interval_exprt::get_extreme(ve, false); THEN("Max (100) and min (-100) are verified") { diff --git a/unit/util/interval/modulo.cpp b/unit/util/interval/modulo.cpp index bedace39767..68996c84e34 100644 --- a/unit/util/interval/modulo.cpp +++ b/unit/util/interval/modulo.cpp @@ -3,10 +3,10 @@ Author: DiffBlue Limited. All rights reserved. \*******************************************************************/ -#include +#include -#include #include +#include #include #include #include @@ -36,37 +36,46 @@ SCENARIO("modulo interval domain", "[core][analyses][interval][modulo]") THEN("Ensure result is consistent.") { REQUIRE( - interval_exprt(v[10], v[20]).modulo(interval_exprt(v[5], v[5])) == - interval_exprt(v[0], v[4])); + constant_interval_exprt(v[10], v[20]) + .modulo(constant_interval_exprt(v[5], v[5])) == + constant_interval_exprt(v[0], v[4])); REQUIRE( - interval_exprt(v[10], v[20]).modulo(interval_exprt(v[4], v[5])) == - interval_exprt(v[0], v[4])); + constant_interval_exprt(v[10], v[20]) + .modulo(constant_interval_exprt(v[4], v[5])) == + constant_interval_exprt(v[0], v[4])); REQUIRE( - interval_exprt(v[10], v[20]).modulo(interval_exprt(v[0], v[5])) == - interval_exprt::top(type)); + constant_interval_exprt(v[10], v[20]) + .modulo(constant_interval_exprt(v[0], v[5])) == + constant_interval_exprt::top(type)); REQUIRE( - interval_exprt(v[10], v[20]).modulo(interval_exprt(v[-5], v[5])) == - interval_exprt::top(type)); + constant_interval_exprt(v[10], v[20]) + .modulo(constant_interval_exprt(v[-5], v[5])) == + constant_interval_exprt::top(type)); REQUIRE( - interval_exprt(v[-10], v[20]).modulo(interval_exprt(v[0], v[5])) == - interval_exprt::top(type)); + constant_interval_exprt(v[-10], v[20]) + .modulo(constant_interval_exprt(v[0], v[5])) == + constant_interval_exprt::top(type)); REQUIRE( - interval_exprt(v[-20], v[-10]).modulo(interval_exprt(v[0], v[5])) == - interval_exprt::top(type)); + constant_interval_exprt(v[-20], v[-10]) + .modulo(constant_interval_exprt(v[0], v[5])) == + constant_interval_exprt::top(type)); REQUIRE( - interval_exprt(v[-20], v[-10]).modulo(interval_exprt(v[1], v[1])) == - interval_exprt(v[0])); + constant_interval_exprt(v[-20], v[-10]) + .modulo(constant_interval_exprt(v[1], v[1])) == + constant_interval_exprt(v[0])); REQUIRE( - interval_exprt(v[30], v[50]).modulo(interval_exprt(v[2], v[2])) == - interval_exprt(v[0], v[1])); + constant_interval_exprt(v[30], v[50]) + .modulo(constant_interval_exprt(v[2], v[2])) == + constant_interval_exprt(v[0], v[1])); // Problems REQUIRE( - interval_exprt(v[30], max_exprt(type)) - .modulo(interval_exprt(v[2], v[2])) == interval_exprt(v[0], v[1])); + constant_interval_exprt(v[30], max_exprt(type)) + .modulo(constant_interval_exprt(v[2], v[2])) == + constant_interval_exprt(v[0], v[1])); } } } diff --git a/unit/util/interval/multiply.cpp b/unit/util/interval/multiply.cpp index 4566f949ee4..b40e60d3b9a 100644 --- a/unit/util/interval/multiply.cpp +++ b/unit/util/interval/multiply.cpp @@ -3,10 +3,10 @@ Author: DiffBlue Limited. All rights reserved. \*******************************************************************/ -#include +#include -#include #include +#include #include #include #include @@ -33,10 +33,10 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") WHEN("Both are positive [2,5]*[7,11]") { - interval_exprt a(values[2], values[5]); - interval_exprt b(values[7], values[11]); + constant_interval_exprt a(values[2], values[5]); + constant_interval_exprt b(values[7], values[11]); - interval_exprt result = a.multiply(b); + constant_interval_exprt result = a.multiply(b); THEN("Domain is consistent") { @@ -57,10 +57,10 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") WHEN("One is entirely negative [-2,-5]*[7,11]") { - interval_exprt a(values[-2], values[-5]); - interval_exprt b(values[7], values[11]); + constant_interval_exprt a(values[-2], values[-5]); + constant_interval_exprt b(values[7], values[11]); - interval_exprt result = a.multiply(b); + constant_interval_exprt result = a.multiply(b); THEN("Domain is consistent") { @@ -81,10 +81,10 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") WHEN("Range contains and extends from zero [-2,5]*[7,11]") { - interval_exprt a(values[-2], values[5]); - interval_exprt b(values[7], values[11]); + constant_interval_exprt a(values[-2], values[5]); + constant_interval_exprt b(values[7], values[11]); - interval_exprt result = a.multiply(b); + constant_interval_exprt result = a.multiply(b); THEN("Domain is consistent") { @@ -105,33 +105,33 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") WHEN("One domain is infinite and other crosses zero [-2,5]*[7,INF]") { - interval_exprt a(values[-2], values[5]); - interval_exprt b(values[7], max_exprt(type)); + constant_interval_exprt a(values[-2], values[5]); + constant_interval_exprt b(values[7], max_exprt(type)); - interval_exprt result = a.multiply(b); + constant_interval_exprt result = a.multiply(b); THEN("Domain is consistent") { CHECK(V(a.get_lower()) == -2); CHECK(V(a.get_upper()) == 5); CHECK(V(b.get_lower()) == 7); - CHECK(interval_exprt::is_max(b.get_upper())); + CHECK(constant_interval_exprt::is_max(b.get_upper())); } CAPTURE(result); THEN("The result is [-INF, INF]") { - CHECK(interval_exprt::is_max(result.get_upper())); - CHECK(interval_exprt::is_min(result.get_lower())); + CHECK(constant_interval_exprt::is_max(result.get_upper())); + CHECK(constant_interval_exprt::is_min(result.get_lower())); } } WHEN("One domain is infinite and other is positive [2,5]*[7,INF]") { - interval_exprt a(values[2], values[5]); - interval_exprt b(values[7], max_exprt(type)); - interval_exprt result = a.multiply(b); + constant_interval_exprt a(values[2], values[5]); + constant_interval_exprt b(values[7], max_exprt(type)); + constant_interval_exprt result = a.multiply(b); THEN("Domain is consistent") { diff --git a/unit/util/interval/shift.cpp b/unit/util/interval/shift.cpp index 5ff8f37ee88..2eb3cea1622 100644 --- a/unit/util/interval/shift.cpp +++ b/unit/util/interval/shift.cpp @@ -3,10 +3,10 @@ Author: DiffBlue Limited. All rights reserved. \*******************************************************************/ -#include +#include -#include #include +#include #include #include #include @@ -36,8 +36,9 @@ SCENARIO("shift interval domain", "[core][analyses][interval][shift]") THEN("Something else") { REQUIRE( - interval_exprt(v[4], v[8]).left_shift(interval_exprt(v[1])) == - interval_exprt(v[8], v[16])); + constant_interval_exprt(v[4], v[8]) + .left_shift(constant_interval_exprt(v[1])) == + constant_interval_exprt(v[8], v[16])); } } } diff --git a/unit/util/interval/subtract.cpp b/unit/util/interval/subtract.cpp index c29b79c1d75..01f3872576e 100644 --- a/unit/util/interval/subtract.cpp +++ b/unit/util/interval/subtract.cpp @@ -3,10 +3,10 @@ Author: DiffBlue Limited. All rights reserved. \*******************************************************************/ -#include +#include -#include #include +#include #include #include #include @@ -33,10 +33,10 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") WHEN("The result is positive [6,8]-[2,4]") { - interval_exprt left(values[6], values[8]); - interval_exprt right(values[2], values[4]); + constant_interval_exprt left(values[6], values[8]); + constant_interval_exprt right(values[2], values[4]); - interval_exprt result = left.minus(right); + constant_interval_exprt result = left.minus(right); THEN("Domain is consistent") { @@ -55,10 +55,10 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") WHEN("One contains infinite [2,4]-[6,INF]") { - interval_exprt left(values[2], values[4]); - interval_exprt right(values[6], max_exprt(type)); + constant_interval_exprt left(values[2], values[4]); + constant_interval_exprt right(values[6], max_exprt(type)); - interval_exprt result = left.minus(right); + constant_interval_exprt result = left.minus(right); THEN("Domain is consistent") { @@ -79,10 +79,10 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") WHEN("Both contain infinite [2,INF]-[6,INF]") { - interval_exprt left(values[2], max_exprt(type)); - interval_exprt right(values[6], max_exprt(type)); + constant_interval_exprt left(values[2], max_exprt(type)); + constant_interval_exprt right(values[6], max_exprt(type)); - interval_exprt result = left.minus(right); + constant_interval_exprt result = left.minus(right); THEN("Domain is consistent") { From 4e2d044a5ecb69bf50699922e2e017e88967ac58 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 16 May 2018 12:23:56 +0100 Subject: [PATCH 03/59] (INT) Rename interval is_constant to is_single_value_interval As it stands in conflicted with the method from exprt --- src/util/interval.cpp | 41 +++++++++++++++++++++-------------------- src/util/interval.h | 4 ++-- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index b41d17625df..da88e4eab2c 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -41,7 +41,7 @@ const constant_interval_exprt constant_interval_exprt::unary_plus() const const constant_interval_exprt constant_interval_exprt::unary_minus() const { - if(is_constant()) + if(is_single_value_interval()) { handle_constants(unary_minus_exprt()); } @@ -73,7 +73,7 @@ const constant_interval_exprt constant_interval_exprt::unary_minus() const const constant_interval_exprt constant_interval_exprt::plus(const constant_interval_exprt &o) const { - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, plus_exprt()); } @@ -107,7 +107,7 @@ constant_interval_exprt::plus(const constant_interval_exprt &o) const const constant_interval_exprt constant_interval_exprt::minus(const constant_interval_exprt &o) const { - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, minus_exprt()); } @@ -119,7 +119,7 @@ constant_interval_exprt::minus(const constant_interval_exprt &o) const const constant_interval_exprt constant_interval_exprt::multiply(const constant_interval_exprt &o) const { - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, mult_exprt()); } @@ -132,7 +132,7 @@ constant_interval_exprt::multiply(const constant_interval_exprt &o) const const constant_interval_exprt constant_interval_exprt::divide(const constant_interval_exprt &o) const { - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, div_exprt()); } @@ -152,7 +152,7 @@ constant_interval_exprt::modulo(const constant_interval_exprt &o) const { // SEE https://stackoverflow.com/questions/11720656/modulo-operation-with-negative-numbers - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, mod_exprt()); } @@ -272,7 +272,7 @@ const tvt constant_interval_exprt::logical_not() const const constant_interval_exprt constant_interval_exprt::left_shift(const constant_interval_exprt &o) const { - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, shl_exprt()); } @@ -291,7 +291,7 @@ constant_interval_exprt::left_shift(const constant_interval_exprt &o) const const constant_interval_exprt constant_interval_exprt::right_shift(const constant_interval_exprt &o) const { - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, ashr_exprt()); } @@ -309,7 +309,7 @@ constant_interval_exprt::right_shift(const constant_interval_exprt &o) const const constant_interval_exprt constant_interval_exprt::bitwise_xor(const constant_interval_exprt &o) const { - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, bitxor_exprt()); } @@ -320,7 +320,7 @@ constant_interval_exprt::bitwise_xor(const constant_interval_exprt &o) const const constant_interval_exprt constant_interval_exprt::bitwise_or(const constant_interval_exprt &o) const { - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, bitor_exprt()); } @@ -331,7 +331,7 @@ constant_interval_exprt::bitwise_or(const constant_interval_exprt &o) const const constant_interval_exprt constant_interval_exprt::bitwise_and(const constant_interval_exprt &o) const { - if(o.is_constant() && is_constant()) + if(o.is_single_value_interval() && is_single_value_interval()) { handle_constants(o, bitand_exprt()); } @@ -341,7 +341,7 @@ constant_interval_exprt::bitwise_and(const constant_interval_exprt &o) const const constant_interval_exprt constant_interval_exprt::bitwise_not() const { - if(is_constant()) + if(is_single_value_interval()) { handle_constants(bitnot_exprt()); } @@ -352,7 +352,7 @@ const constant_interval_exprt constant_interval_exprt::bitwise_not() const tvt constant_interval_exprt::less_than(const constant_interval_exprt &o) const { // [get_lower, get_upper] < [o.get_lower(), o.get_upper()] - if(is_constant() && o.is_constant()) + if(is_single_value_interval() && o.is_single_value_interval()) { return tvt(less_than(get_lower(), o.get_lower())); } @@ -379,7 +379,7 @@ tvt constant_interval_exprt::greater_than( tvt constant_interval_exprt::less_than_or_equal( const constant_interval_exprt &o) const { - if(is_constant() && o.is_constant()) + if(is_single_value_interval() && o.is_single_value_interval()) { return tvt(less_than_or_equal(get_lower(), o.get_lower())); } @@ -406,7 +406,7 @@ tvt constant_interval_exprt::greater_than_or_equal( tvt constant_interval_exprt::equal(const constant_interval_exprt &o) const { - if(is_constant() && o.is_constant()) + if(is_single_value_interval() && o.is_single_value_interval()) { return tvt(equal(get_lower(), o.get_lower())); } @@ -974,7 +974,7 @@ exprt constant_interval_exprt::generate_shift_expression( const constant_interval_exprt constant_interval_exprt::handle_constants(exprt expr) const { - if(is_constant()) + if(is_single_value_interval()) { expr.type() = type(); expr.copy_to_operands(get_lower()); @@ -989,7 +989,7 @@ const constant_interval_exprt constant_interval_exprt::handle_constants( const constant_interval_exprt &o, exprt expr) const { - if(is_constant() && o.is_constant()) + if(is_single_value_interval() && o.is_single_value_interval()) { expr.type() = type(); expr.copy_to_operands(get_lower(), o.get_lower()); @@ -1826,9 +1826,10 @@ bool constant_interval_exprt::is_empty(const constant_interval_exprt &a) return a.is_empty(); } -bool constant_interval_exprt::is_constant(const constant_interval_exprt &a) +bool constant_interval_exprt::is_single_value_interval( + const constant_interval_exprt &a) { - return a.is_constant(); + return a.is_single_value_interval(); } bool constant_interval_exprt::is_top(const constant_interval_exprt &a) @@ -1886,7 +1887,7 @@ bool constant_interval_exprt::is_empty() const return true; } -bool constant_interval_exprt::is_constant() const +bool constant_interval_exprt::is_single_value_interval() const { return !is_extreme(get_lower()) && !is_extreme(get_upper()) && equal(get_lower(), get_upper()); diff --git a/src/util/interval.h b/src/util/interval.h index e48314e5c89..dff9ad75ddb 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -154,7 +154,7 @@ class constant_interval_exprt : public binary_exprt const constant_interval_exprt decrement() const; bool is_empty() const; - bool is_constant() const; + bool is_single_value_interval() const; /** END SET OF ARITHMETIC OPERATORS */ // tvt contains(constant_interval_exprt &o) const; @@ -308,7 +308,7 @@ class constant_interval_exprt : public binary_exprt decrement(const constant_interval_exprt &a); static bool is_empty(const constant_interval_exprt &a); - static bool is_constant(const constant_interval_exprt &a); + static bool is_single_value_interval(const constant_interval_exprt &a); static bool is_top(const constant_interval_exprt &a); static bool is_bottom(const constant_interval_exprt &a); From 3473ad180a1dafa425175bd2ad07d47e35a14fd8 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 16 May 2018 12:39:02 +0100 Subject: [PATCH 04/59] (INT) Rename is_true and is_false in interval expressions So they don't conflict with the exprt methods --- src/util/interval.cpp | 24 +++++++++++++----------- src/util/interval.h | 4 ++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index da88e4eab2c..4ea9a586004 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -211,13 +211,13 @@ constant_interval_exprt::modulo(const constant_interval_exprt &o) const return constant_interval_exprt(lower, upper); } -const tvt constant_interval_exprt::is_true() const +const tvt constant_interval_exprt::is_definitely_true() const { // tvt not - return !is_false(); + return !is_definitely_false(); } -const tvt constant_interval_exprt::is_false() const +const tvt constant_interval_exprt::is_definitely_false() const { if(equal(constant_interval_exprt(zero())).is_true()) { @@ -236,8 +236,8 @@ const tvt constant_interval_exprt::is_false() const const tvt constant_interval_exprt::logical_or(const constant_interval_exprt &o) const { - tvt a = is_true(); - tvt b = o.is_true(); + tvt a = is_definitely_true(); + tvt b = o.is_definitely_true(); return (a || b); } @@ -245,23 +245,25 @@ constant_interval_exprt::logical_or(const constant_interval_exprt &o) const const tvt constant_interval_exprt::logical_and(const constant_interval_exprt &o) const { - return (is_true() && o.is_true()); + return (is_definitely_true() && o.is_definitely_true()); } const tvt constant_interval_exprt::logical_xor(const constant_interval_exprt &o) const { - return ((is_true() && !o.is_true()) || (!is_true() && o.is_true())); + return ( + (is_definitely_true() && !o.is_definitely_true()) || + (!is_definitely_true() && o.is_definitely_true())); } const tvt constant_interval_exprt::logical_not() const { - if(is_true().is_true()) + if(is_definitely_true().is_true()) { return tvt(false); } - if(is_false().is_true()) + if(is_definitely_false().is_true()) { return tvt(true); } @@ -1960,12 +1962,12 @@ tv_to_interval(const constant_interval_exprt &interval, const tvt &tv) const tvt constant_interval_exprt::is_true(const constant_interval_exprt &a) { - return a.is_true(); + return a.is_definitely_true(); } const tvt constant_interval_exprt::is_false(const constant_interval_exprt &a) { - return a.is_false(); + return a.is_definitely_false(); } const tvt constant_interval_exprt::logical_and( diff --git a/src/util/interval.h b/src/util/interval.h index dff9ad75ddb..10343711d82 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -108,8 +108,8 @@ class constant_interval_exprt : public binary_exprt const constant_interval_exprt unary_minus() const; /* Logical */ - const tvt is_true() const; - const tvt is_false() const; + const tvt is_definitely_true() const; + const tvt is_definitely_false() const; const tvt logical_and(const constant_interval_exprt &o) const; const tvt logical_or(const constant_interval_exprt &o) const; From ab44ab109ab4039c87b883196f0b943cfc07a67a Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 16 May 2018 12:40:42 +0100 Subject: [PATCH 05/59] (INT) Make eval take an identifier instead of an exprt --- src/util/interval.cpp | 86 +++++++++++++++++++++---------------------- src/util/interval.h | 4 +- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 4ea9a586004..7b884c467cc 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -807,10 +807,8 @@ exprt constant_interval_exprt::generate_modulo_expression( return simplified_expr(operation); } -const constant_interval_exprt constant_interval_exprt::eval(const exprt &expr) +const constant_interval_exprt constant_interval_exprt::eval(const irep_idt &id) { - const irep_idt &id = expr.id(); - if(id == ID_unary_plus) { return unary_plus(); @@ -833,86 +831,84 @@ const constant_interval_exprt constant_interval_exprt::eval(const exprt &expr) } const constant_interval_exprt constant_interval_exprt::eval( - const exprt &expr, - const constant_interval_exprt &o) + const irep_idt &binary_operator, + const constant_interval_exprt &other) { - const irep_idt &id = expr.id(); - - if(id == ID_plus) + if(binary_operator == ID_plus) { - return plus(o); + return plus(other); } - if(id == ID_minus) + if(binary_operator == ID_minus) { - return unary_minus(o); + return unary_minus(other); } - if(id == ID_mult) + if(binary_operator == ID_mult) { - return multiply(o); + return multiply(other); } - if(id == ID_div) + if(binary_operator == ID_div) { - return divide(o); + return divide(other); } - if(id == ID_mod) + if(binary_operator == ID_mod) { - return modulo(o); + return modulo(other); } - if(id == ID_shl) + if(binary_operator == ID_shl) { - return left_shift(o); + return left_shift(other); } - if(id == ID_ashr) + if(binary_operator == ID_ashr) { - return right_shift(o); + return right_shift(other); } - if(id == ID_bitor) + if(binary_operator == ID_bitor) { - return bitwise_or(o); + return bitwise_or(other); } - if(id == ID_bitand) + if(binary_operator == ID_bitand) { - return bitwise_and(o); + return bitwise_and(other); } - if(id == ID_bitxor) + if(binary_operator == ID_bitxor) { - return bitwise_xor(o); + return bitwise_xor(other); } - if(id == ID_lt) + if(binary_operator == ID_lt) { - return tv_to_interval(less_than(o)); + return tv_to_interval(less_than(other)); } - if(id == ID_le) + if(binary_operator == ID_le) { - return tv_to_interval(less_than_or_equal(o)); + return tv_to_interval(less_than_or_equal(other)); } - if(id == ID_gt) + if(binary_operator == ID_gt) { - return tv_to_interval(greater_than(o)); + return tv_to_interval(greater_than(other)); } - if(id == ID_ge) + if(binary_operator == ID_ge) { - return tv_to_interval(greater_than_or_equal(o)); + return tv_to_interval(greater_than_or_equal(other)); } - if(id == ID_equal) + if(binary_operator == ID_equal) { - return tv_to_interval(equal(o)); + return tv_to_interval(equal(other)); } - if(id == ID_notequal) + if(binary_operator == ID_notequal) { - return tv_to_interval(not_equal(o)); + return tv_to_interval(not_equal(other)); } - if(id == ID_and) + if(binary_operator == ID_and) { - return tv_to_interval(logical_and(o)); + return tv_to_interval(logical_and(other)); } - if(id == ID_or) + if(binary_operator == ID_or) { - return tv_to_interval(logical_or(o)); + return tv_to_interval(logical_or(other)); } - if(id == ID_xor) + if(binary_operator == ID_xor) { - return tv_to_interval(logical_xor(o)); + return tv_to_interval(logical_xor(other)); } return top(); diff --git a/src/util/interval.h b/src/util/interval.h index 10343711d82..dc7365fff38 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -99,9 +99,9 @@ class constant_interval_exprt : public binary_exprt const constant_interval_exprt handle_constants(const constant_interval_exprt &o, exprt expr) const; - const constant_interval_exprt eval(const exprt &expr); + const constant_interval_exprt eval(const irep_idt &unary_operator); const constant_interval_exprt - eval(const exprt &expr, const constant_interval_exprt &o); + eval(const irep_idt &binary_operator, const constant_interval_exprt &o); /* Unary arithmetic */ const constant_interval_exprt unary_plus() const; From 1ba8004110e57283cf1dd3a6d1d9fcc63e344866 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 16 May 2018 12:42:46 +0100 Subject: [PATCH 06/59] (INT) Make constructors take constant references instead of values Also, mark them as explicit where appropriate and add some documentation --- src/util/interval.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/util/interval.h b/src/util/interval.h index dc7365fff38..c31ef06fe79 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -21,12 +21,7 @@ #include #include -/* - * - * Upper set = Specific max (otherwise INF) - * Lower set = Specific min (otherwise INF) - */ - +/// +∞ upper bound for intervals class max_exprt : public exprt { public: @@ -39,6 +34,7 @@ class max_exprt : public exprt } }; +/// -∞ upper bound for intervals class min_exprt : public exprt { public: @@ -51,13 +47,19 @@ class min_exprt : public exprt } }; +/// Represents an interval of values. +/// Bounds should be constant expressions +/// or min_exprt for the lower bound +/// or max_exprt for the upper bound +/// Also, lower bound should always be <= upper bound class constant_interval_exprt : public binary_exprt { public: - constant_interval_exprt(exprt lower, exprt upper, typet type) + constant_interval_exprt(const exprt &lower, const exprt &upper, typet type) : binary_exprt(lower, ID_constant_interval, upper, type) { - PRECONDITION(lower.type() == upper.type() && type == lower.type()); + PRECONDITION(type == upper.type()); + PRECONDITION(type == lower.type()); } constant_interval_exprt() @@ -73,7 +75,7 @@ class constant_interval_exprt : public binary_exprt { } - constant_interval_exprt(const typet type) + explicit constant_interval_exprt(const typet &type) : constant_interval_exprt(min_exprt(type), max_exprt(type), type) { } From 007c84d7f008a6f886f9ea4fde449e0c95a0c8e6 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 16 May 2018 14:07:45 +0100 Subject: [PATCH 07/59] (INT) Remove unnecessary constant specifier from value returning functions --- src/util/interval.cpp | 111 +++++++++++++++++++------------------- src/util/interval.h | 121 +++++++++++++++++++----------------------- 2 files changed, 109 insertions(+), 123 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 7b884c467cc..debabfcabf9 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -34,12 +34,12 @@ const exprt &constant_interval_exprt::get_upper() const //make clean -s && make -j 7 CXX="/usr/local/bin/ccache g++" -s && ./unit_tests -const constant_interval_exprt constant_interval_exprt::unary_plus() const +constant_interval_exprt constant_interval_exprt::unary_plus() const { return *this; } -const constant_interval_exprt constant_interval_exprt::unary_minus() const +constant_interval_exprt constant_interval_exprt::unary_minus() const { if(is_single_value_interval()) { @@ -70,7 +70,7 @@ const constant_interval_exprt constant_interval_exprt::unary_minus() const return constant_interval_exprt(lower, upper); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::plus(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) @@ -104,7 +104,7 @@ constant_interval_exprt::plus(const constant_interval_exprt &o) const return simplified_interval(lower, upper); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::minus(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) @@ -116,7 +116,7 @@ constant_interval_exprt::minus(const constant_interval_exprt &o) const return plus(o.unary_minus().swap()); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::multiply(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) @@ -129,7 +129,7 @@ constant_interval_exprt::multiply(const constant_interval_exprt &o) const return get_extremes(*this, o, operation); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::divide(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) @@ -147,7 +147,7 @@ constant_interval_exprt::divide(const constant_interval_exprt &o) const return get_extremes(*this, o, operation); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::modulo(const constant_interval_exprt &o) const { // SEE https://stackoverflow.com/questions/11720656/modulo-operation-with-negative-numbers @@ -211,13 +211,13 @@ constant_interval_exprt::modulo(const constant_interval_exprt &o) const return constant_interval_exprt(lower, upper); } -const tvt constant_interval_exprt::is_definitely_true() const +tvt constant_interval_exprt::is_definitely_true() const { // tvt not return !is_definitely_false(); } -const tvt constant_interval_exprt::is_definitely_false() const +tvt constant_interval_exprt::is_definitely_false() const { if(equal(constant_interval_exprt(zero())).is_true()) { @@ -233,8 +233,7 @@ const tvt constant_interval_exprt::is_definitely_false() const return tvt(false); } -const tvt -constant_interval_exprt::logical_or(const constant_interval_exprt &o) const +tvt constant_interval_exprt::logical_or(const constant_interval_exprt &o) const { tvt a = is_definitely_true(); tvt b = o.is_definitely_true(); @@ -242,21 +241,19 @@ constant_interval_exprt::logical_or(const constant_interval_exprt &o) const return (a || b); } -const tvt -constant_interval_exprt::logical_and(const constant_interval_exprt &o) const +tvt constant_interval_exprt::logical_and(const constant_interval_exprt &o) const { return (is_definitely_true() && o.is_definitely_true()); } -const tvt -constant_interval_exprt::logical_xor(const constant_interval_exprt &o) const +tvt constant_interval_exprt::logical_xor(const constant_interval_exprt &o) const { return ( (is_definitely_true() && !o.is_definitely_true()) || (!is_definitely_true() && o.is_definitely_true())); } -const tvt constant_interval_exprt::logical_not() const +tvt constant_interval_exprt::logical_not() const { if(is_definitely_true().is_true()) { @@ -271,7 +268,7 @@ const tvt constant_interval_exprt::logical_not() const return tvt::unknown(); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::left_shift(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) @@ -290,7 +287,7 @@ constant_interval_exprt::left_shift(const constant_interval_exprt &o) const } // Arithmetic -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::right_shift(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) @@ -308,7 +305,7 @@ constant_interval_exprt::right_shift(const constant_interval_exprt &o) const return get_extremes(*this, o, operation); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::bitwise_xor(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) @@ -319,7 +316,7 @@ constant_interval_exprt::bitwise_xor(const constant_interval_exprt &o) const return top(); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::bitwise_or(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) @@ -330,7 +327,7 @@ constant_interval_exprt::bitwise_or(const constant_interval_exprt &o) const return top(); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::bitwise_and(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) @@ -341,7 +338,7 @@ constant_interval_exprt::bitwise_and(const constant_interval_exprt &o) const return top(); } -const constant_interval_exprt constant_interval_exprt::bitwise_not() const +constant_interval_exprt constant_interval_exprt::bitwise_not() const { if(is_single_value_interval()) { @@ -434,17 +431,17 @@ tvt constant_interval_exprt::not_equal(const constant_interval_exprt &o) const return !equal(o); } -const constant_interval_exprt constant_interval_exprt::increment() const +constant_interval_exprt constant_interval_exprt::increment() const { return plus(constant_interval_exprt(from_integer(mp_integer(1), type()))); } -const constant_interval_exprt constant_interval_exprt::decrement() const +constant_interval_exprt constant_interval_exprt::decrement() const { return minus(constant_interval_exprt(from_integer(mp_integer(1), type()))); } -const constant_interval_exprt constant_interval_exprt::get_extremes( +constant_interval_exprt constant_interval_exprt::get_extremes( const constant_interval_exprt &a, const constant_interval_exprt &b, const exprt operation) @@ -807,7 +804,7 @@ exprt constant_interval_exprt::generate_modulo_expression( return simplified_expr(operation); } -const constant_interval_exprt constant_interval_exprt::eval(const irep_idt &id) +constant_interval_exprt constant_interval_exprt::eval(const irep_idt &id) { if(id == ID_unary_plus) { @@ -830,7 +827,7 @@ const constant_interval_exprt constant_interval_exprt::eval(const irep_idt &id) return top(); } -const constant_interval_exprt constant_interval_exprt::eval( +constant_interval_exprt constant_interval_exprt::eval( const irep_idt &binary_operator, const constant_interval_exprt &other) { @@ -914,7 +911,7 @@ const constant_interval_exprt constant_interval_exprt::eval( return top(); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::tv_to_interval(const tvt &tv) const { if(tv.is_true()) @@ -969,7 +966,7 @@ exprt constant_interval_exprt::generate_shift_expression( return simplified_expr(operation); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::handle_constants(exprt expr) const { if(is_single_value_interval()) @@ -983,7 +980,7 @@ constant_interval_exprt::handle_constants(exprt expr) const return top(); } -const constant_interval_exprt constant_interval_exprt::handle_constants( +constant_interval_exprt constant_interval_exprt::handle_constants( const constant_interval_exprt &o, exprt expr) const { @@ -1018,7 +1015,7 @@ exprt constant_interval_exprt::get_max(std::vector &values) } /* we don't simplify in the constructor otherwise */ -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::simplified_interval(exprt &l, exprt &r) { return constant_interval_exprt(simplified_expr(l), simplified_expr(r)); @@ -1078,27 +1075,27 @@ bool constant_interval_exprt::is_bottom() const return is_min(get_upper()) || is_max(get_lower()); } -const constant_interval_exprt constant_interval_exprt::top(const typet &type) +constant_interval_exprt constant_interval_exprt::top(const typet &type) { return constant_interval_exprt(type); } -const constant_interval_exprt constant_interval_exprt::bottom(const typet &type) +constant_interval_exprt constant_interval_exprt::bottom(const typet &type) { return constant_interval_exprt(max_exprt(type), min_exprt(type)); } -const constant_interval_exprt constant_interval_exprt::top() const +constant_interval_exprt constant_interval_exprt::top() const { return constant_interval_exprt(type()); } -const constant_interval_exprt constant_interval_exprt::bottom() const +constant_interval_exprt constant_interval_exprt::bottom() const { return bottom(type()); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::swap(constant_interval_exprt &i) { return constant_interval_exprt(i.get_upper(), i.get_lower()); @@ -1673,48 +1670,48 @@ const constant_interval_exprt operator>>( return lhs.right_shift(rhs); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::unary_plus(const constant_interval_exprt &a) { return a.unary_plus(); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::unary_minus(const constant_interval_exprt &a) { return a.unary_minus(); } /* Binary */ -const constant_interval_exprt constant_interval_exprt::plus( +constant_interval_exprt constant_interval_exprt::plus( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.plus(b); } -const constant_interval_exprt constant_interval_exprt::minus( +constant_interval_exprt constant_interval_exprt::minus( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.minus(b); } -const constant_interval_exprt constant_interval_exprt::multiply( +constant_interval_exprt constant_interval_exprt::multiply( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.multiply(b); } -const constant_interval_exprt constant_interval_exprt::divide( +constant_interval_exprt constant_interval_exprt::divide( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.divide(b); } -const constant_interval_exprt constant_interval_exprt::modulo( +constant_interval_exprt constant_interval_exprt::modulo( const constant_interval_exprt &a, const constant_interval_exprt &b) { @@ -1722,14 +1719,14 @@ const constant_interval_exprt constant_interval_exprt::modulo( } /* Binary shifts */ -const constant_interval_exprt constant_interval_exprt::left_shift( +constant_interval_exprt constant_interval_exprt::left_shift( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.left_shift(b); } -const constant_interval_exprt constant_interval_exprt::right_shift( +constant_interval_exprt constant_interval_exprt::right_shift( const constant_interval_exprt &a, const constant_interval_exprt &b) { @@ -1737,28 +1734,28 @@ const constant_interval_exprt constant_interval_exprt::right_shift( } /* Unary bitwise */ -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::bitwise_not(const constant_interval_exprt &a) { return a.bitwise_not(); } /* Binary bitwise */ -const constant_interval_exprt constant_interval_exprt::bitwise_xor( +constant_interval_exprt constant_interval_exprt::bitwise_xor( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.bitwise_xor(b); } -const constant_interval_exprt constant_interval_exprt::bitwise_or( +constant_interval_exprt constant_interval_exprt::bitwise_or( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.bitwise_or(b); } -const constant_interval_exprt constant_interval_exprt::bitwise_and( +constant_interval_exprt constant_interval_exprt::bitwise_and( const constant_interval_exprt &a, const constant_interval_exprt &b) { @@ -1807,13 +1804,13 @@ tvt constant_interval_exprt::not_equal( return a.equal(b); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::increment(const constant_interval_exprt &a) { return a.increment(); } -const constant_interval_exprt +constant_interval_exprt constant_interval_exprt::decrement(const constant_interval_exprt &a) { return a.decrement(); @@ -1956,38 +1953,38 @@ tv_to_interval(const constant_interval_exprt &interval, const tvt &tv) return interval.tv_to_interval(tv); } -const tvt constant_interval_exprt::is_true(const constant_interval_exprt &a) +tvt constant_interval_exprt::is_true(const constant_interval_exprt &a) { return a.is_definitely_true(); } -const tvt constant_interval_exprt::is_false(const constant_interval_exprt &a) +tvt constant_interval_exprt::is_false(const constant_interval_exprt &a) { return a.is_definitely_false(); } -const tvt constant_interval_exprt::logical_and( +tvt constant_interval_exprt::logical_and( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.logical_and(b); } -const tvt constant_interval_exprt::logical_or( +tvt constant_interval_exprt::logical_or( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.logical_or(b); } -const tvt constant_interval_exprt::logical_xor( +tvt constant_interval_exprt::logical_xor( const constant_interval_exprt &a, const constant_interval_exprt &b) { return a.logical_xor(b); } -const tvt constant_interval_exprt::logical_not(const constant_interval_exprt &a) +tvt constant_interval_exprt::logical_not(const constant_interval_exprt &a) { return a.logical_not(); } diff --git a/src/util/interval.h b/src/util/interval.h index c31ef06fe79..6405c2cd05d 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -97,53 +97,47 @@ class constant_interval_exprt : public binary_exprt const exprt &get_upper() const; /** SET OF ARITHMETIC OPERATORS */ - const constant_interval_exprt handle_constants(exprt expr) const; - const constant_interval_exprt + constant_interval_exprt handle_constants(exprt expr) const; + constant_interval_exprt handle_constants(const constant_interval_exprt &o, exprt expr) const; - const constant_interval_exprt eval(const irep_idt &unary_operator); - const constant_interval_exprt + constant_interval_exprt eval(const irep_idt &unary_operator); + constant_interval_exprt eval(const irep_idt &binary_operator, const constant_interval_exprt &o); /* Unary arithmetic */ - const constant_interval_exprt unary_plus() const; - const constant_interval_exprt unary_minus() const; + constant_interval_exprt unary_plus() const; + constant_interval_exprt unary_minus() const; /* Logical */ - const tvt is_definitely_true() const; - const tvt is_definitely_false() const; + tvt is_definitely_true() const; + tvt is_definitely_false() const; - const tvt logical_and(const constant_interval_exprt &o) const; - const tvt logical_or(const constant_interval_exprt &o) const; - const tvt logical_xor(const constant_interval_exprt &o) const; - const tvt logical_not() const; + tvt logical_and(const constant_interval_exprt &o) const; + tvt logical_or(const constant_interval_exprt &o) const; + tvt logical_xor(const constant_interval_exprt &o) const; + tvt logical_not() const; - const constant_interval_exprt tv_to_interval(const tvt &tv) const; + constant_interval_exprt tv_to_interval(const tvt &tv) const; /* Binary */ - const constant_interval_exprt plus(const constant_interval_exprt &o) const; - const constant_interval_exprt minus(const constant_interval_exprt &o) const; - const constant_interval_exprt - multiply(const constant_interval_exprt &o) const; - const constant_interval_exprt divide(const constant_interval_exprt &o) const; - const constant_interval_exprt modulo(const constant_interval_exprt &o) const; + constant_interval_exprt plus(const constant_interval_exprt &o) const; + constant_interval_exprt minus(const constant_interval_exprt &o) const; + constant_interval_exprt multiply(const constant_interval_exprt &o) const; + constant_interval_exprt divide(const constant_interval_exprt &o) const; + constant_interval_exprt modulo(const constant_interval_exprt &o) const; /* Binary shifts */ - const constant_interval_exprt - left_shift(const constant_interval_exprt &o) const; - const constant_interval_exprt - right_shift(const constant_interval_exprt &o) const; + constant_interval_exprt left_shift(const constant_interval_exprt &o) const; + constant_interval_exprt right_shift(const constant_interval_exprt &o) const; /* Unary bitwise */ - const constant_interval_exprt bitwise_not() const; + constant_interval_exprt bitwise_not() const; /* Binary bitwise */ - const constant_interval_exprt - bitwise_xor(const constant_interval_exprt &o) const; - const constant_interval_exprt - bitwise_or(const constant_interval_exprt &o) const; - const constant_interval_exprt - bitwise_and(const constant_interval_exprt &o) const; + constant_interval_exprt bitwise_xor(const constant_interval_exprt &o) const; + constant_interval_exprt bitwise_or(const constant_interval_exprt &o) const; + constant_interval_exprt bitwise_and(const constant_interval_exprt &o) const; tvt less_than(const constant_interval_exprt &o) const; tvt greater_than(const constant_interval_exprt &o) const; @@ -152,8 +146,8 @@ class constant_interval_exprt : public binary_exprt tvt equal(const constant_interval_exprt &o) const; tvt not_equal(const constant_interval_exprt &o) const; - const constant_interval_exprt increment() const; - const constant_interval_exprt decrement() const; + constant_interval_exprt increment() const; + constant_interval_exprt decrement() const; bool is_empty() const; bool is_single_value_interval() const; @@ -231,60 +225,57 @@ class constant_interval_exprt : public binary_exprt std::string to_string() const; /* Now static equivalents! */ - static const tvt is_true(const constant_interval_exprt &a); - static const tvt is_false(const constant_interval_exprt &a); + static tvt is_true(const constant_interval_exprt &a); + static tvt is_false(const constant_interval_exprt &a); - static const tvt logical_and( + static tvt logical_and( const constant_interval_exprt &a, const constant_interval_exprt &b); - static const tvt logical_or( + static tvt logical_or( const constant_interval_exprt &a, const constant_interval_exprt &b); - static const tvt logical_xor( + static tvt logical_xor( const constant_interval_exprt &a, const constant_interval_exprt &b); - static const tvt logical_not(const constant_interval_exprt &a); + static tvt logical_not(const constant_interval_exprt &a); - static const constant_interval_exprt + static constant_interval_exprt tv_to_interval(const constant_interval_exprt &interval, const tvt &tv); - static const constant_interval_exprt - unary_plus(const constant_interval_exprt &a); - static const constant_interval_exprt - unary_minus(const constant_interval_exprt &a); + static constant_interval_exprt unary_plus(const constant_interval_exprt &a); + static constant_interval_exprt unary_minus(const constant_interval_exprt &a); /* Binary */ - static const constant_interval_exprt + static constant_interval_exprt plus(const constant_interval_exprt &a, const constant_interval_exprt &b); - static const constant_interval_exprt + static constant_interval_exprt minus(const constant_interval_exprt &a, const constant_interval_exprt &b); - static const constant_interval_exprt + static constant_interval_exprt multiply(const constant_interval_exprt &a, const constant_interval_exprt &b); - static const constant_interval_exprt + static constant_interval_exprt divide(const constant_interval_exprt &a, const constant_interval_exprt &b); - static const constant_interval_exprt + static constant_interval_exprt modulo(const constant_interval_exprt &a, const constant_interval_exprt &b); /* Binary shifts */ - static const constant_interval_exprt left_shift( + static constant_interval_exprt left_shift( const constant_interval_exprt &a, const constant_interval_exprt &b); - static const constant_interval_exprt right_shift( + static constant_interval_exprt right_shift( const constant_interval_exprt &a, const constant_interval_exprt &b); /* Unary bitwise */ - static const constant_interval_exprt - bitwise_not(const constant_interval_exprt &a); + static constant_interval_exprt bitwise_not(const constant_interval_exprt &a); /* Binary bitwise */ - static const constant_interval_exprt bitwise_xor( + static constant_interval_exprt bitwise_xor( const constant_interval_exprt &a, const constant_interval_exprt &b); - static const constant_interval_exprt bitwise_or( + static constant_interval_exprt bitwise_or( const constant_interval_exprt &a, const constant_interval_exprt &b); - static const constant_interval_exprt bitwise_and( + static constant_interval_exprt bitwise_and( const constant_interval_exprt &a, const constant_interval_exprt &b); @@ -304,10 +295,8 @@ class constant_interval_exprt : public binary_exprt static tvt not_equal(const constant_interval_exprt &a, const constant_interval_exprt &b); - static const constant_interval_exprt - increment(const constant_interval_exprt &a); - static const constant_interval_exprt - decrement(const constant_interval_exprt &a); + static constant_interval_exprt increment(const constant_interval_exprt &a); + static constant_interval_exprt decrement(const constant_interval_exprt &a); static bool is_empty(const constant_interval_exprt &a); static bool is_single_value_interval(const constant_interval_exprt &a); @@ -321,10 +310,10 @@ class constant_interval_exprt : public binary_exprt bool is_top() const; bool is_bottom() const; - static const constant_interval_exprt top(const typet &type); - static const constant_interval_exprt bottom(const typet &type); - const constant_interval_exprt top() const; - const constant_interval_exprt bottom() const; + static constant_interval_exprt top(const typet &type); + static constant_interval_exprt bottom(const typet &type); + constant_interval_exprt top() const; + constant_interval_exprt bottom() const; bool is_min() const; bool is_max() const; @@ -341,7 +330,7 @@ class constant_interval_exprt : public binary_exprt static constant_exprt zero(const constant_interval_exprt &interval); /* Private? */ - static const constant_interval_exprt get_extremes( + static constant_interval_exprt get_extremes( const constant_interval_exprt &lhs, const constant_interval_exprt &rhs, const exprt operation); @@ -352,12 +341,12 @@ class constant_interval_exprt : public binary_exprt static exprt get_max(std::vector &values); /* we don't simplify in the constructor otherwise */ - static const constant_interval_exprt simplified_interval(exprt &l, exprt &r); + static constant_interval_exprt simplified_interval(exprt &l, exprt &r); static exprt simplified_expr(exprt expr); /* Swap lower and upper! */ const constant_interval_exprt swap() const; - static const constant_interval_exprt swap(constant_interval_exprt &i); + static constant_interval_exprt swap(constant_interval_exprt &i); /* Helpers */ /* Four common params: self, static: type, expr, interval */ From b9e0d5a984d5d3002e3d224691df65c629adea4a Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 16 May 2018 15:33:17 +0100 Subject: [PATCH 08/59] (INT) Use irep_idt in place of exprt when exprt isn't needed Also replace some asserts with INVARIANT, PRECONDITION or UNREACHABLE --- src/util/interval.cpp | 238 ++++++++++++++++++++---------------------- src/util/interval.h | 22 ++-- 2 files changed, 128 insertions(+), 132 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index debabfcabf9..e61469bb62b 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -124,9 +124,7 @@ constant_interval_exprt::multiply(const constant_interval_exprt &o) const handle_constants(o, mult_exprt()); } - mult_exprt operation; - operation.type() = type(); - return get_extremes(*this, o, operation); + return get_extremes(*this, o, ID_mult); } constant_interval_exprt @@ -143,8 +141,7 @@ constant_interval_exprt::divide(const constant_interval_exprt &o) const return top(); } - div_exprt operation; - return get_extremes(*this, o, operation); + return get_extremes(*this, o, ID_div); } constant_interval_exprt @@ -281,9 +278,7 @@ constant_interval_exprt::left_shift(const constant_interval_exprt &o) const return top(); } - shl_exprt operation; - operation.type() = type(); - return get_extremes(*this, o, operation); + return get_extremes(*this, o, ID_shl); } // Arithmetic @@ -300,9 +295,7 @@ constant_interval_exprt::right_shift(const constant_interval_exprt &o) const return top(); } - ashr_exprt operation; - operation.type() = type(); - return get_extremes(*this, o, operation); + return get_extremes(*this, o, ID_ashr); } constant_interval_exprt @@ -444,7 +437,7 @@ constant_interval_exprt constant_interval_exprt::decrement() const constant_interval_exprt constant_interval_exprt::get_extremes( const constant_interval_exprt &a, const constant_interval_exprt &b, - const exprt operation) + const irep_idt &operation) { constant_interval_exprt result; @@ -549,65 +542,65 @@ exprt constant_interval_exprt::get_extreme( } exprt constant_interval_exprt::generate_expression( - const exprt &a, - const exprt &b, - const exprt &operation) + const exprt &lhs, + const exprt &rhs, + const irep_idt &operation) { - if(operation.id() == ID_mult) + if(operation == ID_mult) { - return generate_multiply_expression(a, b, operation); + return generate_multiply_expression(lhs, rhs); } - if(operation.id() == ID_div) + if(operation == ID_div) { - return generate_division_expression(a, b, operation); + return generate_division_expression(lhs, rhs); } - if(operation.id() == ID_mod) + if(operation == ID_mod) { - return generate_modulo_expression(a, b, operation); + return generate_modulo_expression(lhs, rhs); } - if(operation.id() == ID_shl || operation.id() == ID_ashr) + if(operation == ID_shl || operation == ID_ashr) { - return generate_shift_expression(a, b, operation); + return generate_shift_expression(lhs, rhs, operation); } - assert(0 && "Not yet implemented!"); + UNREACHABLE; } exprt constant_interval_exprt::generate_multiply_expression( - const exprt &a, - const exprt &b, - exprt operation) + const exprt &lower, + const exprt &upper) { - assert(operation.id() == ID_mult); - assert(operation.type().is_not_nil() && is_numeric(operation.type())); + PRECONDITION(lower.type().is_not_nil() && is_numeric(lower.type())); - if(is_max(a)) + if(is_max(lower)) { - return generate_multiply_expression_max(b); + return generate_multiply_expression_max(upper); } - if(is_max(b)) + if(is_max(upper)) { - return generate_multiply_expression_max(a); + return generate_multiply_expression_max(lower); } - if(is_min(a)) + if(is_min(lower)) { - return generate_multiply_expression_min(a, b); + return generate_multiply_expression_min(lower, upper); } - if(is_min(b)) + if(is_min(upper)) { - return generate_multiply_expression_min(b, a); + return generate_multiply_expression_min(upper, lower); } - assert(!is_extreme(a) && !is_extreme(b)); + INVARIANT( + !is_extreme(lower) && !is_extreme(upper), + "We ruled out extreme cases beforehand"); - operation.copy_to_operands(a, b); - return simplified_expr(operation); + auto result = mult_exprt(lower, upper); + return simplified_expr(result); } exprt constant_interval_exprt::generate_multiply_expression_max( @@ -626,14 +619,14 @@ exprt constant_interval_exprt::generate_multiply_expression_max( } else { - assert(!is_positive(expr) && "Min value cannot be >0."); - assert(is_zero(expr) && "Non-negative MIN must be zero."); + INVARIANT(!is_positive(expr), "Min value cannot be >0."); + INVARIANT(is_zero(expr), "Non-negative MIN must be zero."); return expr; } } - assert(!is_extreme(expr)); + INVARIANT(!is_extreme(expr), "We ruled out extreme cases"); if(is_negative(expr)) { @@ -650,7 +643,7 @@ exprt constant_interval_exprt::generate_multiply_expression_max( return max_exprt(expr); } - assert(0 && "Unreachable."); + UNREACHABLE; return nil_exprt(); } @@ -658,7 +651,7 @@ exprt constant_interval_exprt::generate_multiply_expression_min( const exprt &min, const exprt &other) { - assert(is_min(min)); + PRECONDITION(is_min(min)); if(is_max(other)) { @@ -668,8 +661,8 @@ exprt constant_interval_exprt::generate_multiply_expression_min( } else { - assert(!is_positive(min) && "Min value cannot be >0."); - assert(is_zero(min) && "Non-negative MIN must be zero."); + INVARIANT(!is_positive(min), "Min value cannot be >0."); + INVARIANT(is_zero(min), "Non-negative MIN must be zero."); return min; } @@ -677,131 +670,132 @@ exprt constant_interval_exprt::generate_multiply_expression_min( if(is_min(other)) { - assert( - !is_positive(min) && !is_positive(other) && "Min value cannot be >0."); - assert(is_negative(other) || is_zero(other)); + INVARIANT( + !is_positive(min) && !is_positive(other), "Min value cannot be >0."); + INVARIANT( + is_negative(other) || is_zero(other), + "Other was established to be min value, which must be <= 0"); if(is_negative(min) && is_negative(other)) { return max_exprt(min); } - assert(is_zero(min) || is_zero(other)); + INVARIANT(is_zero(min) || is_zero(other), "Min value must be <= 0"); return (is_zero(min) ? min : other); } - assert(0 && "Unreachable."); + UNREACHABLE; return nil_exprt(); } exprt constant_interval_exprt::generate_division_expression( - const exprt &a, - const exprt &b, - exprt operation) + const exprt &lhs, + const exprt &rhs) { - assert(operation.id() == ID_div); - assert(operation.type().is_not_nil() && is_numeric(operation.type())); + PRECONDITION(lhs.type().is_not_nil() && is_numeric(lhs.type())); - assert(!is_zero(b)); + PRECONDITION(!is_zero(rhs)); - if(b.is_one()) + if(rhs.is_one()) { - return a; + return lhs; } - if(is_max(a)) + if(is_max(lhs)) { - if(is_negative(b)) + if(is_negative(rhs)) { - return min_exprt(a); + return min_exprt(lhs); } - return a; + return lhs; } - if(is_min(a)) + if(is_min(lhs)) { - if(is_negative(b)) + if(is_negative(rhs)) { - return max_exprt(a); + return max_exprt(lhs); } - return a; + return lhs; } - assert(!is_extreme(a)); + INVARIANT(!is_extreme(lhs), "We ruled out extreme cases beforehand"); - if(is_max(b)) + if(is_max(rhs)) { - return zero(b); + return zero(rhs); } - if(is_min(b)) + if(is_min(rhs)) { - assert(is_signed(b)); - return zero(b); + INVARIANT( + is_signed(rhs), "We think this is a signed integer for some reason?"); + return zero(rhs); } - assert(!is_extreme(a) && !is_extreme(b)); + INVARIANT( + !is_extreme(lhs) && !is_extreme(rhs), + "We ruled out extreme cases beforehand"); - assert(!operation.has_operands()); - operation.copy_to_operands(a, b); - return simplified_expr(operation); + auto div_expr = div_exprt(lhs, rhs); + return simplified_expr(div_expr); } exprt constant_interval_exprt::generate_modulo_expression( - const exprt &a, - const exprt &b, - exprt operation) + const exprt &lhs, + const exprt &rhs) { - assert(operation.id() == ID_mod); - assert(operation.type().is_not_nil() && is_numeric(operation.type())); + PRECONDITION(lhs.type().is_not_nil() && is_numeric(lhs.type())); - assert(!is_zero(b)); + PRECONDITION(!is_zero(rhs)); - if(b.is_one()) + if(rhs.is_one()) { - return a; + return lhs; } - if(is_max(a)) + if(is_max(lhs)) { - if(is_negative(b)) + if(is_negative(rhs)) { - return min_exprt(a); + return min_exprt(lhs); } - return a; + return lhs; } - if(is_min(a)) + if(is_min(lhs)) { - if(is_negative(b)) + if(is_negative(rhs)) { - return max_exprt(a); + return max_exprt(lhs); } - return a; + return lhs; } - assert(!is_extreme(a)); + INVARIANT(!is_extreme(lhs), "We rule out this case beforehand"); - if(is_max(b)) + if(is_max(rhs)) { - return zero(b); + return zero(rhs); } - if(is_min(b)) + if(is_min(rhs)) { - assert(is_signed(b)); - return zero(b); + INVARIANT(is_signed(rhs), "We assume this is signed for some reason?"); + return zero(rhs); } - assert(!is_extreme(a) && !is_extreme(b)); + INVARIANT( + !is_extreme(lhs) && !is_extreme(rhs), + "We ruled out extreme values beforehand"); - assert(!operation.has_operands()); - operation.copy_to_operands(a, b); - return simplified_expr(operation); + auto modulo_expr = mod_exprt(lhs, rhs); + return simplified_expr(modulo_expr); } constant_interval_exprt constant_interval_exprt::eval(const irep_idt &id) @@ -928,42 +922,42 @@ constant_interval_exprt::tv_to_interval(const tvt &tv) const } exprt constant_interval_exprt::generate_shift_expression( - const exprt &a, - const exprt &b, - exprt operation) + const exprt &lhs, + const exprt &rhs, + const irep_idt &operation) { - assert(operation.id() == ID_shl || operation.id() == ID_ashr); + PRECONDITION(operation == ID_shl || operation == ID_ashr); - if(is_zero(a) || is_zero(b)) + if(is_zero(lhs) || is_zero(rhs)) { // Shifting zero does nothing. // Shifting BY zero also does nothing. - return a; + return lhs; } - // Should be caught at an earlier stage. - assert(!is_negative(b)); + INVARIANT(!is_negative(rhs), "Should be caught at an earlier stage."); - if(is_max(a)) + if(is_max(lhs)) { - return a; + return lhs; } - if(is_min(a)) + if(is_min(lhs)) { - return a; + return lhs; } - if(is_max(b)) + if(is_max(rhs)) { - return min_exprt(b); + return min_exprt(rhs); } - assert(!is_extreme(a) && !is_extreme(b)); + INVARIANT( + !is_extreme(lhs) && !is_extreme(rhs), + "We ruled out extreme cases beforehand"); - operation.op0() = a; - operation.op1() = b; - return simplified_expr(operation); + auto shift_expr = shift_exprt(lhs, operation, rhs); + return simplified_expr(shift_expr); } constant_interval_exprt diff --git a/src/util/interval.h b/src/util/interval.h index 6405c2cd05d..64ba52afcfb 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -333,7 +333,7 @@ class constant_interval_exprt : public binary_exprt static constant_interval_exprt get_extremes( const constant_interval_exprt &lhs, const constant_interval_exprt &rhs, - const exprt operation); + const irep_idt &operation); static exprt get_extreme(std::vector values, bool min = true); static exprt get_max(const exprt &a, const exprt &b); static exprt get_min(const exprt &a, const exprt &b); @@ -404,19 +404,21 @@ class constant_interval_exprt : public binary_exprt static exprt abs(const exprt &expr); private: + static exprt generate_expression( + const exprt &lhs, + const exprt &rhs, + const irep_idt &operation); static exprt - generate_expression(const exprt &a, const exprt &b, const exprt &operation); - static exprt - generate_multiply_expression(const exprt &a, const exprt &b, exprt operation); + generate_multiply_expression(const exprt &lower, const exprt &upper); static exprt generate_multiply_expression_max(const exprt &expr); static exprt generate_multiply_expression_min(const exprt &min, const exprt &other); - static exprt - generate_division_expression(const exprt &a, const exprt &b, exprt operation); - static exprt - generate_modulo_expression(const exprt &a, const exprt &b, exprt operation); - static exprt - generate_shift_expression(const exprt &a, const exprt &b, exprt operation); + static exprt generate_division_expression(const exprt &lhs, const exprt &rhs); + static exprt generate_modulo_expression(const exprt &lhs, const exprt &rhs); + static exprt generate_shift_expression( + const exprt &lhs, + const exprt &rhs, + const irep_idt &operation); }; inline const constant_interval_exprt & From 8c48d158dd63fd6adbdba230be6892c82e450898 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 16 May 2018 16:03:22 +0100 Subject: [PATCH 09/59] (INT) Cleanup to_string and operator<< for intervals Also left some comments for things that need to be cleaned up in the future --- src/util/interval.cpp | 50 ++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index e61469bb62b..20bb8c720d7 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1493,56 +1493,62 @@ bool constant_interval_exprt::contains( std::string constant_interval_exprt::to_string() const { std::stringstream out; + out << *this; + return out.str(); +} - out << dstringt("["); +std::ostream &operator<<(std::ostream &out, const constant_interval_exprt &i) +{ + out << "["; - if(!is_min()) + if(!i.is_min()) { - if(is_bitvector(get_lower())) + // FIXME Not everything that's a bitvector is also an integer + if(i.is_bitvector(i.get_lower())) { - out << binary2integer(get_lower().get(ID_value).c_str(), 2); + out << binary2integer( + id2string(i.get_lower().get(ID_value)), i.is_signed()); } else { - out << get_lower().get(ID_value); + // TODO handle floating point numbers? + out << i.get_lower().get(ID_value); } } else { - if(is_signed(get_lower())) + if(i.is_signed(i.get_lower())) { - out << dstringt("MIN"); + out << "MIN"; } else { - out << dstringt("0"); + // FIXME Extremely sketchy, the opposite of + // FIXME "signed" isn't "unsigned" but + // FIXME "literally anything else" + out << "0"; } } - out << dstringt(","); + out << ","; - if(!is_max()) + // FIXME See comments on is_min + if(!i.is_max()) { - if(is_bitvector(get_upper())) + if(i.is_bitvector(i.get_upper())) { - out << binary2integer(get_upper().get(ID_value).c_str(), 2); + out << binary2integer( + id2string(i.get_upper().get(ID_value)), i.is_signed()); } else { - out << get_upper().get(ID_value); + out << i.get_upper().get(ID_value); } } else - out << dstringt("MAX"); - - out << dstringt("]"); + out << "MAX"; - return out.str(); -} - -std::ostream &operator<<(std::ostream &out, const constant_interval_exprt &i) -{ - out << i.to_string(); + out << "]"; return out; } From bb0c583e38e1cab84c7814eae0f98bed77131ab3 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 16 May 2018 16:41:18 +0100 Subject: [PATCH 10/59] (INT) Give handle constants a better name --- src/util/interval.cpp | 48 +++++++++++++++++++------------------------ src/util/interval.h | 8 +++++--- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 20bb8c720d7..02931066d25 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -43,7 +43,7 @@ constant_interval_exprt constant_interval_exprt::unary_minus() const { if(is_single_value_interval()) { - handle_constants(unary_minus_exprt()); + handle_constant_unary_expression(ID_unary_minus); } exprt lower; @@ -75,7 +75,7 @@ constant_interval_exprt::plus(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, plus_exprt()); + handle_constant_binary_expression(o, ID_plus); } exprt lower = min(); @@ -121,7 +121,7 @@ constant_interval_exprt::multiply(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, mult_exprt()); + handle_constant_binary_expression(o, ID_mult); } return get_extremes(*this, o, ID_mult); @@ -132,7 +132,7 @@ constant_interval_exprt::divide(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, div_exprt()); + handle_constant_binary_expression(o, ID_div); } // If other might be division by zero, set everything to top. @@ -151,7 +151,7 @@ constant_interval_exprt::modulo(const constant_interval_exprt &o) const if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, mod_exprt()); + handle_constant_binary_expression(o, ID_mod); } if(o.is_bottom()) @@ -270,7 +270,7 @@ constant_interval_exprt::left_shift(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, shl_exprt()); + handle_constant_binary_expression(o, ID_shl); } if(is_negative(o.get_lower())) @@ -287,7 +287,7 @@ constant_interval_exprt::right_shift(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, ashr_exprt()); + handle_constant_binary_expression(o, ID_ashr); } if(is_negative(o.get_lower())) @@ -303,7 +303,7 @@ constant_interval_exprt::bitwise_xor(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, bitxor_exprt()); + handle_constant_binary_expression(o, ID_bitxor); } return top(); @@ -314,7 +314,7 @@ constant_interval_exprt::bitwise_or(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, bitor_exprt()); + handle_constant_binary_expression(o, ID_bitor); } return top(); @@ -325,7 +325,7 @@ constant_interval_exprt::bitwise_and(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, bitand_exprt()); + handle_constant_binary_expression(o, ID_bitand); } return top(); @@ -335,7 +335,7 @@ constant_interval_exprt constant_interval_exprt::bitwise_not() const { if(is_single_value_interval()) { - handle_constants(bitnot_exprt()); + handle_constant_unary_expression(ID_bitnot); } return top(); @@ -961,31 +961,25 @@ exprt constant_interval_exprt::generate_shift_expression( } constant_interval_exprt -constant_interval_exprt::handle_constants(exprt expr) const +constant_interval_exprt::handle_constant_unary_expression( + const irep_idt &op) const { if(is_single_value_interval()) { - expr.type() = type(); - expr.copy_to_operands(get_lower()); - + auto expr = unary_exprt(op, get_lower()); return constant_interval_exprt(simplified_expr(expr)); } - return top(); } -constant_interval_exprt constant_interval_exprt::handle_constants( - const constant_interval_exprt &o, - exprt expr) const +constant_interval_exprt +constant_interval_exprt::handle_constant_binary_expression( + const constant_interval_exprt &other, + const irep_idt &op) const { - if(is_single_value_interval() && o.is_single_value_interval()) - { - expr.type() = type(); - expr.copy_to_operands(get_lower(), o.get_lower()); - return constant_interval_exprt(simplified_expr(expr)); - } - - return top(); + PRECONDITION(is_single_value_interval() && other.is_single_value_interval()); + auto expr = binary_exprt(get_lower(), op, other.get_lower()); + return constant_interval_exprt(simplified_expr(expr)); } exprt constant_interval_exprt::get_max(const exprt &a, const exprt &b) diff --git a/src/util/interval.h b/src/util/interval.h index 64ba52afcfb..1a00dc8fdf2 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -97,9 +97,11 @@ class constant_interval_exprt : public binary_exprt const exprt &get_upper() const; /** SET OF ARITHMETIC OPERATORS */ - constant_interval_exprt handle_constants(exprt expr) const; constant_interval_exprt - handle_constants(const constant_interval_exprt &o, exprt expr) const; + handle_constant_unary_expression(const irep_idt &op) const; + constant_interval_exprt handle_constant_binary_expression( + const constant_interval_exprt &other, + const irep_idt &) const; constant_interval_exprt eval(const irep_idt &unary_operator); constant_interval_exprt @@ -122,7 +124,7 @@ class constant_interval_exprt : public binary_exprt /* Binary */ constant_interval_exprt plus(const constant_interval_exprt &o) const; - constant_interval_exprt minus(const constant_interval_exprt &o) const; + constant_interval_exprt minus(const constant_interval_exprt &other) const; constant_interval_exprt multiply(const constant_interval_exprt &o) const; constant_interval_exprt divide(const constant_interval_exprt &o) const; constant_interval_exprt modulo(const constant_interval_exprt &o) const; From f7bb44210cad4598044ebe634777a74085298ae1 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 16 May 2018 16:42:29 +0100 Subject: [PATCH 11/59] (INT) Remove swap function in intervals --- src/util/interval.cpp | 11 ----------- src/util/interval.h | 3 --- 2 files changed, 14 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 02931066d25..677b49ae755 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1083,17 +1083,6 @@ constant_interval_exprt constant_interval_exprt::bottom() const return bottom(type()); } -constant_interval_exprt -constant_interval_exprt::swap(constant_interval_exprt &i) -{ - return constant_interval_exprt(i.get_upper(), i.get_lower()); -} - -const constant_interval_exprt constant_interval_exprt::swap() const -{ - return constant_interval_exprt(get_lower(), get_upper()); -} - /* Helpers */ bool constant_interval_exprt::is_int() const diff --git a/src/util/interval.h b/src/util/interval.h index 1a00dc8fdf2..292275fa42a 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -346,9 +346,6 @@ class constant_interval_exprt : public binary_exprt static constant_interval_exprt simplified_interval(exprt &l, exprt &r); static exprt simplified_expr(exprt expr); - /* Swap lower and upper! */ - const constant_interval_exprt swap() const; - static constant_interval_exprt swap(constant_interval_exprt &i); /* Helpers */ /* Four common params: self, static: type, expr, interval */ From 412bbad46fe51c333aa9e4823b86d462843dc197 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 29 May 2020 10:37:03 +0100 Subject: [PATCH 12/59] Refactor minus and correct a typo in the comments --- src/util/interval.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 677b49ae755..265c1ff6ea3 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -105,15 +105,16 @@ constant_interval_exprt::plus(const constant_interval_exprt &o) const } constant_interval_exprt -constant_interval_exprt::minus(const constant_interval_exprt &o) const +constant_interval_exprt::minus(const constant_interval_exprt &other) const { - if(o.is_single_value_interval() && is_single_value_interval()) + if(other.is_single_value_interval() && is_single_value_interval()) { - handle_constants(o, minus_exprt()); + handle_constant_binary_expression(other, ID_minus); } - // e.g. [t.u - o.l, t.l - o.u] - return plus(o.unary_minus().swap()); + // FIXME This is nonsense if the interval type is unsigned int + // [this.lower - other.upper, this.upper - other.lower] + return plus(other.unary_minus()); } constant_interval_exprt From ad4dda3e7f3c9b86562b74960099ab98722b0175 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Mon, 21 May 2018 16:22:17 +0100 Subject: [PATCH 13/59] (INT) Add additional unit tests for intervals --- unit/util/interval/subtract.cpp | 63 ++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/unit/util/interval/subtract.cpp b/unit/util/interval/subtract.cpp index 01f3872576e..3f65c2ae3de 100644 --- a/unit/util/interval/subtract.cpp +++ b/unit/util/interval/subtract.cpp @@ -87,18 +87,73 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") THEN("Domain is consistent") { REQUIRE(V(left.get_lower()) == 2); - REQUIRE(left.is_max()); + REQUIRE(left.has_no_upper_bound()); REQUIRE(V(right.get_lower()) == 6); - REQUIRE(right.is_max()); + REQUIRE(right.has_no_upper_bound()); } CAPTURE(result); THEN("The result is [MIN, MAX]") { - REQUIRE(result.is_max()); - REQUIRE(result.is_min()); + REQUIRE(result.has_no_upper_bound()); + REQUIRE(result.has_no_lower_bound()); } } } } + +SCENARIO("Subtracting unsigned integers") +{ + WHEN("Subtracting two constant intervals") + { + auto lhs = + constant_interval_exprt(constant_exprt("1010", unsignedbv_typet(32))); + auto rhs = + constant_interval_exprt(constant_exprt("0011", unsignedbv_typet(32))); + THEN("it should work") + { + auto result = lhs.minus(rhs); + REQUIRE(result.is_single_value_interval()); + auto maybe_lower = numeric_cast(result.get_lower()); + REQUIRE(maybe_lower.has_value()); + REQUIRE(maybe_lower.value() == 7); + } + } + + WHEN("Subtracting zero from something") + { + auto lhs = + constant_interval_exprt(constant_exprt("1010", unsignedbv_typet(32))); + auto rhs = + constant_interval_exprt(constant_exprt("0", unsignedbv_typet(32))); + + THEN("it should not give a completely crazy result") + { + auto result = lhs.minus(rhs); + REQUIRE(result.is_single_value_interval()); + auto maybe_lower = numeric_cast(result.get_lower()); + REQUIRE(maybe_lower.has_value()); + REQUIRE(maybe_lower.value() == 10); + } + } + + WHEN("Subtracting an non-constant interval containing zero") + { + auto lhs = + constant_interval_exprt(constant_exprt("1010", unsignedbv_typet(32))); + auto rhs = constant_interval_exprt( + constant_exprt("0", unsignedbv_typet(32)), + constant_exprt("1", unsignedbv_typet(32))); + THEN("it should not give a completely crazy result") + { + auto result = lhs.minus(rhs); + auto maybe_lower = numeric_cast(result.get_lower()); + REQUIRE(maybe_lower.has_value()); + REQUIRE(maybe_lower.value() == 9); + auto maybe_upper = numeric_cast(result.get_upper()); + REQUIRE(maybe_upper.has_value()); + REQUIRE(maybe_upper.value() == 10); + } + } +} \ No newline at end of file From d707ed0055701515f5eef113f5657739aa498746 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Mon, 21 May 2018 17:09:30 +0100 Subject: [PATCH 14/59] (INT) Various code style fixes in intervals code --- src/util/interval.cpp | 121 +++++++++++++---------------- src/util/interval.h | 16 ++-- unit/util/interval/add.cpp | 12 +-- unit/util/interval/bitwise.cpp | 2 +- unit/util/interval/comparisons.cpp | 2 +- unit/util/interval/get_extreme.cpp | 2 +- unit/util/interval/modulo.cpp | 2 +- unit/util/interval/multiply.cpp | 6 +- unit/util/interval/shift.cpp | 2 +- unit/util/interval/subtract.cpp | 6 +- 10 files changed, 78 insertions(+), 93 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 265c1ff6ea3..42530cdd277 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1,9 +1,10 @@ -/* - * interval.cpp - * - * Created on: 16 Jun 2017 - * Author: dan - */ +/*******************************************************************\ + + Module: intervals + + Author: Daniel Neville (2017), Diffblue Ltd + +\*******************************************************************/ /* * @@ -32,8 +33,6 @@ const exprt &constant_interval_exprt::get_upper() const return op1(); } -//make clean -s && make -j 7 CXX="/usr/local/bin/ccache g++" -s && ./unit_tests - constant_interval_exprt constant_interval_exprt::unary_plus() const { return *this; @@ -49,7 +48,7 @@ constant_interval_exprt constant_interval_exprt::unary_minus() const exprt lower; exprt upper; - if(is_max()) + if(has_no_upper_bound()) { lower = min(); } @@ -58,7 +57,7 @@ constant_interval_exprt constant_interval_exprt::unary_minus() const lower = simplified_expr(unary_minus_exprt(get_upper())); } - if(is_min()) + if(has_no_lower_bound()) { upper = max(); } @@ -87,7 +86,9 @@ constant_interval_exprt::plus(const constant_interval_exprt &o) const } else { - assert(!is_max(get_upper()) && !is_max(o.get_upper())); + INVARIANT( + !is_max(get_upper()) && !is_max(o.get_upper()), + "We just excluded this case"); upper = simplified_expr(plus_exprt(get_upper(), o.get_upper())); } @@ -97,7 +98,9 @@ constant_interval_exprt::plus(const constant_interval_exprt &o) const } else { - assert(!is_min(get_lower()) && !is_min(o.get_lower())); + INVARIANT( + !is_min(get_lower()) && !is_min(o.get_lower()), + "We just excluded that case"); lower = simplified_expr(plus_exprt(get_lower(), o.get_lower())); } @@ -112,7 +115,6 @@ constant_interval_exprt::minus(const constant_interval_exprt &other) const handle_constant_binary_expression(other, ID_minus); } - // FIXME This is nonsense if the interval type is unsigned int // [this.lower - other.upper, this.upper - other.lower] return plus(other.unary_minus()); } @@ -193,8 +195,9 @@ constant_interval_exprt::modulo(const constant_interval_exprt &o) const // [-5, 5] % [3] if(is_negative(get_lower()) && is_positive(get_upper())) { - assert(contains_zero()); - + INVARIANT( + contains_zero(), + "Zero should be between a negative and a positive value"); // This can be done more accurately. lower = get_min(o.get_lower(), get_lower()); upper = get_max(o.get_upper(), get_upper()); @@ -224,7 +227,10 @@ tvt constant_interval_exprt::is_definitely_false() const if(contains(constant_interval_exprt(zero()))) { - assert(is_positive(get_upper()) || is_negative(get_lower())); + INVARIANT( + is_positive(get_upper()) || is_negative(get_lower()), + "If an interval contains zero its lower bound can't be positive" + " and its upper bound can't be negative"); return tvt::unknown(); } @@ -539,7 +545,7 @@ exprt constant_interval_exprt::get_extreme( return max_exprt(type); } - assert(0); + UNREACHABLE; } exprt constant_interval_exprt::generate_expression( @@ -918,7 +924,7 @@ constant_interval_exprt::tv_to_interval(const tvt &tv) const return constant_interval_exprt(zero()); } - assert(tv.is_unknown()); + INVARIANT(tv.is_unknown(), "We excluded the other cases"); return top(); } @@ -1015,7 +1021,7 @@ exprt constant_interval_exprt::simplified_expr(exprt expr) symbol_tablet symbol_table; const namespacet ns(symbol_table); - assert(!contains_extreme(expr)); + PRECONDITION(!contains_extreme(expr)); return simplify_expr(expr, ns); } @@ -1023,7 +1029,9 @@ exprt constant_interval_exprt::simplified_expr(exprt expr) constant_exprt constant_interval_exprt::zero(const typet &type) { constant_exprt zero = from_integer(mp_integer(0), type); - assert(zero.is_zero()); // NOT is_zero(zero) (inf. recursion + INVARIANT( + zero.is_zero(), // NOT is_zero(zero) (inf. recursion) + "The value created from 0 should be zero"); return zero; } @@ -1055,7 +1063,7 @@ max_exprt constant_interval_exprt::max() const bool constant_interval_exprt::is_top() const { - return (is_min() && is_max()); + return (has_no_lower_bound() && has_no_upper_bound()); } bool constant_interval_exprt::is_bottom() const @@ -1221,12 +1229,12 @@ bool constant_interval_exprt::is_extreme(const exprt &expr1, const exprt &expr2) return is_extreme(expr1) || is_extreme(expr2); } -bool constant_interval_exprt::is_max() const +bool constant_interval_exprt::has_no_upper_bound() const { return is_max(get_upper()); } -bool constant_interval_exprt::is_min() const +bool constant_interval_exprt::has_no_lower_bound() const { return is_min(get_lower()); } @@ -1255,7 +1263,7 @@ bool constant_interval_exprt::is_positive(const exprt &expr) return true; } - assert(is_signed(expr)); + INVARIANT(is_signed(expr), "Not implemented for floats"); // Floats later if(is_min(expr)) @@ -1285,7 +1293,7 @@ bool constant_interval_exprt::is_zero(const exprt &expr) return false; } - assert(!is_max(expr) && !is_min(expr)); + INVARIANT(!is_max(expr) && !is_min(expr), "We excluded those cases"); if(expr.is_zero()) { @@ -1302,14 +1310,15 @@ bool constant_interval_exprt::is_negative(const exprt &expr) return false; } - assert(is_signed(expr)); + INVARIANT( + is_signed(expr), "We don't support anything other than integers yet"); if(is_min(expr)) { return true; } - assert(!is_extreme(expr)); + INVARIANT(!is_extreme(expr), "We excluded these cases before"); return less_than(expr, zero(expr)); } @@ -1338,8 +1347,10 @@ bool constant_interval_exprt::equal(const exprt &a, const exprt &b) if(!is_numeric(a) || !is_numeric(b)) { - // Best we can do now is a==b?, but this is covered by the above, so always false. - assert(!(a == b)); + INVARIANT( + !(a == b), + "Best we can do now is a==b?, but this is covered by the above, so " + "always false"); return false; } @@ -1364,7 +1375,7 @@ bool constant_interval_exprt::equal(const exprt &a, const exprt &b) return false; } - assert(!is_extreme(l, r)); + INVARIANT(!is_extreme(l, r), "We've excluded this before"); return simplified_expr(equal_exprt(l, r)).is_true(); } @@ -1385,7 +1396,7 @@ bool constant_interval_exprt::less_than(const exprt &a, const exprt &b) return false; } - assert(!is_max(l)); + INVARIANT(!is_max(l), "We've just excluded this case"); if(is_min(r)) { @@ -1393,15 +1404,16 @@ bool constant_interval_exprt::less_than(const exprt &a, const exprt &b) return false; } - assert(!is_max(l) && !is_min(r)); + INVARIANT(!is_max(l) && !is_min(r), "We've excluded these cases"); if(is_min(l)) { - assert(!is_min(r)); return true; } - assert(!is_max(l) && !is_min(r) && !is_min(l)); + INVARIANT( + !is_max(l) && !is_min(r) && !is_min(l), + "These cases should have all been handled before this point"); if(is_max(r)) { @@ -1409,9 +1421,9 @@ bool constant_interval_exprt::less_than(const exprt &a, const exprt &b) return !is_max(l); } - assert(!is_max(l) && !is_min(r) && !is_min(l) && !is_max(r)); - - assert(!is_extreme(l, r)); + INVARIANT( + !is_extreme(l) && !is_extreme(r), + "We have excluded all of these cases in the code above"); return simplified_expr(binary_relation_exprt(l, ID_lt, r)).is_true(); } @@ -1419,33 +1431,6 @@ bool constant_interval_exprt::less_than(const exprt &a, const exprt &b) bool constant_interval_exprt::greater_than(const exprt &a, const exprt &b) { return less_than(b, a); - - // if(!is_numeric(a) || !is_numeric(b)) - // { - // return false; - // } - // - // exprt l=(is_min(a) && is_unsigned(a)) ? zero(a) : a; - // exprt r=(is_min(b) && is_unsigned(b)) ? zero(b) : b; - // - // if(is_max(l) && !is_max(r)) - // { - // return true; - // } - // - // if((is_max(l) && is_max(r)) || (is_min(l) && is_min(r))) - // { - // return false; - // } - // - // if(is_min(l) && is_max(r)) - // { - // return false; - // } - // - // assert(!is_extreme(l) && !is_extreme(r)); - // - // return simplified_expr(binary_relation_exprt(l, ID_gt, r)).is_true(); } bool constant_interval_exprt::less_than_or_equal(const exprt &a, const exprt &b) @@ -1485,7 +1470,7 @@ std::ostream &operator<<(std::ostream &out, const constant_interval_exprt &i) { out << "["; - if(!i.is_min()) + if(!i.has_no_lower_bound()) { // FIXME Not everything that's a bitvector is also an integer if(i.is_bitvector(i.get_lower())) @@ -1517,7 +1502,7 @@ std::ostream &operator<<(std::ostream &out, const constant_interval_exprt &i) out << ","; // FIXME See comments on is_min - if(!i.is_max()) + if(!i.has_no_upper_bound()) { if(i.is_bitvector(i.get_upper())) { @@ -1823,12 +1808,12 @@ bool constant_interval_exprt::is_bottom(const constant_interval_exprt &a) bool constant_interval_exprt::is_min(const constant_interval_exprt &a) { - return a.is_min(); + return a.has_no_lower_bound(); } bool constant_interval_exprt::is_max(const constant_interval_exprt &a) { - return a.is_max(); + return a.has_no_upper_bound(); } bool constant_interval_exprt::contains_extreme(const exprt expr) diff --git a/src/util/interval.h b/src/util/interval.h index 292275fa42a..acc14534056 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -1,10 +1,10 @@ -/* - * interval.h - * - * Created on: 16 Jun 2017 - * Author: dan - */ +/*******************************************************************\ + Module: intervals + + Author: Daniel Neville (2017) + +\*******************************************************************/ #ifndef SRC_ANALYSES_INTERVAL_H_ #define SRC_ANALYSES_INTERVAL_H_ @@ -317,8 +317,8 @@ class constant_interval_exprt : public binary_exprt constant_interval_exprt top() const; constant_interval_exprt bottom() const; - bool is_min() const; - bool is_max() const; + bool has_no_lower_bound() const; + bool has_no_upper_bound() const; static bool is_min(const exprt &expr); static bool is_max(const exprt &expr); diff --git a/unit/util/interval/add.cpp b/unit/util/interval/add.cpp index 1f0a2bab786..ac159c94a18 100644 --- a/unit/util/interval/add.cpp +++ b/unit/util/interval/add.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ Module: Unit tests for variable/sensitivity/abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited \*******************************************************************/ #include @@ -65,7 +65,7 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") REQUIRE(V(left.get_lower()) == 2); REQUIRE(V(left.get_upper()) == 4); REQUIRE(V(right.get_lower()) == 6); - REQUIRE(right.is_max()); + REQUIRE(right.has_no_upper_bound()); } CAPTURE(result); @@ -73,7 +73,7 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") THEN("The result is [8, MAX]") { REQUIRE(V(result.get_lower()) == 8); - REQUIRE(result.is_max()); + REQUIRE(result.has_no_upper_bound()); } } @@ -87,9 +87,9 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") THEN("Domain is consistent") { REQUIRE(V(left.get_lower()) == 2); - REQUIRE(left.is_max()); + REQUIRE(left.has_no_upper_bound()); REQUIRE(V(right.get_lower()) == 6); - REQUIRE(right.is_max()); + REQUIRE(right.has_no_upper_bound()); } CAPTURE(result); @@ -97,7 +97,7 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") THEN("The result is [8, MAX]") { REQUIRE(V(result.get_lower()) == 8); - REQUIRE(result.is_max()); + REQUIRE(result.has_no_upper_bound()); } } } diff --git a/unit/util/interval/bitwise.cpp b/unit/util/interval/bitwise.cpp index 88898fb413e..f5f6b1954b7 100644 --- a/unit/util/interval/bitwise.cpp +++ b/unit/util/interval/bitwise.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ Module: Unit tests for variable/sensitivity/abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited \*******************************************************************/ #include diff --git a/unit/util/interval/comparisons.cpp b/unit/util/interval/comparisons.cpp index a20eb03ed66..0b2e8322df4 100644 --- a/unit/util/interval/comparisons.cpp +++ b/unit/util/interval/comparisons.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ Module: Unit tests for variable/sensitivity/abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited \*******************************************************************/ #include diff --git a/unit/util/interval/get_extreme.cpp b/unit/util/interval/get_extreme.cpp index e10b8cfc5db..7d501f174bf 100644 --- a/unit/util/interval/get_extreme.cpp +++ b/unit/util/interval/get_extreme.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ Module: Unit tests for variable/sensitivity/abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited \*******************************************************************/ #include diff --git a/unit/util/interval/modulo.cpp b/unit/util/interval/modulo.cpp index 68996c84e34..4999daed88f 100644 --- a/unit/util/interval/modulo.cpp +++ b/unit/util/interval/modulo.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ Module: Unit tests for variable/sensitivity/abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited \*******************************************************************/ #include diff --git a/unit/util/interval/multiply.cpp b/unit/util/interval/multiply.cpp index b40e60d3b9a..dfd6361707b 100644 --- a/unit/util/interval/multiply.cpp +++ b/unit/util/interval/multiply.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ Module: Unit tests for variable/sensitivity/abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited \*******************************************************************/ #include @@ -138,14 +138,14 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") CHECK(V(a.get_lower()) == 2); CHECK(V(a.get_upper()) == 5); CHECK(V(b.get_lower()) == 7); - CHECK(b.is_max()); + CHECK(b.has_no_upper_bound()); } THEN("The result is [14, INF]") { CAPTURE(result); - CHECK(result.is_max()); + CHECK(result.has_no_upper_bound()); CHECK(V(result.get_lower()) == 14); } } diff --git a/unit/util/interval/shift.cpp b/unit/util/interval/shift.cpp index 2eb3cea1622..33e2b73f5c9 100644 --- a/unit/util/interval/shift.cpp +++ b/unit/util/interval/shift.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ Module: Unit tests for variable/sensitivity/abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited \*******************************************************************/ #include diff --git a/unit/util/interval/subtract.cpp b/unit/util/interval/subtract.cpp index 3f65c2ae3de..18b41fa3bc8 100644 --- a/unit/util/interval/subtract.cpp +++ b/unit/util/interval/subtract.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ Module: Unit tests for variable/sensitivity/abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited \*******************************************************************/ #include @@ -65,7 +65,7 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") REQUIRE(V(left.get_lower()) == 2); REQUIRE(V(left.get_upper()) == 4); REQUIRE(V(right.get_lower()) == 6); - REQUIRE(right.is_max()); + REQUIRE(right.has_no_upper_bound()); } CAPTURE(result); @@ -73,7 +73,7 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") THEN("The result is [MIN, -2]") { REQUIRE(V(result.get_upper()) == -2); - REQUIRE(result.is_min()); + REQUIRE(result.has_no_lower_bound()); } } From 069d113773a52c0b4ab0a2fd50e4158ba64d5858 Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Wed, 23 May 2018 12:05:31 +0100 Subject: [PATCH 15/59] (INT) Fix eval handling of ID_not case in intervals And also add tests for it. --- src/util/interval.cpp | 31 ++++++++++++++++++++++++++++-- src/util/interval.h | 2 ++ unit/util/interval/eval.cpp | 38 +++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 unit/util/interval/eval.cpp diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 42530cdd277..137cc097a3a 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -220,6 +220,18 @@ tvt constant_interval_exprt::is_definitely_true() const tvt constant_interval_exprt::is_definitely_false() const { + if(type().id() == ID_bool) + { + if(is_single_value_interval()) + { + return tvt(get_lower() == false_exprt()); + } + else + { + return tvt::unknown(); + } + } + if(equal(constant_interval_exprt(zero())).is_true()) { return tvt(true); @@ -821,8 +833,7 @@ constant_interval_exprt constant_interval_exprt::eval(const irep_idt &id) } if(id == ID_not) { - //return logical_not(); - return top(); + return tvt_to_interval(logical_not()); } return top(); @@ -1957,3 +1968,19 @@ tvt constant_interval_exprt::logical_not(const constant_interval_exprt &a) { return a.logical_not(); } + +constant_interval_exprt constant_interval_exprt::tvt_to_interval(const tvt &val) +{ + if(val.is_true()) + { + return constant_interval_exprt(true_exprt()); + } + else if(val.is_false()) + { + return constant_interval_exprt(false_exprt()); + } + else + { + return constant_interval_exprt(bool_typet()); + } +} diff --git a/src/util/interval.h b/src/util/interval.h index acc14534056..6251e104e43 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -85,6 +85,8 @@ class constant_interval_exprt : public binary_exprt { } + static constant_interval_exprt tvt_to_interval(const tvt &val); + /* Naming scheme * is_[X]? Returns bool / tvt * get_[X]? Returns relevant object diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp new file mode 100644 index 00000000000..c364ac815b7 --- /dev/null +++ b/unit/util/interval/eval.cpp @@ -0,0 +1,38 @@ +/*******************************************************************\ + Module: Unit tests for intervals + Author: DiffBlue Limited +\*******************************************************************/ + +#include + +#include +#include +#include +#include +#include + +SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") +{ + WHEN("Negating a boolean interval") + { + constant_interval_exprt true_interval = + constant_interval_exprt(true_exprt()); + constant_interval_exprt false_interval = + constant_interval_exprt(false_exprt()); + constant_interval_exprt bool_top_interval = + constant_interval_exprt(bool_typet()); + + THEN("True interval negated should equal the false interval") + { + REQUIRE(true_interval.eval(ID_not) == false_interval); + } + THEN("False interval negated should equal the true interval") + { + REQUIRE(false_interval.eval(ID_not) == true_interval); + } + THEN("An unknown boolean type should equal top (itself)") + { + REQUIRE(bool_top_interval.eval(ID_not) == bool_top_interval); + } + } +} From b07f98a7d2f6430ddc33b18d127be0ca2af932e0 Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Wed, 23 May 2018 14:38:58 +0100 Subject: [PATCH 16/59] (INT) Fix bitwise operators for intervals and add tests for them and eval. --- src/util/interval.cpp | 12 ++++---- unit/util/interval/bitwise.cpp | 56 +++++++++++++++++++++++----------- unit/util/interval/eval.cpp | 27 ++++++++++++++++ 3 files changed, 72 insertions(+), 23 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 137cc097a3a..82e64052c93 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -289,7 +289,7 @@ constant_interval_exprt::left_shift(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constant_binary_expression(o, ID_shl); + return handle_constant_binary_expression(o, ID_shl); } if(is_negative(o.get_lower())) @@ -306,7 +306,7 @@ constant_interval_exprt::right_shift(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constant_binary_expression(o, ID_ashr); + return handle_constant_binary_expression(o, ID_ashr); } if(is_negative(o.get_lower())) @@ -322,7 +322,7 @@ constant_interval_exprt::bitwise_xor(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constant_binary_expression(o, ID_bitxor); + return handle_constant_binary_expression(o, ID_bitxor); } return top(); @@ -333,7 +333,7 @@ constant_interval_exprt::bitwise_or(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constant_binary_expression(o, ID_bitor); + return handle_constant_binary_expression(o, ID_bitor); } return top(); @@ -344,7 +344,7 @@ constant_interval_exprt::bitwise_and(const constant_interval_exprt &o) const { if(o.is_single_value_interval() && is_single_value_interval()) { - handle_constant_binary_expression(o, ID_bitand); + return handle_constant_binary_expression(o, ID_bitand); } return top(); @@ -354,7 +354,7 @@ constant_interval_exprt constant_interval_exprt::bitwise_not() const { if(is_single_value_interval()) { - handle_constant_unary_expression(ID_bitnot); + return handle_constant_unary_expression(ID_bitnot); } return top(); diff --git a/unit/util/interval/bitwise.cpp b/unit/util/interval/bitwise.cpp index f5f6b1954b7..0363c1e2cc2 100644 --- a/unit/util/interval/bitwise.cpp +++ b/unit/util/interval/bitwise.cpp @@ -11,32 +11,54 @@ #include #include -#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) -#define V_(X) (binary2integer(X.c_str(), 2)) - SCENARIO("bitwise interval domain", "[core][analyses][interval][bitwise]") { - GIVEN("Two simple signed intervals") + WHEN("We have two unsigned single value intervals - 5 and 9") { - const typet type = signedbv_typet(32); - symbol_tablet symbol_table; - namespacet ns(symbol_table); + const unsignedbv_typet &unsigned_int = unsignedbv_typet(32); + constant_interval_exprt five = + constant_interval_exprt(from_integer(5, unsigned_int)); + constant_interval_exprt nine = + constant_interval_exprt(from_integer(9, unsigned_int)); + + THEN("Bitwise or should yield bitwise representation of 13") + { + REQUIRE( + five.bitwise_or(nine) == + constant_interval_exprt(from_integer(13, unsigned_int))); + } - source_locationt source_location; + THEN("Bitwise and should yield bitwise representation of 1") + { + REQUIRE( + five.bitwise_and(nine) == + constant_interval_exprt(from_integer(1, unsigned_int))); + REQUIRE( + (five & nine) == + constant_interval_exprt(from_integer(1, unsigned_int))); + } - std::map values; + THEN("Bitwise xor should yield bitwise representation of 12") + { + REQUIRE( + five.bitwise_xor(nine) == + constant_interval_exprt(from_integer(12, unsigned_int))); + } - for(int i = -100; i <= 100; i++) + THEN("Left shift on the 5 should produce 10") { - values[i] = from_integer(mp_integer(i), type); + REQUIRE( + five.left_shift( + constant_interval_exprt(from_integer(1, unsigned_int))) == + constant_interval_exprt(from_integer(10, unsigned_int))); } - WHEN("Something") + THEN("Right shift on the 5 should produce 2") { - THEN("Something else") - { - REQUIRE(true); - } + REQUIRE( + five.right_shift( + constant_interval_exprt(from_integer(1, unsigned_int))) == + constant_interval_exprt(from_integer(2, unsigned_int))); } } -} +} \ No newline at end of file diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp index c364ac815b7..2490c9c19ee 100644 --- a/unit/util/interval/eval.cpp +++ b/unit/util/interval/eval.cpp @@ -35,4 +35,31 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") REQUIRE(bool_top_interval.eval(ID_not) == bool_top_interval); } } + + WHEN("Unary operations to an interval") + { + constant_interval_exprt five = + constant_interval_exprt(from_integer(5, signedbv_typet(32))); + + THEN("When we apply unary addition to it, nothing should happen") + { + REQUIRE(five.eval(ID_unary_plus) == five); + } + + THEN("When we apply unary subtraction to it, it should be negated") + { + auto negated_val = + numeric_cast(five.eval(ID_unary_minus).get_lower()); + REQUIRE(negated_val.has_value()); + REQUIRE(negated_val.value() == -5); + } + + THEN("When we apply bitwise negation to it, is should be bitwise negated") + { + auto bitwise_negated_val = + numeric_cast(five.eval(ID_bitnot).get_lower()); + REQUIRE(bitwise_negated_val.has_value()); + REQUIRE(bitwise_negated_val.value() == (~5)); + } + } } From f64591cc5dbf89906768684138ee2c9ed9fa15ad Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 29 May 2018 11:38:17 +0100 Subject: [PATCH 17/59] (INT) Make eval in constant_interval_exprt const --- src/util/interval.cpp | 4 ++-- src/util/interval.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 82e64052c93..08695e1fccb 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -817,7 +817,7 @@ exprt constant_interval_exprt::generate_modulo_expression( return simplified_expr(modulo_expr); } -constant_interval_exprt constant_interval_exprt::eval(const irep_idt &id) +constant_interval_exprt constant_interval_exprt::eval(const irep_idt &id) const { if(id == ID_unary_plus) { @@ -841,7 +841,7 @@ constant_interval_exprt constant_interval_exprt::eval(const irep_idt &id) constant_interval_exprt constant_interval_exprt::eval( const irep_idt &binary_operator, - const constant_interval_exprt &other) + const constant_interval_exprt &other) const { if(binary_operator == ID_plus) { diff --git a/src/util/interval.h b/src/util/interval.h index 6251e104e43..3996748076b 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -105,9 +105,9 @@ class constant_interval_exprt : public binary_exprt const constant_interval_exprt &other, const irep_idt &) const; - constant_interval_exprt eval(const irep_idt &unary_operator); + constant_interval_exprt eval(const irep_idt &unary_operator) const; constant_interval_exprt - eval(const irep_idt &binary_operator, const constant_interval_exprt &o); + eval(const irep_idt &binary_operator, const constant_interval_exprt &o) const; /* Unary arithmetic */ constant_interval_exprt unary_plus() const; From 025896873132f1ea7b25de51fd1ddc7de51042ef Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 29 May 2018 15:40:10 +0100 Subject: [PATCH 18/59] (INT) Removed unimplemented function from util/interval.h --- src/util/interval.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/util/interval.h b/src/util/interval.h index 3996748076b..31e209225ab 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -243,9 +243,6 @@ class constant_interval_exprt : public binary_exprt const constant_interval_exprt &b); static tvt logical_not(const constant_interval_exprt &a); - static constant_interval_exprt - tv_to_interval(const constant_interval_exprt &interval, const tvt &tv); - static constant_interval_exprt unary_plus(const constant_interval_exprt &a); static constant_interval_exprt unary_minus(const constant_interval_exprt &a); From 0d3780284f8c0b5ab9f48a02a37ed461c4d6d74d Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 29 May 2018 16:50:35 +0100 Subject: [PATCH 19/59] (INT) accept false of ID_bool as valid zero value --- src/util/interval.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 08695e1fccb..5d2617ebad8 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1041,8 +1041,8 @@ constant_exprt constant_interval_exprt::zero(const typet &type) { constant_exprt zero = from_integer(mp_integer(0), type); INVARIANT( - zero.is_zero(), // NOT is_zero(zero) (inf. recursion) - "The value created from 0 should be zero"); + zero.is_zero() || (type.id() == ID_bool && zero.is_false()), + "The value created from 0 should be zero or false"); return zero; } From 053c0c416336021c1d42ad7b540d889b1544ca54 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 29 May 2018 16:56:06 +0100 Subject: [PATCH 20/59] (INT) Add ID_bool type preconditions to logical interval operations --- src/util/interval.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 5d2617ebad8..9f169ec50a0 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -251,6 +251,9 @@ tvt constant_interval_exprt::is_definitely_false() const tvt constant_interval_exprt::logical_or(const constant_interval_exprt &o) const { + PRECONDITION(type().id() == ID_bool); + PRECONDITION(o.type().id() == ID_bool); + tvt a = is_definitely_true(); tvt b = o.is_definitely_true(); @@ -259,11 +262,17 @@ tvt constant_interval_exprt::logical_or(const constant_interval_exprt &o) const tvt constant_interval_exprt::logical_and(const constant_interval_exprt &o) const { + PRECONDITION(type().id() == ID_bool); + PRECONDITION(o.type().id() == ID_bool); + return (is_definitely_true() && o.is_definitely_true()); } tvt constant_interval_exprt::logical_xor(const constant_interval_exprt &o) const { + PRECONDITION(type().id() == ID_bool); + PRECONDITION(o.type().id() == ID_bool); + return ( (is_definitely_true() && !o.is_definitely_true()) || (!is_definitely_true() && o.is_definitely_true())); @@ -271,6 +280,8 @@ tvt constant_interval_exprt::logical_xor(const constant_interval_exprt &o) const tvt constant_interval_exprt::logical_not() const { + PRECONDITION(type().id() == ID_bool); + if(is_definitely_true().is_true()) { return tvt(false); From ed2ae28b162ef8f07e2342cefa86aa3db1dcc718 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 29 May 2018 17:09:53 +0100 Subject: [PATCH 21/59] (INT) use tvt_to_interval instead of tv_to_interval in constant_interval_exprt --- src/util/interval.cpp | 40 +++++++++------------------------------- src/util/interval.h | 2 -- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 9f169ec50a0..9c39c7152b4 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -896,60 +896,44 @@ constant_interval_exprt constant_interval_exprt::eval( } if(binary_operator == ID_lt) { - return tv_to_interval(less_than(other)); + return tvt_to_interval(less_than(other)); } if(binary_operator == ID_le) { - return tv_to_interval(less_than_or_equal(other)); + return tvt_to_interval(less_than_or_equal(other)); } if(binary_operator == ID_gt) { - return tv_to_interval(greater_than(other)); + return tvt_to_interval(greater_than(other)); } if(binary_operator == ID_ge) { - return tv_to_interval(greater_than_or_equal(other)); + return tvt_to_interval(greater_than_or_equal(other)); } if(binary_operator == ID_equal) { - return tv_to_interval(equal(other)); + return tvt_to_interval(equal(other)); } if(binary_operator == ID_notequal) { - return tv_to_interval(not_equal(other)); + return tvt_to_interval(not_equal(other)); } if(binary_operator == ID_and) { - return tv_to_interval(logical_and(other)); + return tvt_to_interval(logical_and(other)); } if(binary_operator == ID_or) { - return tv_to_interval(logical_or(other)); + return tvt_to_interval(logical_or(other)); } if(binary_operator == ID_xor) { - return tv_to_interval(logical_xor(other)); + return tvt_to_interval(logical_xor(other)); } return top(); } -constant_interval_exprt -constant_interval_exprt::tv_to_interval(const tvt &tv) const -{ - if(tv.is_true()) - { - return constant_interval_exprt(from_integer(1, type())); - } - if(tv.is_false()) - { - return constant_interval_exprt(zero()); - } - - INVARIANT(tv.is_unknown(), "We excluded the other cases"); - return top(); -} - exprt constant_interval_exprt::generate_shift_expression( const exprt &lhs, const exprt &rhs, @@ -1938,12 +1922,6 @@ bool constant_interval_exprt::is_negative() const return is_negative(get_lower()) && is_negative(get_upper()); } -const constant_interval_exprt -tv_to_interval(const constant_interval_exprt &interval, const tvt &tv) -{ - return interval.tv_to_interval(tv); -} - tvt constant_interval_exprt::is_true(const constant_interval_exprt &a) { return a.is_definitely_true(); diff --git a/src/util/interval.h b/src/util/interval.h index 31e209225ab..8ead560a246 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -122,8 +122,6 @@ class constant_interval_exprt : public binary_exprt tvt logical_xor(const constant_interval_exprt &o) const; tvt logical_not() const; - constant_interval_exprt tv_to_interval(const tvt &tv) const; - /* Binary */ constant_interval_exprt plus(const constant_interval_exprt &o) const; constant_interval_exprt minus(const constant_interval_exprt &other) const; From 8623c59f64c6d42a5b89a77ae9d22de68f8ab95c Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 29 May 2018 17:28:22 +0100 Subject: [PATCH 22/59] (INT) Handle typecasts in constant_interval_exprt --- src/util/interval.cpp | 12 ++++++++++++ src/util/interval.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 9c39c7152b4..cc51e9e6685 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1657,6 +1657,18 @@ constant_interval_exprt::unary_minus(const constant_interval_exprt &a) return a.unary_minus(); } +constant_interval_exprt +constant_interval_exprt::typecast(const typet &type) const +{ + exprt lower = get_lower(); + lower.type() = type; + + exprt upper = get_upper(); + upper.type() = type; + + return constant_interval_exprt(lower, upper, type); +} + /* Binary */ constant_interval_exprt constant_interval_exprt::plus( const constant_interval_exprt &a, diff --git a/src/util/interval.h b/src/util/interval.h index 8ead560a246..143022998e6 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -113,6 +113,8 @@ class constant_interval_exprt : public binary_exprt constant_interval_exprt unary_plus() const; constant_interval_exprt unary_minus() const; + constant_interval_exprt typecast(const typet &type) const; + /* Logical */ tvt is_definitely_true() const; tvt is_definitely_false() const; From f7b19a9f99a33da8ff341da9a9f7d5dc1efbbd21 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:30:05 +0000 Subject: [PATCH 23/59] (INT) Typecast from ID_bool to integer types --- src/util/interval.cpp | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index cc51e9e6685..60c190f144c 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1164,7 +1164,7 @@ bool constant_interval_exprt::is_float(const constant_interval_exprt &interval) bool constant_interval_exprt::is_bitvector(const typet &t) { return t.id() == ID_bv || t.id() == ID_signedbv || t.id() == ID_unsignedbv || - t.id() == ID_pointer || t.id() == ID_bool; + t.id() == ID_c_bool; } bool constant_interval_exprt::is_signed(const typet &t) @@ -1174,8 +1174,7 @@ bool constant_interval_exprt::is_signed(const typet &t) bool constant_interval_exprt::is_unsigned(const typet &t) { - return t.id() == ID_bv || t.id() == ID_unsignedbv || t.id() == ID_pointer || - t.id() == ID_bool; + return t.id() == ID_bv || t.id() == ID_unsignedbv || t.id() == ID_c_bool; } bool constant_interval_exprt::is_signed(const constant_interval_exprt &interval) @@ -1660,13 +1659,28 @@ constant_interval_exprt::unary_minus(const constant_interval_exprt &a) constant_interval_exprt constant_interval_exprt::typecast(const typet &type) const { - exprt lower = get_lower(); - lower.type() = type; + if(this->type().id() == ID_bool && is_int(type)) + { + unsigned lower_num = !has_no_lower_bound() && get_lower().is_true(); + unsigned upper_num = has_no_upper_bound() || get_upper().is_true(); + + INVARIANT(lower_num <= upper_num, ""); + + constant_exprt lower = from_integer(lower_num, type); + constant_exprt upper = from_integer(upper_num, type); + + return constant_interval_exprt(lower, upper, type); + } + else + { + exprt lower = get_lower(); + lower.type() = type; - exprt upper = get_upper(); - upper.type() = type; + exprt upper = get_upper(); + upper.type() = type; - return constant_interval_exprt(lower, upper, type); + return constant_interval_exprt(lower, upper, type); + } } /* Binary */ From 140abbf98cfc18adfc3e901a06afa66d1c4e2359 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:31:01 +0000 Subject: [PATCH 24/59] (INT) Addressing review comments --- src/util/interval.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 60c190f144c..1fec70fdfd8 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1661,15 +1661,15 @@ constant_interval_exprt::typecast(const typet &type) const { if(this->type().id() == ID_bool && is_int(type)) { - unsigned lower_num = !has_no_lower_bound() && get_lower().is_true(); - unsigned upper_num = has_no_upper_bound() || get_upper().is_true(); + bool lower = !has_no_lower_bound() && get_lower().is_true(); + bool upper = has_no_upper_bound() || get_upper().is_true(); - INVARIANT(lower_num <= upper_num, ""); + INVARIANT(!lower || upper, ""); - constant_exprt lower = from_integer(lower_num, type); - constant_exprt upper = from_integer(upper_num, type); + constant_exprt lower_num = from_integer(lower, type); + constant_exprt upper_num = from_integer(upper, type); - return constant_interval_exprt(lower, upper, type); + return constant_interval_exprt(lower_num, upper_num, type); } else { From 9caf96a300b5a9b8ff3b3f548a24952ad7872b0d Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Wed, 30 May 2018 16:47:17 +0100 Subject: [PATCH 25/59] (INT) Add well-formedness checks for constant_interval_exprt --- src/util/interval.h | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/util/interval.h b/src/util/interval.h index 143022998e6..bfd6b5770f8 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -58,8 +58,7 @@ class constant_interval_exprt : public binary_exprt constant_interval_exprt(const exprt &lower, const exprt &upper, typet type) : binary_exprt(lower, ID_constant_interval, upper, type) { - PRECONDITION(type == upper.type()); - PRECONDITION(type == lower.type()); + PRECONDITION(is_well_formed()); } constant_interval_exprt() @@ -85,6 +84,43 @@ class constant_interval_exprt : public binary_exprt { } + bool is_well_formed() const + { + bool b = true; + + const typet &type = this->type(); + const exprt &lower = get_lower(); + const exprt &upper = get_upper(); + + b &= is_numeric() || type.id() == ID_bool || type.is_nil(); + + b &= type == lower.type(); + b &= type == upper.type(); + + b &= is_valid_bound(lower); + b &= is_valid_bound(upper); + + b &= !is_numeric() || less_than_or_equal(lower, upper); + + return b; + } + + bool is_valid_bound(const exprt &expr) const + { + const irep_idt &id = expr.id(); + + bool b = true; + + b &= id == ID_constant || id == ID_min || id == ID_max; + + if(type().id() == ID_bool && id == ID_constant) + { + b &= expr == true_exprt() || expr == false_exprt(); + } + + return b; + } + static constant_interval_exprt tvt_to_interval(const tvt &val); /* Naming scheme From db7df69ba179e80b9052c6ed973e2780f063b254 Mon Sep 17 00:00:00 2001 From: Petr Bauch Date: Thu, 13 Sep 2018 15:06:16 +0100 Subject: [PATCH 26/59] (INT) Extend interval multiplication for extremes --- src/util/interval.cpp | 176 ++++++++++++-------------------- src/util/interval.h | 21 ++-- unit/util/interval/multiply.cpp | 4 +- 3 files changed, 84 insertions(+), 117 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 1fec70fdfd8..948bb66f217 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -473,14 +473,10 @@ constant_interval_exprt constant_interval_exprt::get_extremes( std::vector results; - results.push_back( - generate_expression(a.get_lower(), b.get_lower(), operation)); - results.push_back( - generate_expression(a.get_lower(), b.get_upper(), operation)); - results.push_back( - generate_expression(a.get_upper(), b.get_lower(), operation)); - results.push_back( - generate_expression(a.get_upper(), b.get_upper(), operation)); + generate_expression(a.get_lower(), b.get_lower(), operation, results); + generate_expression(a.get_lower(), b.get_upper(), operation, results); + generate_expression(a.get_upper(), b.get_lower(), operation, results); + generate_expression(a.get_upper(), b.get_upper(), operation, results); for(auto result : results) { @@ -571,152 +567,116 @@ exprt constant_interval_exprt::get_extreme( UNREACHABLE; } -exprt constant_interval_exprt::generate_expression( +void constant_interval_exprt::generate_expression( const exprt &lhs, const exprt &rhs, - const irep_idt &operation) + const irep_idt &operation, + std::vector &collection) { if(operation == ID_mult) { - return generate_multiply_expression(lhs, rhs); + append_multiply_expression(lhs, rhs, collection); } - - if(operation == ID_div) + else if(operation == ID_div) { - return generate_division_expression(lhs, rhs); + collection.push_back(generate_division_expression(lhs, rhs)); } - - if(operation == ID_mod) + else if(operation == ID_mod) { - return generate_modulo_expression(lhs, rhs); + collection.push_back(generate_modulo_expression(lhs, rhs)); } - - if(operation == ID_shl || operation == ID_ashr) + else if(operation == ID_shl || operation == ID_ashr) { - return generate_shift_expression(lhs, rhs, operation); + collection.push_back(generate_shift_expression(lhs, rhs, operation)); } - - UNREACHABLE; } -exprt constant_interval_exprt::generate_multiply_expression( +/// Adds all possible values that may arise from multiplication (more than one, +/// in case of past the type boundary results). +/// \param lower lhs of multiplication +/// \param upper rhs of multiplication +/// \param collection vector of possible values +void constant_interval_exprt::append_multiply_expression( const exprt &lower, - const exprt &upper) + const exprt &upper, + std::vector &collection) { PRECONDITION(lower.type().is_not_nil() && is_numeric(lower.type())); if(is_max(lower)) { - return generate_multiply_expression_max(upper); + append_multiply_expression_max(upper, collection); } - - if(is_max(upper)) + else if(is_max(upper)) { - return generate_multiply_expression_max(lower); + append_multiply_expression_max(lower, collection); } - - if(is_min(lower)) + else if(is_min(lower)) { - return generate_multiply_expression_min(lower, upper); + append_multiply_expression_min(lower, upper, collection); } - - if(is_min(upper)) + else if(is_min(upper)) { - return generate_multiply_expression_min(upper, lower); + append_multiply_expression_min(upper, lower, collection); } + else + { + INVARIANT( + !is_extreme(lower) && !is_extreme(upper), + "We ruled out extreme cases beforehand"); - INVARIANT( - !is_extreme(lower) && !is_extreme(upper), - "We ruled out extreme cases beforehand"); - - auto result = mult_exprt(lower, upper); - return simplified_expr(result); + auto result = mult_exprt(lower, upper); + collection.push_back(simplified_expr(result)); + } } -exprt constant_interval_exprt::generate_multiply_expression_max( - const exprt &expr) +/// Appends interval bounds that could arise from MAX * expr. Accommodates for +/// overflows by over-approximating. +/// \param expr the unknown side of multiplication +/// \param collection vector of collected bounds +void constant_interval_exprt::append_multiply_expression_max( + const exprt &expr, + std::vector &collection) { - if(is_max(expr)) - { - return max_exprt(expr); - } - if(is_min(expr)) { - if(is_negative(expr)) - { - return min_exprt(expr); - } - else - { - INVARIANT(!is_positive(expr), "Min value cannot be >0."); - INVARIANT(is_zero(expr), "Non-negative MIN must be zero."); - - return expr; - } - } - - INVARIANT(!is_extreme(expr), "We ruled out extreme cases"); - - if(is_negative(expr)) - { - return min_exprt(expr); + INVARIANT(!is_positive(expr), "Min value cannot be >0."); + INVARIANT( + is_negative(expr) || is_zero(expr), "Non-negative MIN must be zero."); } if(is_zero(expr)) + collection.push_back(expr); + else { - return expr; + collection.push_back(max_exprt(expr)); + collection.push_back(min_exprt(expr)); } - - if(is_positive(expr)) - { - return max_exprt(expr); - } - - UNREACHABLE; - return nil_exprt(); } -exprt constant_interval_exprt::generate_multiply_expression_min( +/// Appends interval bounds that could arise from MIN * other. Accommodates for +/// overflows by over-approximating. +/// \param min the side known to be MIN for a given type +/// \param other the side of unknown value +/// \param collection reference to the vector of collected boundaries +void constant_interval_exprt::append_multiply_expression_min( const exprt &min, - const exprt &other) + const exprt &other, + std::vector &collection) { PRECONDITION(is_min(min)); + INVARIANT(!is_positive(min), "Min value cannot be >0."); + INVARIANT(is_negative(min) || is_zero(min), "Non-negative MIN must be zero."); - if(is_max(other)) - { - if(is_negative(min)) - { - return min_exprt(min); - } - else - { - INVARIANT(!is_positive(min), "Min value cannot be >0."); - INVARIANT(is_zero(min), "Non-negative MIN must be zero."); - - return min; - } - } - - if(is_min(other)) + if(is_zero(min)) + collection.push_back(min); + else if(is_zero(other)) + collection.push_back(other); + else { - INVARIANT( - !is_positive(min) && !is_positive(other), "Min value cannot be >0."); - INVARIANT( - is_negative(other) || is_zero(other), - "Other was established to be min value, which must be <= 0"); - - if(is_negative(min) && is_negative(other)) - { - return max_exprt(min); - } - - INVARIANT(is_zero(min) || is_zero(other), "Min value must be <= 0"); - return (is_zero(min) ? min : other); + collection.push_back(min_exprt(min)); + collection.push_back(max_exprt(min)); } - - UNREACHABLE; - return nil_exprt(); } exprt constant_interval_exprt::generate_division_expression( diff --git a/src/util/interval.h b/src/util/interval.h index bfd6b5770f8..e949cceae23 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -438,15 +438,22 @@ class constant_interval_exprt : public binary_exprt static exprt abs(const exprt &expr); private: - static exprt generate_expression( + static void generate_expression( const exprt &lhs, const exprt &rhs, - const irep_idt &operation); - static exprt - generate_multiply_expression(const exprt &lower, const exprt &upper); - static exprt generate_multiply_expression_max(const exprt &expr); - static exprt - generate_multiply_expression_min(const exprt &min, const exprt &other); + const irep_idt &operation, + std::vector &collection); + static void append_multiply_expression( + const exprt &lower, + const exprt &upper, + std::vector &collection); + static void append_multiply_expression_max( + const exprt &expr, + std::vector &collection); + static void append_multiply_expression_min( + const exprt &min, + const exprt &other, + std::vector &collection); static exprt generate_division_expression(const exprt &lhs, const exprt &rhs); static exprt generate_modulo_expression(const exprt &lhs, const exprt &rhs); static exprt generate_shift_expression( diff --git a/unit/util/interval/multiply.cpp b/unit/util/interval/multiply.cpp index dfd6361707b..f6093a40bce 100644 --- a/unit/util/interval/multiply.cpp +++ b/unit/util/interval/multiply.cpp @@ -141,12 +141,12 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") CHECK(b.has_no_upper_bound()); } - THEN("The result is [14, INF]") + THEN("The result is [-INF, INF]") { CAPTURE(result); CHECK(result.has_no_upper_bound()); - CHECK(V(result.get_lower()) == 14); + CHECK(result.has_no_lower_bound()); } } } From bbfb1bb1859db02cdedcc11595621ae7ed03b6fd Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:42:33 +0000 Subject: [PATCH 27/59] (INT) Add support for bit field and enums intervals.cpp --- src/util/interval.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 948bb66f217..cc576eef774 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1124,17 +1124,21 @@ bool constant_interval_exprt::is_float(const constant_interval_exprt &interval) bool constant_interval_exprt::is_bitvector(const typet &t) { return t.id() == ID_bv || t.id() == ID_signedbv || t.id() == ID_unsignedbv || - t.id() == ID_c_bool; + t.id() == ID_c_bool || + (t.id() == ID_c_bit_field && is_bitvector(t.subtype())); } bool constant_interval_exprt::is_signed(const typet &t) { - return t.id() == ID_signedbv; + return t.id() == ID_signedbv || + (t.id() == ID_c_bit_field && is_signed(t.subtype())); } bool constant_interval_exprt::is_unsigned(const typet &t) { - return t.id() == ID_bv || t.id() == ID_unsignedbv || t.id() == ID_c_bool; + return t.id() == ID_bv || t.id() == ID_unsignedbv || t.id() == ID_c_bool || + t.id() == ID_c_enum || + (t.id() == ID_c_bit_field && is_unsigned(t.subtype())); } bool constant_interval_exprt::is_signed(const constant_interval_exprt &interval) From fba3a55e70534763c00ab0b0e81c138830e7ad4e Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 18 Jul 2018 15:12:00 +0100 Subject: [PATCH 28/59] (INT) Fix broken interval unit tests --- unit/util/interval/multiply.cpp | 6 +++--- unit/util/interval/subtract.cpp | 21 ++++++++------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/unit/util/interval/multiply.cpp b/unit/util/interval/multiply.cpp index f6093a40bce..dc5ffd6a872 100644 --- a/unit/util/interval/multiply.cpp +++ b/unit/util/interval/multiply.cpp @@ -57,15 +57,15 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") WHEN("One is entirely negative [-2,-5]*[7,11]") { - constant_interval_exprt a(values[-2], values[-5]); + constant_interval_exprt a(values[-5], values[-2]); constant_interval_exprt b(values[7], values[11]); constant_interval_exprt result = a.multiply(b); THEN("Domain is consistent") { - CHECK(V(a.get_lower()) == -2); - CHECK(V(a.get_upper()) == -5); + CHECK(V(a.get_lower()) == -5); + CHECK(V(a.get_upper()) == -2); CHECK(V(b.get_lower()) == 7); CHECK(V(b.get_upper()) == 11); } diff --git a/unit/util/interval/subtract.cpp b/unit/util/interval/subtract.cpp index 18b41fa3bc8..d9b8af0ca5c 100644 --- a/unit/util/interval/subtract.cpp +++ b/unit/util/interval/subtract.cpp @@ -105,12 +105,12 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") SCENARIO("Subtracting unsigned integers") { + auto get_value = [](int x) { return from_integer(x, signedbv_typet(32)); }; + WHEN("Subtracting two constant intervals") { - auto lhs = - constant_interval_exprt(constant_exprt("1010", unsignedbv_typet(32))); - auto rhs = - constant_interval_exprt(constant_exprt("0011", unsignedbv_typet(32))); + auto lhs = constant_interval_exprt(get_value(10)); + auto rhs = constant_interval_exprt(get_value(3)); THEN("it should work") { auto result = lhs.minus(rhs); @@ -123,10 +123,8 @@ SCENARIO("Subtracting unsigned integers") WHEN("Subtracting zero from something") { - auto lhs = - constant_interval_exprt(constant_exprt("1010", unsignedbv_typet(32))); - auto rhs = - constant_interval_exprt(constant_exprt("0", unsignedbv_typet(32))); + auto lhs = constant_interval_exprt(get_value(10)); + auto rhs = constant_interval_exprt(get_value(0)); THEN("it should not give a completely crazy result") { @@ -140,11 +138,8 @@ SCENARIO("Subtracting unsigned integers") WHEN("Subtracting an non-constant interval containing zero") { - auto lhs = - constant_interval_exprt(constant_exprt("1010", unsignedbv_typet(32))); - auto rhs = constant_interval_exprt( - constant_exprt("0", unsignedbv_typet(32)), - constant_exprt("1", unsignedbv_typet(32))); + auto lhs = constant_interval_exprt(get_value(10)); + auto rhs = constant_interval_exprt(get_value(0), get_value(1)); THEN("it should not give a completely crazy result") { auto result = lhs.minus(rhs); From f19ad6a2f1f8db8b795d60316fd0fcbd116a1c4b Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Mon, 23 Jul 2018 16:10:25 +0100 Subject: [PATCH 29/59] (INT) Fix bug with interval typecasts Previously the typecast operator for interval_exprt simply set the type on the bounds; This yielded incorrect results for widening or narrowing casts. This delegates the typecast handling to simplify_expr instead. --- src/util/interval.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index cc576eef774..f4263467f95 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1637,11 +1637,23 @@ constant_interval_exprt::typecast(const typet &type) const } else { - exprt lower = get_lower(); - lower.type() = type; + auto do_typecast = [&type](exprt e) { + if(e.id() == ID_min || e.id() == ID_max) + { + e.type() = type; + } + else + { + e = simplified_expr(typecast_exprt(e, type)); + } + return e; + }; + + exprt lower = do_typecast(get_lower()); + POSTCONDITION(lower.id() == get_lower().id()); - exprt upper = get_upper(); - upper.type() = type; + exprt upper = do_typecast(get_upper()); + POSTCONDITION(upper.id() == get_upper().id()); return constant_interval_exprt(lower, upper, type); } From 8558abd1f8db7cdd730558e53d55762553ca7eb3 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 11 Oct 2019 16:02:45 +0100 Subject: [PATCH 30/59] (INT) Fixup for nil_typet being removed --- src/util/interval.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/util/interval.h b/src/util/interval.h index e949cceae23..f091119073f 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -62,10 +62,7 @@ class constant_interval_exprt : public binary_exprt } constant_interval_exprt() - : constant_interval_exprt( - min_exprt(nil_typet()), - max_exprt(nil_typet()), - nil_typet()) + : constant_interval_exprt(min_exprt(typet()), max_exprt(typet()), typet()) { } From 0eb8cef2ee14a1c9b220f19942fc875a555b9a73 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:06:54 +0000 Subject: [PATCH 31/59] (INT) Fixups post-rebase --- src/util/interval.cpp | 2 - src/util/interval.h | 13 +- unit/util/interval/add.cpp | 29 ++-- unit/util/interval/bitwise.cpp | 4 +- unit/util/interval/comparisons.cpp | 217 +++++++++++++++-------------- unit/util/interval/eval.cpp | 2 +- unit/util/interval/get_extreme.cpp | 38 +++-- unit/util/interval/modulo.cpp | 71 +++++----- unit/util/interval/multiply.cpp | 37 ++--- unit/util/interval/shift.cpp | 23 +-- unit/util/interval/subtract.cpp | 31 ++--- 11 files changed, 211 insertions(+), 256 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index f4263467f95..34161de013c 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -469,8 +469,6 @@ constant_interval_exprt constant_interval_exprt::get_extremes( const constant_interval_exprt &b, const irep_idt &operation) { - constant_interval_exprt result; - std::vector results; generate_expression(a.get_lower(), b.get_lower(), operation, results); diff --git a/src/util/interval.h b/src/util/interval.h index f091119073f..bd154967044 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -55,18 +55,21 @@ class min_exprt : public exprt class constant_interval_exprt : public binary_exprt { public: - constant_interval_exprt(const exprt &lower, const exprt &upper, typet type) + constant_interval_exprt( + const exprt &lower, + const exprt &upper, + const typet type) : binary_exprt(lower, ID_constant_interval, upper, type) { PRECONDITION(is_well_formed()); } - constant_interval_exprt() - : constant_interval_exprt(min_exprt(typet()), max_exprt(typet()), typet()) + constant_interval_exprt(const constant_interval_exprt &x) + : constant_interval_exprt(x.get_lower(), x.get_upper(), x.type()) { } - explicit constant_interval_exprt(const exprt &x) + constant_interval_exprt(const exprt &x) : constant_interval_exprt(x, x, x.type()) { } @@ -97,7 +100,7 @@ class constant_interval_exprt : public binary_exprt b &= is_valid_bound(lower); b &= is_valid_bound(upper); - b &= !is_numeric() || less_than_or_equal(lower, upper); + b &= !is_numeric() || is_bottom() || less_than_or_equal(lower, upper); return b; } diff --git a/unit/util/interval/add.cpp b/unit/util/interval/add.cpp index ac159c94a18..73aee75759f 100644 --- a/unit/util/interval/add.cpp +++ b/unit/util/interval/add.cpp @@ -3,7 +3,7 @@ Author: DiffBlue Limited \*******************************************************************/ -#include +#include #include #include @@ -11,30 +11,21 @@ #include #include -#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) -#define V_(X) (binary2integer(X.c_str(), 2)) +#define V(X) (bvrep2integer(X.get(ID_value).c_str(), 32, true)) +#define V_(X) (bvrep2integer(X.c_str(), 32, true)) +#define CEV(X) (from_integer(mp_integer(X), signedbv_typet(32))) SCENARIO("add interval domain", "[core][analyses][interval][add]") { GIVEN("Two simple signed intervals") { - const typet type = signedbv_typet(32); symbol_tablet symbol_table; namespacet ns(symbol_table); - source_locationt source_location; - - std::map values; - - for(int i = -100; i <= 100; i++) - { - values[i] = from_integer(mp_integer(i), type); - } - WHEN("Both are positive [2,4]+[6,8]") { - constant_interval_exprt left(values[2], values[4]); - constant_interval_exprt right(values[6], values[8]); + constant_interval_exprt left(CEV(2), CEV(4)); + constant_interval_exprt right(CEV(6), CEV(8)); constant_interval_exprt result = left.plus(right); @@ -55,8 +46,8 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") WHEN("One contains infinite [2,4]+[6,INF]") { - constant_interval_exprt left(values[2], values[4]); - constant_interval_exprt right(values[6], max_exprt(type)); + constant_interval_exprt left(CEV(2), CEV(4)); + constant_interval_exprt right(CEV(6), max_exprt(signedbv_typet(32))); constant_interval_exprt result = left.plus(right); @@ -79,8 +70,8 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") WHEN("Both contain infinite [2,INF]+[6,INF]") { - constant_interval_exprt left(values[2], max_exprt(type)); - constant_interval_exprt right(values[6], max_exprt(type)); + constant_interval_exprt left(CEV(2), max_exprt(signedbv_typet(32))); + constant_interval_exprt right(CEV(6), max_exprt(signedbv_typet(32))); constant_interval_exprt result = left.plus(right); diff --git a/unit/util/interval/bitwise.cpp b/unit/util/interval/bitwise.cpp index 0363c1e2cc2..8737956ff5e 100644 --- a/unit/util/interval/bitwise.cpp +++ b/unit/util/interval/bitwise.cpp @@ -3,7 +3,7 @@ Author: DiffBlue Limited \*******************************************************************/ -#include +#include #include #include @@ -61,4 +61,4 @@ SCENARIO("bitwise interval domain", "[core][analyses][interval][bitwise]") constant_interval_exprt(from_integer(2, unsigned_int))); } } -} \ No newline at end of file +} diff --git a/unit/util/interval/comparisons.cpp b/unit/util/interval/comparisons.cpp index 0b2e8322df4..1a838bc0dd1 100644 --- a/unit/util/interval/comparisons.cpp +++ b/unit/util/interval/comparisons.cpp @@ -3,7 +3,7 @@ Author: DiffBlue Limited \*******************************************************************/ -#include +#include #include #include @@ -11,96 +11,99 @@ #include #include -#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) -#define V_(X) (binary2integer(X.c_str(), 2)) +#define V(X) (bvrep2integer(X.get(ID_value).c_str(), 32, true)) +#define V_(X) (bvrep2integer(X.c_str(), 32, true)) +#define CEV(X) (from_integer(mp_integer(X), signedbv_typet(32))) SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") { GIVEN("Two simple signed intervals") { - const typet type = signedbv_typet(32); symbol_tablet symbol_table; namespacet ns(symbol_table); - const typet t = type; - - source_locationt source_location; - - std::map v; - - for(int i = -100; i <= 100; i++) - { - v[i] = from_integer(mp_integer(i), type); - } - WHEN("<, >, <=, >=, ==, != are tested on expressions") { THEN("Require correctness") { - REQUIRE(constant_interval_exprt::less_than(v[0], v[1])); - REQUIRE(constant_interval_exprt::less_than(v[1], v[2])); - REQUIRE(constant_interval_exprt::less_than(v[1], v[100])); - - REQUIRE(constant_interval_exprt::less_than(v[-10], v[1])); - REQUIRE_FALSE(constant_interval_exprt::less_than(v[-10], v[-100])); - REQUIRE(constant_interval_exprt::less_than(v[-10], v[-5])); - REQUIRE(constant_interval_exprt::less_than(v[-10], max_exprt(t))); - REQUIRE(constant_interval_exprt::less_than(v[10], max_exprt(t))); - REQUIRE(constant_interval_exprt::less_than(v[0], max_exprt(t))); - - REQUIRE_FALSE(constant_interval_exprt::less_than(v[-10], min_exprt(t))); - REQUIRE_FALSE(constant_interval_exprt::less_than(v[10], min_exprt(t))); - REQUIRE_FALSE(constant_interval_exprt::less_than(v[0], min_exprt(t))); - - REQUIRE_FALSE( - constant_interval_exprt::less_than(min_exprt(t), min_exprt(t))); - REQUIRE_FALSE( - constant_interval_exprt::less_than(max_exprt(t), min_exprt(t))); - REQUIRE_FALSE( - constant_interval_exprt::less_than(max_exprt(t), max_exprt(t))); - REQUIRE(constant_interval_exprt::less_than(min_exprt(t), max_exprt(t))); - - REQUIRE(constant_interval_exprt::equal(min_exprt(t), min_exprt(t))); - REQUIRE(constant_interval_exprt::not_equal(max_exprt(t), min_exprt(t))); - REQUIRE(constant_interval_exprt::equal(max_exprt(t), max_exprt(t))); - REQUIRE(constant_interval_exprt::not_equal(min_exprt(t), max_exprt(t))); + REQUIRE(constant_interval_exprt::less_than(CEV(0), CEV(1))); + REQUIRE(constant_interval_exprt::less_than(CEV(1), CEV(2))); + REQUIRE(constant_interval_exprt::less_than(CEV(1), CEV(100))); + + REQUIRE(constant_interval_exprt::less_than(CEV(-10), CEV(1))); + REQUIRE_FALSE(constant_interval_exprt::less_than(CEV(-10), CEV(-100))); + REQUIRE(constant_interval_exprt::less_than(CEV(-10), CEV(-5))); + REQUIRE(constant_interval_exprt::less_than( + CEV(-10), max_exprt(signedbv_typet(32)))); + REQUIRE(constant_interval_exprt::less_than( + CEV(10), max_exprt(signedbv_typet(32)))); + REQUIRE(constant_interval_exprt::less_than( + CEV(0), max_exprt(signedbv_typet(32)))); + + REQUIRE_FALSE(constant_interval_exprt::less_than( + CEV(-10), min_exprt(signedbv_typet(32)))); + REQUIRE_FALSE(constant_interval_exprt::less_than( + CEV(10), min_exprt(signedbv_typet(32)))); + REQUIRE_FALSE(constant_interval_exprt::less_than( + CEV(0), min_exprt(signedbv_typet(32)))); + + REQUIRE_FALSE(constant_interval_exprt::less_than( + min_exprt(signedbv_typet(32)), min_exprt(signedbv_typet(32)))); + REQUIRE_FALSE(constant_interval_exprt::less_than( + max_exprt(signedbv_typet(32)), min_exprt(signedbv_typet(32)))); + REQUIRE_FALSE(constant_interval_exprt::less_than( + max_exprt(signedbv_typet(32)), max_exprt(signedbv_typet(32)))); + REQUIRE(constant_interval_exprt::less_than( + min_exprt(signedbv_typet(32)), max_exprt(signedbv_typet(32)))); + + REQUIRE(constant_interval_exprt::equal( + min_exprt(signedbv_typet(32)), min_exprt(signedbv_typet(32)))); + REQUIRE(constant_interval_exprt::not_equal( + max_exprt(signedbv_typet(32)), min_exprt(signedbv_typet(32)))); + REQUIRE(constant_interval_exprt::equal( + max_exprt(signedbv_typet(32)), max_exprt(signedbv_typet(32)))); + REQUIRE(constant_interval_exprt::not_equal( + min_exprt(signedbv_typet(32)), max_exprt(signedbv_typet(32)))); } THEN("") { - REQUIRE_FALSE(constant_interval_exprt::greater_than(v[0], v[1])); - REQUIRE_FALSE(constant_interval_exprt::greater_than(v[1], v[2])); - REQUIRE_FALSE(constant_interval_exprt::greater_than(v[1], v[100])); - - REQUIRE_FALSE(constant_interval_exprt::greater_than(v[-10], v[1])); - REQUIRE(constant_interval_exprt::greater_than(v[-10], v[-100])); - REQUIRE_FALSE(constant_interval_exprt::greater_than(v[-10], v[-5])); - REQUIRE_FALSE( - constant_interval_exprt::greater_than(v[-10], max_exprt(t))); - REQUIRE_FALSE( - constant_interval_exprt::greater_than(v[10], max_exprt(t))); - REQUIRE_FALSE( - constant_interval_exprt::greater_than(v[0], max_exprt(t))); - - REQUIRE(constant_interval_exprt::greater_than(v[-10], min_exprt(t))); - REQUIRE(constant_interval_exprt::greater_than(v[10], min_exprt(t))); - REQUIRE(constant_interval_exprt::greater_than(v[0], min_exprt(t))); - - REQUIRE_FALSE( - constant_interval_exprt::greater_than(min_exprt(t), min_exprt(t))); + REQUIRE_FALSE(constant_interval_exprt::greater_than(CEV(0), CEV(1))); + REQUIRE_FALSE(constant_interval_exprt::greater_than(CEV(1), CEV(2))); + REQUIRE_FALSE(constant_interval_exprt::greater_than(CEV(1), CEV(100))); + + REQUIRE_FALSE(constant_interval_exprt::greater_than(CEV(-10), CEV(1))); + REQUIRE(constant_interval_exprt::greater_than(CEV(-10), CEV(-100))); + REQUIRE_FALSE(constant_interval_exprt::greater_than(CEV(-10), CEV(-5))); + REQUIRE_FALSE(constant_interval_exprt::greater_than( + CEV(-10), max_exprt(signedbv_typet(32)))); + REQUIRE_FALSE(constant_interval_exprt::greater_than( + CEV(10), max_exprt(signedbv_typet(32)))); + REQUIRE_FALSE(constant_interval_exprt::greater_than( + CEV(0), max_exprt(signedbv_typet(32)))); + + REQUIRE(constant_interval_exprt::greater_than( + CEV(-10), min_exprt(signedbv_typet(32)))); + REQUIRE(constant_interval_exprt::greater_than( + CEV(10), min_exprt(signedbv_typet(32)))); + REQUIRE(constant_interval_exprt::greater_than( + CEV(0), min_exprt(signedbv_typet(32)))); + + REQUIRE_FALSE(constant_interval_exprt::greater_than( + min_exprt(signedbv_typet(32)), min_exprt(signedbv_typet(32)))); REQUIRE(constant_interval_exprt::greater_than_or_equal( - min_exprt(t), min_exprt(t))); + min_exprt(signedbv_typet(32)), min_exprt(signedbv_typet(32)))); - REQUIRE( - constant_interval_exprt::greater_than(max_exprt(t), min_exprt(t))); + REQUIRE(constant_interval_exprt::greater_than( + max_exprt(signedbv_typet(32)), min_exprt(signedbv_typet(32)))); REQUIRE(constant_interval_exprt::greater_than_or_equal( - max_exprt(t), min_exprt(t))); + max_exprt(signedbv_typet(32)), min_exprt(signedbv_typet(32)))); - REQUIRE_FALSE( - constant_interval_exprt::greater_than(max_exprt(t), max_exprt(t))); + REQUIRE_FALSE(constant_interval_exprt::greater_than( + max_exprt(signedbv_typet(32)), max_exprt(signedbv_typet(32)))); - REQUIRE_FALSE( - constant_interval_exprt::greater_than(min_exprt(t), max_exprt(t))); + REQUIRE_FALSE(constant_interval_exprt::greater_than( + min_exprt(signedbv_typet(32)), max_exprt(signedbv_typet(32)))); } } @@ -109,14 +112,14 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") THEN("Require correctness") { CHECK( - constant_interval_exprt(v[10], v[20]) < - constant_interval_exprt(v[30], v[40])); + constant_interval_exprt(CEV(10), CEV(20)) < + constant_interval_exprt(CEV(30), CEV(40))); REQUIRE_FALSE( - constant_interval_exprt(v[10], v[30]) < - constant_interval_exprt(v[30], v[40])); + constant_interval_exprt(CEV(10), CEV(30)) < + constant_interval_exprt(CEV(30), CEV(40))); REQUIRE_FALSE( - constant_interval_exprt(v[10], v[20]) > - constant_interval_exprt(v[30], v[40])); + constant_interval_exprt(CEV(10), CEV(20)) > + constant_interval_exprt(CEV(30), CEV(40))); } THEN( @@ -124,20 +127,21 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") "< [30, 40] == unknown") { CHECK( - constant_interval_exprt(v[10], v[29]) - .less_than(constant_interval_exprt(v[30], v[40])) == tvt(true)); + constant_interval_exprt(CEV(10), CEV(29)) + .less_than(constant_interval_exprt(CEV(30), CEV(40))) == tvt(true)); CHECK( - constant_interval_exprt(v[10], v[30]) - .less_than(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(30)) + .less_than(constant_interval_exprt(CEV(30), CEV(40))) == tvt::unknown()); CHECK( - constant_interval_exprt(v[10], v[31]) - .less_than(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(31)) + .less_than(constant_interval_exprt(CEV(30), CEV(40))) == tvt::unknown()); CHECK( - constant_interval_exprt(v[30], v[40]) - .less_than(constant_interval_exprt(v[10], v[29])) == tvt(false)); + constant_interval_exprt(CEV(30), CEV(40)) + .less_than(constant_interval_exprt(CEV(10), CEV(29))) == + tvt(false)); } THEN( @@ -145,21 +149,22 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") "31] > [30, 40] == unknown") { CHECK( - constant_interval_exprt(v[10], v[29]) - .greater_than(constant_interval_exprt(v[30], v[40])) == tvt(false)); + constant_interval_exprt(CEV(10), CEV(29)) + .greater_than(constant_interval_exprt(CEV(30), CEV(40))) == + tvt(false)); CHECK( - constant_interval_exprt(v[10], v[29]) - .greater_than(constant_interval_exprt(v[30], v[40])) == - constant_interval_exprt(v[30], v[40]) - .less_than(constant_interval_exprt(v[10], v[29]))); + constant_interval_exprt(CEV(10), CEV(29)) + .greater_than(constant_interval_exprt(CEV(30), CEV(40))) == + constant_interval_exprt(CEV(30), CEV(40)) + .less_than(constant_interval_exprt(CEV(10), CEV(29)))); CHECK( - constant_interval_exprt(v[10], v[30]) - .greater_than(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(30)) + .greater_than(constant_interval_exprt(CEV(30), CEV(40))) == tvt::unknown()); CHECK( - constant_interval_exprt(v[10], v[31]) - .greater_than(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(31)) + .greater_than(constant_interval_exprt(CEV(30), CEV(40))) == tvt::unknown()); } @@ -168,16 +173,16 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") "<- [30, 40] == unknown") { CHECK( - constant_interval_exprt(v[10], v[29]) - .less_than_or_equal(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(29)) + .less_than_or_equal(constant_interval_exprt(CEV(30), CEV(40))) == tvt(true)); CHECK( - constant_interval_exprt(v[10], v[30]) - .less_than_or_equal(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(30)) + .less_than_or_equal(constant_interval_exprt(CEV(30), CEV(40))) == tvt(true)); CHECK( - constant_interval_exprt(v[10], v[31]) - .less_than_or_equal(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(31)) + .less_than_or_equal(constant_interval_exprt(CEV(30), CEV(40))) == tvt::unknown()); } @@ -186,16 +191,16 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") "31] >= [30, 40] == unknown") { CHECK( - constant_interval_exprt(v[10], v[29]) - .greater_than_or_equal(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(29)) + .greater_than_or_equal(constant_interval_exprt(CEV(30), CEV(40))) == tvt(false)); CHECK( - constant_interval_exprt(v[10], v[30]) - .greater_than_or_equal(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(30)) + .greater_than_or_equal(constant_interval_exprt(CEV(30), CEV(40))) == tvt::unknown()); CHECK( - constant_interval_exprt(v[10], v[31]) - .greater_than_or_equal(constant_interval_exprt(v[30], v[40])) == + constant_interval_exprt(CEV(10), CEV(31)) + .greater_than_or_equal(constant_interval_exprt(CEV(30), CEV(40))) == tvt::unknown()); } } diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp index 2490c9c19ee..d39b6894945 100644 --- a/unit/util/interval/eval.cpp +++ b/unit/util/interval/eval.cpp @@ -3,7 +3,7 @@ Author: DiffBlue Limited \*******************************************************************/ -#include +#include #include #include diff --git a/unit/util/interval/get_extreme.cpp b/unit/util/interval/get_extreme.cpp index 7d501f174bf..71ada31d94a 100644 --- a/unit/util/interval/get_extreme.cpp +++ b/unit/util/interval/get_extreme.cpp @@ -3,7 +3,7 @@ Author: DiffBlue Limited \*******************************************************************/ -#include +#include #include #include @@ -12,33 +12,28 @@ #include #include -#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) -#define V_(X) (binary2integer(X.c_str(), 2)) +#define V(X) (bvrep2integer(X.get(ID_value).c_str(), 32, true)) +#define V_(X) (bvrep2integer(X.c_str(), 32, true)) +#define CEV(X) (from_integer(mp_integer(X), signedbv_typet(32))) SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") { GIVEN("A selection of constant_exprts in a std::vector and map") { - const typet type = signedbv_typet(32); symbol_tablet symbol_table; namespacet ns(symbol_table); - std::map values; std::vector ve; for(int i = -100; i <= 100; i++) { - values[i] = from_integer(mp_integer(i), type); - ve.push_back(from_integer(mp_integer(i), type)); - // values[i] = constant_exprt(std::to_string(i), integer_typet());; - // ve.push_back(exprt(constant_exprt(std::to_string(i), integer_typet()))); + ve.push_back(from_integer(mp_integer(i), signedbv_typet(32))); } - WHEN("-20 <= 20 is tested") { - binary_predicate_exprt op1(values[-20], ID_le, values[20]); + binary_predicate_exprt op1(CEV(-20), ID_le, CEV(20)); bool interval_eval = - constant_interval_exprt::less_than_or_equal(values[-20], values[20]); + constant_interval_exprt::less_than_or_equal(CEV(-20), CEV(20)); simplify(op1, ns); THEN("Require it is TRUE") @@ -50,9 +45,9 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") WHEN("20 <= -20 is tested") { - binary_predicate_exprt op1(values[20], ID_le, values[-20]); + binary_predicate_exprt op1(CEV(20), ID_le, CEV(-20)); bool interval_eval = - constant_interval_exprt::less_than_or_equal(values[20], values[-20]); + constant_interval_exprt::less_than_or_equal(CEV(20), CEV(-20)); simplify(op1, ns); THEN("Require it is FALSE") @@ -64,9 +59,9 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") WHEN("-20 <= -20 is tested") { - binary_predicate_exprt op1(values[-20], ID_le, values[-20]); + binary_predicate_exprt op1(CEV(-20), ID_le, CEV(-20)); bool interval_eval = - constant_interval_exprt::less_than_or_equal(values[-20], values[-20]); + constant_interval_exprt::less_than_or_equal(CEV(-20), CEV(-20)); simplify(op1, ns); @@ -74,13 +69,13 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") { REQUIRE(op1.is_true()); REQUIRE(interval_eval); - REQUIRE(constant_interval_exprt::equal(values[1], values[1])); + REQUIRE(constant_interval_exprt::equal(CEV(1), CEV(1))); } } WHEN("Two are selected and min found [20, -20]") { - std::vector selected = {values[20], values[-20]}; + std::vector selected = {CEV(20), CEV(-20)}; exprt min = constant_interval_exprt::get_extreme(selected, true); exprt max = constant_interval_exprt::get_extreme(selected, false); @@ -96,8 +91,7 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") WHEN("Four are selected and min found [-20, 0, 20, 50]") { - std::vector selected = { - values[-20], values[0], values[50], values[20]}; + std::vector selected = {CEV(-20), CEV(0), CEV(50), CEV(20)}; exprt min = constant_interval_exprt::get_extreme(selected, true); exprt max = constant_interval_exprt::get_extreme(selected, false); @@ -111,7 +105,7 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") WHEN("One is selected [-100]") { - std::vector selected = {values[-100]}; + std::vector selected = {CEV(-100)}; exprt min = constant_interval_exprt::get_extreme(selected, true); exprt max = constant_interval_exprt::get_extreme(selected, false); @@ -126,7 +120,7 @@ SCENARIO("get extreme exprt value", "[core][analyses][interval][get_extreme]") WHEN("Five are selected [20, 30, 15, 0, -100]") { std::vector selected = { - values[20], values[30], values[15], values[0], values[-100]}; + CEV(20), CEV(30), CEV(15), CEV(0), CEV(-100)}; exprt min = constant_interval_exprt::get_extreme(selected, true); exprt max = constant_interval_exprt::get_extreme(selected, false); diff --git a/unit/util/interval/modulo.cpp b/unit/util/interval/modulo.cpp index 4999daed88f..0095e473c10 100644 --- a/unit/util/interval/modulo.cpp +++ b/unit/util/interval/modulo.cpp @@ -3,7 +3,7 @@ Author: DiffBlue Limited \*******************************************************************/ -#include +#include #include #include @@ -11,71 +11,62 @@ #include #include -#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) -#define V_(X) (binary2integer(X.c_str(), 2)) +#define V(X) (bvrep2integer(X.get(ID_value).c_str(), 32, true)) +#define V_(X) (bvrep2integer(X.c_str(), 32, true)) +#define CEV(X) (from_integer(mp_integer(X), signedbv_typet(32))) SCENARIO("modulo interval domain", "[core][analyses][interval][modulo]") { GIVEN("Two simple signed intervals") { - const typet type = signedbv_typet(32); symbol_tablet symbol_table; namespacet ns(symbol_table); - source_locationt source_location; - - std::map v; - - for(int i = -100; i <= 100; i++) - { - v[i] = from_integer(mp_integer(i), type); - } - WHEN("Positive RHS") { THEN("Ensure result is consistent.") { REQUIRE( - constant_interval_exprt(v[10], v[20]) - .modulo(constant_interval_exprt(v[5], v[5])) == - constant_interval_exprt(v[0], v[4])); + constant_interval_exprt(CEV(10), CEV(20)) + .modulo(constant_interval_exprt(CEV(5), CEV(5))) == + constant_interval_exprt(CEV(0), CEV(4))); REQUIRE( - constant_interval_exprt(v[10], v[20]) - .modulo(constant_interval_exprt(v[4], v[5])) == - constant_interval_exprt(v[0], v[4])); + constant_interval_exprt(CEV(10), CEV(20)) + .modulo(constant_interval_exprt(CEV(4), CEV(5))) == + constant_interval_exprt(CEV(0), CEV(4))); REQUIRE( - constant_interval_exprt(v[10], v[20]) - .modulo(constant_interval_exprt(v[0], v[5])) == - constant_interval_exprt::top(type)); + constant_interval_exprt(CEV(10), CEV(20)) + .modulo(constant_interval_exprt(CEV(0), CEV(5))) == + constant_interval_exprt::top(signedbv_typet(32))); REQUIRE( - constant_interval_exprt(v[10], v[20]) - .modulo(constant_interval_exprt(v[-5], v[5])) == - constant_interval_exprt::top(type)); + constant_interval_exprt(CEV(10), CEV(20)) + .modulo(constant_interval_exprt(CEV(-5), CEV(5))) == + constant_interval_exprt::top(signedbv_typet(32))); REQUIRE( - constant_interval_exprt(v[-10], v[20]) - .modulo(constant_interval_exprt(v[0], v[5])) == - constant_interval_exprt::top(type)); + constant_interval_exprt(CEV(-10), CEV(20)) + .modulo(constant_interval_exprt(CEV(0), CEV(5))) == + constant_interval_exprt::top(signedbv_typet(32))); REQUIRE( - constant_interval_exprt(v[-20], v[-10]) - .modulo(constant_interval_exprt(v[0], v[5])) == - constant_interval_exprt::top(type)); + constant_interval_exprt(CEV(-20), CEV(-10)) + .modulo(constant_interval_exprt(CEV(0), CEV(5))) == + constant_interval_exprt::top(signedbv_typet(32))); REQUIRE( - constant_interval_exprt(v[-20], v[-10]) - .modulo(constant_interval_exprt(v[1], v[1])) == - constant_interval_exprt(v[0])); + constant_interval_exprt(CEV(-20), CEV(-10)) + .modulo(constant_interval_exprt(CEV(1), CEV(1))) == + constant_interval_exprt(CEV(0))); REQUIRE( - constant_interval_exprt(v[30], v[50]) - .modulo(constant_interval_exprt(v[2], v[2])) == - constant_interval_exprt(v[0], v[1])); + constant_interval_exprt(CEV(30), CEV(50)) + .modulo(constant_interval_exprt(CEV(2), CEV(2))) == + constant_interval_exprt(CEV(0), CEV(1))); // Problems REQUIRE( - constant_interval_exprt(v[30], max_exprt(type)) - .modulo(constant_interval_exprt(v[2], v[2])) == - constant_interval_exprt(v[0], v[1])); + constant_interval_exprt(CEV(30), max_exprt(signedbv_typet(32))) + .modulo(constant_interval_exprt(CEV(2), CEV(2))) == + constant_interval_exprt(CEV(0), CEV(1))); } } } diff --git a/unit/util/interval/multiply.cpp b/unit/util/interval/multiply.cpp index dc5ffd6a872..7214e1ccf38 100644 --- a/unit/util/interval/multiply.cpp +++ b/unit/util/interval/multiply.cpp @@ -3,7 +3,7 @@ Author: DiffBlue Limited \*******************************************************************/ -#include +#include #include #include @@ -11,30 +11,21 @@ #include #include -#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) -#define V_(X) (binary2integer(X.c_str(), 2)) +#define V(X) (bvrep2integer(X.get(ID_value).c_str(), 32, true)) +#define V_(X) (bvrep2integer(X.c_str(), 32, true)) +#define CEV(X) (from_integer(mp_integer(X), signedbv_typet(32))) SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") { GIVEN("A selection of constant_exprts in a std::vector and map") { - const typet type = signedbv_typet(32); symbol_tablet symbol_table; namespacet ns(symbol_table); - std::map values; - std::vector ve; - - for(int i = -100; i <= 100; i++) - { - values[i] = from_integer(mp_integer(i), type); - ve.push_back(exprt(from_integer(mp_integer(i), type))); - } - WHEN("Both are positive [2,5]*[7,11]") { - constant_interval_exprt a(values[2], values[5]); - constant_interval_exprt b(values[7], values[11]); + constant_interval_exprt a(CEV(2), CEV(5)); + constant_interval_exprt b(CEV(7), CEV(11)); constant_interval_exprt result = a.multiply(b); @@ -57,8 +48,8 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") WHEN("One is entirely negative [-2,-5]*[7,11]") { - constant_interval_exprt a(values[-5], values[-2]); - constant_interval_exprt b(values[7], values[11]); + constant_interval_exprt a(CEV(-5), CEV(-2)); + constant_interval_exprt b(CEV(7), CEV(11)); constant_interval_exprt result = a.multiply(b); @@ -81,8 +72,8 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") WHEN("Range contains and extends from zero [-2,5]*[7,11]") { - constant_interval_exprt a(values[-2], values[5]); - constant_interval_exprt b(values[7], values[11]); + constant_interval_exprt a(CEV(-2), CEV(5)); + constant_interval_exprt b(CEV(7), CEV(11)); constant_interval_exprt result = a.multiply(b); @@ -105,8 +96,8 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") WHEN("One domain is infinite and other crosses zero [-2,5]*[7,INF]") { - constant_interval_exprt a(values[-2], values[5]); - constant_interval_exprt b(values[7], max_exprt(type)); + constant_interval_exprt a(CEV(-2), CEV(5)); + constant_interval_exprt b(CEV(7), max_exprt(signedbv_typet(32))); constant_interval_exprt result = a.multiply(b); @@ -129,8 +120,8 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") WHEN("One domain is infinite and other is positive [2,5]*[7,INF]") { - constant_interval_exprt a(values[2], values[5]); - constant_interval_exprt b(values[7], max_exprt(type)); + constant_interval_exprt a(CEV(2), CEV(5)); + constant_interval_exprt b(CEV(7), max_exprt(signedbv_typet(32))); constant_interval_exprt result = a.multiply(b); THEN("Domain is consistent") diff --git a/unit/util/interval/shift.cpp b/unit/util/interval/shift.cpp index 33e2b73f5c9..3813bf97bbc 100644 --- a/unit/util/interval/shift.cpp +++ b/unit/util/interval/shift.cpp @@ -3,7 +3,7 @@ Author: DiffBlue Limited \*******************************************************************/ -#include +#include #include #include @@ -11,34 +11,25 @@ #include #include -#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) -#define V_(X) (binary2integer(X.c_str(), 2)) +#define V(X) (bvrep2integer(X.get(ID_value).c_str(), 32, true)) +#define V_(X) (bvrep2integer(X.c_str(), 32, true)) +#define CEV(X) (from_integer(mp_integer(X), signedbv_typet(32))) SCENARIO("shift interval domain", "[core][analyses][interval][shift]") { GIVEN("Two simple signed intervals") { - const typet type = signedbv_typet(32); symbol_tablet symbol_table; namespacet ns(symbol_table); - source_locationt source_location; - - std::map v; - - for(int i = -100; i <= 100; i++) - { - v[i] = from_integer(mp_integer(i), type); - } - WHEN("Something") { THEN("Something else") { REQUIRE( - constant_interval_exprt(v[4], v[8]) - .left_shift(constant_interval_exprt(v[1])) == - constant_interval_exprt(v[8], v[16])); + constant_interval_exprt(CEV(4), CEV(8)) + .left_shift(constant_interval_exprt(CEV(1))) == + constant_interval_exprt(CEV(8), CEV(16))); } } } diff --git a/unit/util/interval/subtract.cpp b/unit/util/interval/subtract.cpp index d9b8af0ca5c..e9857e0f47a 100644 --- a/unit/util/interval/subtract.cpp +++ b/unit/util/interval/subtract.cpp @@ -3,7 +3,7 @@ Author: DiffBlue Limited \*******************************************************************/ -#include +#include #include #include @@ -11,30 +11,21 @@ #include #include -#define V(X) (binary2integer(X.get(ID_value).c_str(), 2)) -#define V_(X) (binary2integer(X.c_str(), 2)) +#define V(X) (bvrep2integer(X.get(ID_value).c_str(), 32, true)) +#define V_(X) (bvrep2integer(X.c_str(), 32, true)) +#define CEV(X) (from_integer(mp_integer(X), signedbv_typet(32))) SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") { GIVEN("Two simple signed intervals") { - const typet type = signedbv_typet(32); symbol_tablet symbol_table; namespacet ns(symbol_table); - source_locationt source_location; - - std::map values; - - for(int i = -100; i <= 100; i++) - { - values[i] = from_integer(mp_integer(i), type); - } - WHEN("The result is positive [6,8]-[2,4]") { - constant_interval_exprt left(values[6], values[8]); - constant_interval_exprt right(values[2], values[4]); + constant_interval_exprt left(CEV(6), CEV(8)); + constant_interval_exprt right(CEV(2), CEV(4)); constant_interval_exprt result = left.minus(right); @@ -55,8 +46,8 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") WHEN("One contains infinite [2,4]-[6,INF]") { - constant_interval_exprt left(values[2], values[4]); - constant_interval_exprt right(values[6], max_exprt(type)); + constant_interval_exprt left(CEV(2), CEV(4)); + constant_interval_exprt right(CEV(6), max_exprt(signedbv_typet(32))); constant_interval_exprt result = left.minus(right); @@ -79,8 +70,8 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") WHEN("Both contain infinite [2,INF]-[6,INF]") { - constant_interval_exprt left(values[2], max_exprt(type)); - constant_interval_exprt right(values[6], max_exprt(type)); + constant_interval_exprt left(CEV(2), max_exprt(signedbv_typet(32))); + constant_interval_exprt right(CEV(6), max_exprt(signedbv_typet(32))); constant_interval_exprt result = left.minus(right); @@ -151,4 +142,4 @@ SCENARIO("Subtracting unsigned integers") REQUIRE(maybe_upper.value() == 10); } } -} \ No newline at end of file +} From 3477c38008f0ee4163f9bdc8917ffa1a57da9677 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 9 Dec 2019 22:28:47 +0000 Subject: [PATCH 32/59] Fixes for the linter. --- src/util/interval.h | 6 +++--- unit/util/interval/module_dependencies.txt | 3 +++ unit/util/interval/subtract.cpp | 4 +++- 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 unit/util/interval/module_dependencies.txt diff --git a/src/util/interval.h b/src/util/interval.h index bd154967044..cadb323f19c 100644 --- a/src/util/interval.h +++ b/src/util/interval.h @@ -5,8 +5,8 @@ Author: Daniel Neville (2017) \*******************************************************************/ -#ifndef SRC_ANALYSES_INTERVAL_H_ -#define SRC_ANALYSES_INTERVAL_H_ +#ifndef CPROVER_UTIL_INTERVAL_H +#define CPROVER_UTIL_INTERVAL_H #include #include @@ -69,7 +69,7 @@ class constant_interval_exprt : public binary_exprt { } - constant_interval_exprt(const exprt &x) + explicit constant_interval_exprt(const exprt &x) : constant_interval_exprt(x, x, x.type()) { } diff --git a/unit/util/interval/module_dependencies.txt b/unit/util/interval/module_dependencies.txt new file mode 100644 index 00000000000..253b4a5d0f0 --- /dev/null +++ b/unit/util/interval/module_dependencies.txt @@ -0,0 +1,3 @@ +testing-utils +util + diff --git a/unit/util/interval/subtract.cpp b/unit/util/interval/subtract.cpp index e9857e0f47a..84f2386493d 100644 --- a/unit/util/interval/subtract.cpp +++ b/unit/util/interval/subtract.cpp @@ -94,7 +94,9 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") } } -SCENARIO("Subtracting unsigned integers") +SCENARIO( + "Subtracting unsigned integers", + "[core][analyses][interval][subtract]") { auto get_value = [](int x) { return from_integer(x, signedbv_typet(32)); }; From 368fc662d84628916028a90e0881724c5e19e786 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 22 May 2020 11:41:15 +0100 Subject: [PATCH 33/59] Sort makefile includes --- unit/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unit/Makefile b/unit/Makefile index 80e00dc5cb6..82d197402b0 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -77,14 +77,14 @@ SRC += analyses/ai/ai.cpp \ util/format_number_range.cpp \ util/get_base_name.cpp \ util/graph.cpp \ - util/interval/multiply.cpp \ util/interval/add.cpp \ + util/interval/bitwise.cpp \ + util/interval/comparisons.cpp \ util/interval/get_extreme.cpp \ - util/interval/subtract.cpp \ util/interval/modulo.cpp \ + util/interval/multiply.cpp \ util/interval/shift.cpp \ - util/interval/comparisons.cpp \ - util/interval/bitwise.cpp \ + util/interval/subtract.cpp \ util/interval_constraint.cpp \ util/interval_union.cpp \ util/irep.cpp \ From ea981ce9e725d914f31d7f76c52ef512ce178d42 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 22 May 2020 11:42:15 +0100 Subject: [PATCH 34/59] Add missing unit test to the Makefile --- unit/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/unit/Makefile b/unit/Makefile index 82d197402b0..943db32ae00 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -80,6 +80,7 @@ SRC += analyses/ai/ai.cpp \ util/interval/add.cpp \ util/interval/bitwise.cpp \ util/interval/comparisons.cpp \ + util/interval/eval.cpp \ util/interval/get_extreme.cpp \ util/interval/modulo.cpp \ util/interval/multiply.cpp \ From 0e5f919c26ffdb6dbd8bf8cea64497110f795215 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 22 May 2020 14:49:03 +0100 Subject: [PATCH 35/59] Adapt unit tests for consistent interface Methods that result in a new interval are static, const getters of an existing interval are member methods --- unit/util/interval/add.cpp | 9 ++++--- unit/util/interval/bitwise.cpp | 14 +++++----- unit/util/interval/modulo.cpp | 45 ++++++++++++++++++++------------- unit/util/interval/multiply.cpp | 17 +++++++------ unit/util/interval/shift.cpp | 5 ++-- unit/util/interval/subtract.cpp | 15 ++++++----- 6 files changed, 61 insertions(+), 44 deletions(-) diff --git a/unit/util/interval/add.cpp b/unit/util/interval/add.cpp index 73aee75759f..3b6aa07c88e 100644 --- a/unit/util/interval/add.cpp +++ b/unit/util/interval/add.cpp @@ -27,7 +27,8 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") constant_interval_exprt left(CEV(2), CEV(4)); constant_interval_exprt right(CEV(6), CEV(8)); - constant_interval_exprt result = left.plus(right); + constant_interval_exprt result = + constant_interval_exprt::plus(left, right); THEN("Domain is consistent") { @@ -49,7 +50,8 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") constant_interval_exprt left(CEV(2), CEV(4)); constant_interval_exprt right(CEV(6), max_exprt(signedbv_typet(32))); - constant_interval_exprt result = left.plus(right); + constant_interval_exprt result = + constant_interval_exprt::plus(left, right); THEN("Domain is consistent") { @@ -73,7 +75,8 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") constant_interval_exprt left(CEV(2), max_exprt(signedbv_typet(32))); constant_interval_exprt right(CEV(6), max_exprt(signedbv_typet(32))); - constant_interval_exprt result = left.plus(right); + constant_interval_exprt result = + constant_interval_exprt::plus(left, right); THEN("Domain is consistent") { diff --git a/unit/util/interval/bitwise.cpp b/unit/util/interval/bitwise.cpp index 8737956ff5e..6eceb86f920 100644 --- a/unit/util/interval/bitwise.cpp +++ b/unit/util/interval/bitwise.cpp @@ -24,14 +24,14 @@ SCENARIO("bitwise interval domain", "[core][analyses][interval][bitwise]") THEN("Bitwise or should yield bitwise representation of 13") { REQUIRE( - five.bitwise_or(nine) == + constant_interval_exprt::bitwise_or(five, nine) == constant_interval_exprt(from_integer(13, unsigned_int))); } THEN("Bitwise and should yield bitwise representation of 1") { REQUIRE( - five.bitwise_and(nine) == + constant_interval_exprt::bitwise_and(five, nine) == constant_interval_exprt(from_integer(1, unsigned_int))); REQUIRE( (five & nine) == @@ -41,23 +41,23 @@ SCENARIO("bitwise interval domain", "[core][analyses][interval][bitwise]") THEN("Bitwise xor should yield bitwise representation of 12") { REQUIRE( - five.bitwise_xor(nine) == + constant_interval_exprt::bitwise_xor(five, nine) == constant_interval_exprt(from_integer(12, unsigned_int))); } THEN("Left shift on the 5 should produce 10") { REQUIRE( - five.left_shift( - constant_interval_exprt(from_integer(1, unsigned_int))) == + constant_interval_exprt::left_shift( + five, constant_interval_exprt(from_integer(1, unsigned_int))) == constant_interval_exprt(from_integer(10, unsigned_int))); } THEN("Right shift on the 5 should produce 2") { REQUIRE( - five.right_shift( - constant_interval_exprt(from_integer(1, unsigned_int))) == + constant_interval_exprt::right_shift( + five, constant_interval_exprt(from_integer(1, unsigned_int))) == constant_interval_exprt(from_integer(2, unsigned_int))); } } diff --git a/unit/util/interval/modulo.cpp b/unit/util/interval/modulo.cpp index 0095e473c10..daf1214abf7 100644 --- a/unit/util/interval/modulo.cpp +++ b/unit/util/interval/modulo.cpp @@ -27,45 +27,54 @@ SCENARIO("modulo interval domain", "[core][analyses][interval][modulo]") THEN("Ensure result is consistent.") { REQUIRE( - constant_interval_exprt(CEV(10), CEV(20)) - .modulo(constant_interval_exprt(CEV(5), CEV(5))) == + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(10), CEV(20)), + constant_interval_exprt(CEV(5), CEV(5))) == constant_interval_exprt(CEV(0), CEV(4))); REQUIRE( - constant_interval_exprt(CEV(10), CEV(20)) - .modulo(constant_interval_exprt(CEV(4), CEV(5))) == + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(10), CEV(20)), + constant_interval_exprt(CEV(4), CEV(5))) == constant_interval_exprt(CEV(0), CEV(4))); REQUIRE( - constant_interval_exprt(CEV(10), CEV(20)) - .modulo(constant_interval_exprt(CEV(0), CEV(5))) == + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(10), CEV(20)), + constant_interval_exprt(CEV(0), CEV(5))) == constant_interval_exprt::top(signedbv_typet(32))); REQUIRE( - constant_interval_exprt(CEV(10), CEV(20)) - .modulo(constant_interval_exprt(CEV(-5), CEV(5))) == + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(10), CEV(20)), + constant_interval_exprt(CEV(-5), CEV(5))) == constant_interval_exprt::top(signedbv_typet(32))); REQUIRE( - constant_interval_exprt(CEV(-10), CEV(20)) - .modulo(constant_interval_exprt(CEV(0), CEV(5))) == + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(-10), CEV(20)), + constant_interval_exprt(CEV(0), CEV(5))) == constant_interval_exprt::top(signedbv_typet(32))); REQUIRE( - constant_interval_exprt(CEV(-20), CEV(-10)) - .modulo(constant_interval_exprt(CEV(0), CEV(5))) == + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(-20), CEV(-10)), + constant_interval_exprt(CEV(0), CEV(5))) == constant_interval_exprt::top(signedbv_typet(32))); REQUIRE( - constant_interval_exprt(CEV(-20), CEV(-10)) - .modulo(constant_interval_exprt(CEV(1), CEV(1))) == + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(-20), CEV(-10)), + constant_interval_exprt(CEV(1), CEV(1))) == constant_interval_exprt(CEV(0))); REQUIRE( - constant_interval_exprt(CEV(30), CEV(50)) - .modulo(constant_interval_exprt(CEV(2), CEV(2))) == + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(30), CEV(50)), + constant_interval_exprt(CEV(2), CEV(2))) == constant_interval_exprt(CEV(0), CEV(1))); // Problems REQUIRE( - constant_interval_exprt(CEV(30), max_exprt(signedbv_typet(32))) - .modulo(constant_interval_exprt(CEV(2), CEV(2))) == + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(30), max_exprt(signedbv_typet(32))), + constant_interval_exprt(CEV(2), CEV(2))) == constant_interval_exprt(CEV(0), CEV(1))); } } diff --git a/unit/util/interval/multiply.cpp b/unit/util/interval/multiply.cpp index 7214e1ccf38..8eda40399d8 100644 --- a/unit/util/interval/multiply.cpp +++ b/unit/util/interval/multiply.cpp @@ -27,7 +27,7 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") constant_interval_exprt a(CEV(2), CEV(5)); constant_interval_exprt b(CEV(7), CEV(11)); - constant_interval_exprt result = a.multiply(b); + constant_interval_exprt result = constant_interval_exprt::multiply(a, b); THEN("Domain is consistent") { @@ -51,7 +51,7 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") constant_interval_exprt a(CEV(-5), CEV(-2)); constant_interval_exprt b(CEV(7), CEV(11)); - constant_interval_exprt result = a.multiply(b); + constant_interval_exprt result = constant_interval_exprt::multiply(a, b); THEN("Domain is consistent") { @@ -75,7 +75,7 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") constant_interval_exprt a(CEV(-2), CEV(5)); constant_interval_exprt b(CEV(7), CEV(11)); - constant_interval_exprt result = a.multiply(b); + constant_interval_exprt result = constant_interval_exprt::multiply(a, b); THEN("Domain is consistent") { @@ -99,22 +99,23 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") constant_interval_exprt a(CEV(-2), CEV(5)); constant_interval_exprt b(CEV(7), max_exprt(signedbv_typet(32))); - constant_interval_exprt result = a.multiply(b); + constant_interval_exprt result = constant_interval_exprt::multiply(a, b); THEN("Domain is consistent") { CHECK(V(a.get_lower()) == -2); CHECK(V(a.get_upper()) == 5); CHECK(V(b.get_lower()) == 7); - CHECK(constant_interval_exprt::is_max(b.get_upper())); + + CHECK(b.has_no_upper_bound()); } CAPTURE(result); THEN("The result is [-INF, INF]") { - CHECK(constant_interval_exprt::is_max(result.get_upper())); - CHECK(constant_interval_exprt::is_min(result.get_lower())); + CHECK(result.has_no_upper_bound()); + CHECK(result.has_no_lower_bound()); } } @@ -122,7 +123,7 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") { constant_interval_exprt a(CEV(2), CEV(5)); constant_interval_exprt b(CEV(7), max_exprt(signedbv_typet(32))); - constant_interval_exprt result = a.multiply(b); + constant_interval_exprt result = constant_interval_exprt::multiply(a, b); THEN("Domain is consistent") { diff --git a/unit/util/interval/shift.cpp b/unit/util/interval/shift.cpp index 3813bf97bbc..35ff76030ee 100644 --- a/unit/util/interval/shift.cpp +++ b/unit/util/interval/shift.cpp @@ -27,8 +27,9 @@ SCENARIO("shift interval domain", "[core][analyses][interval][shift]") THEN("Something else") { REQUIRE( - constant_interval_exprt(CEV(4), CEV(8)) - .left_shift(constant_interval_exprt(CEV(1))) == + constant_interval_exprt::left_shift( + constant_interval_exprt(CEV(4), CEV(8)), + constant_interval_exprt(CEV(1))) == constant_interval_exprt(CEV(8), CEV(16))); } } diff --git a/unit/util/interval/subtract.cpp b/unit/util/interval/subtract.cpp index 84f2386493d..16acd1d213a 100644 --- a/unit/util/interval/subtract.cpp +++ b/unit/util/interval/subtract.cpp @@ -27,7 +27,8 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") constant_interval_exprt left(CEV(6), CEV(8)); constant_interval_exprt right(CEV(2), CEV(4)); - constant_interval_exprt result = left.minus(right); + constant_interval_exprt result = + constant_interval_exprt::minus(left, right); THEN("Domain is consistent") { @@ -49,7 +50,8 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") constant_interval_exprt left(CEV(2), CEV(4)); constant_interval_exprt right(CEV(6), max_exprt(signedbv_typet(32))); - constant_interval_exprt result = left.minus(right); + constant_interval_exprt result = + constant_interval_exprt::minus(left, right); THEN("Domain is consistent") { @@ -73,7 +75,8 @@ SCENARIO("subtract interval domain", "[core][analyses][interval][subtract]") constant_interval_exprt left(CEV(2), max_exprt(signedbv_typet(32))); constant_interval_exprt right(CEV(6), max_exprt(signedbv_typet(32))); - constant_interval_exprt result = left.minus(right); + constant_interval_exprt result = + constant_interval_exprt::minus(left, right); THEN("Domain is consistent") { @@ -106,7 +109,7 @@ SCENARIO( auto rhs = constant_interval_exprt(get_value(3)); THEN("it should work") { - auto result = lhs.minus(rhs); + auto result = constant_interval_exprt::minus(lhs, rhs); REQUIRE(result.is_single_value_interval()); auto maybe_lower = numeric_cast(result.get_lower()); REQUIRE(maybe_lower.has_value()); @@ -121,7 +124,7 @@ SCENARIO( THEN("it should not give a completely crazy result") { - auto result = lhs.minus(rhs); + auto result = constant_interval_exprt::minus(lhs, rhs); REQUIRE(result.is_single_value_interval()); auto maybe_lower = numeric_cast(result.get_lower()); REQUIRE(maybe_lower.has_value()); @@ -135,7 +138,7 @@ SCENARIO( auto rhs = constant_interval_exprt(get_value(0), get_value(1)); THEN("it should not give a completely crazy result") { - auto result = lhs.minus(rhs); + auto result = constant_interval_exprt::minus(lhs, rhs); auto maybe_lower = numeric_cast(result.get_lower()); REQUIRE(maybe_lower.has_value()); REQUIRE(maybe_lower.value() == 9); From 1cd26b4214e7f273adb4c28c0db8e7af585aaadf Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 22 May 2020 17:55:47 +0100 Subject: [PATCH 36/59] Add tests for divide --- unit/Makefile | 1 + unit/util/interval/divide.cpp | 98 +++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/unit/Makefile b/unit/Makefile index 943db32ae00..c1ce7f42531 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -80,6 +80,7 @@ SRC += analyses/ai/ai.cpp \ util/interval/add.cpp \ util/interval/bitwise.cpp \ util/interval/comparisons.cpp \ + util/interval/divide.cpp \ util/interval/eval.cpp \ util/interval/get_extreme.cpp \ util/interval/modulo.cpp \ diff --git a/unit/util/interval/divide.cpp b/unit/util/interval/divide.cpp index e69de29bb2d..db436f9c2e6 100644 --- a/unit/util/interval/divide.cpp +++ b/unit/util/interval/divide.cpp @@ -0,0 +1,98 @@ +/*******************************************************************\ + Module: Unit tests for variable/sensitivity/abstract_object::merge + Author: Diffblue Ltd. +\*******************************************************************/ + +#include +#include +#include +#include + +int value_of(const constant_interval_exprt &interval) +{ + REQUIRE(interval.is_single_value_interval()); + const auto value = numeric_cast(interval.get_upper()); + REQUIRE(value.has_value()); + return *value; +} + +bool matching_range( + const constant_interval_exprt &actual, + const constant_interval_exprt &expected) +{ + return actual.get_upper() == expected.get_upper() && + actual.get_lower() == expected.get_lower(); +} + +TEST_CASE("interval::divide", "[core][util][interval][divide]") +{ + cbmc_invariants_should_throwt invariants_throw; + const signedbv_typet &signed_int_type = signedbv_typet(32); + const auto zero = from_integer(0, signed_int_type); + const auto one = from_integer(1, signed_int_type); + const auto four = from_integer(4, signed_int_type); + const auto eight = from_integer(8, signed_int_type); + const auto negative_twelve = from_integer(-12, signed_int_type); + const auto negative_sixteen = from_integer(-16, signed_int_type); + + SECTION("Single element intervals") + { + const constant_interval_exprt zero_interval(zero); + const constant_interval_exprt one_interval(one); + const constant_interval_exprt four_interval(four); + const constant_interval_exprt eight_interval(eight); + const constant_interval_exprt negative_twelve_interval(negative_twelve); + + REQUIRE(value_of(zero_interval.divide(four_interval)) == 0); + REQUIRE(value_of(four_interval.divide(four_interval)) == 1); + REQUIRE(value_of(four_interval.divide(eight_interval)) == 0); + REQUIRE(value_of(eight_interval.divide(four_interval)) == 2); + REQUIRE(value_of(negative_twelve_interval.divide(four_interval)) == -3); + REQUIRE(value_of(negative_twelve_interval.divide(one_interval)) == -12); + + SECTION("Divide by zero") + { + // TODO: currently this triggers an invariant + // REQUIRE(zero_interval.divide(zero_interval).is_top()); + // REQUIRE(one_interval.divide(zero_interval).is_top()); + // REQUIRE(negative_twelve_interval.divide(zero_interval).is_top()); + } + + SECTION("Max & Min") + { + const constant_interval_exprt min_interval{min_exprt{signed_int_type}}; + const constant_interval_exprt max_interval{max_exprt{signed_int_type}}; + // TODO: division of single max or min don't work as expected + // CHECK(max_interval.divide(max_interval).is_top()); + // CHECK(max_interval.divide(min_interval).is_top()); + CHECK(max_interval.divide(zero_interval).is_top()); + // CHECK(max_interval.divide(one_interval).is_top()); + + // CHECK(min_interval.divide(max_interval).is_top()); + // CHECK(min_interval.divide(min_interval).is_top()); + CHECK(min_interval.divide(zero_interval).is_top()); + // CHECK(min_interval.divide(one_interval).is_top()); + } + } + + SECTION("Interval ranges") + { + const constant_interval_exprt positive_range(four, eight); + const constant_interval_exprt negative_range( + negative_sixteen, negative_twelve); + const constant_interval_exprt range_containing_zero(negative_twelve, four); + const constant_interval_exprt zero_interval(zero); + + const constant_exprt &two = from_integer(2, signed_int_type); + REQUIRE(matching_range( + positive_range.divide(positive_range), + constant_interval_exprt{zero, two})); + + REQUIRE(value_of(positive_range.divide(negative_range)) == 0); + const constant_exprt &negative_four = from_integer(-4, signed_int_type); + const constant_exprt &negative_one = from_integer(-1, signed_int_type); + REQUIRE(matching_range( + negative_range.divide(positive_range), + constant_interval_exprt(negative_four, negative_one))); + } +} From 50fae45ad51a24b0c52cc9e772d1f6ae7fd75573 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 22 May 2020 17:56:20 +0100 Subject: [PATCH 37/59] Add missing test coverage for unary operations --- unit/util/interval/eval.cpp | 47 ++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp index d39b6894945..b724866c019 100644 --- a/unit/util/interval/eval.cpp +++ b/unit/util/interval/eval.cpp @@ -36,14 +36,20 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") } } - WHEN("Unary operations to an interval") + WHEN("Unary operations to an single element interval") { constant_interval_exprt five = constant_interval_exprt(from_integer(5, signedbv_typet(32))); + const constant_interval_exprt &max_interval = + constant_interval_exprt(max_exprt{signedbv_typet(32)}); + const constant_interval_exprt &min_interval = + constant_interval_exprt(min_exprt{signedbv_typet(32)}); THEN("When we apply unary addition to it, nothing should happen") { REQUIRE(five.eval(ID_unary_plus) == five); + REQUIRE(min_interval.eval(ID_unary_minus).has_no_lower_bound()); + REQUIRE(max_interval.eval(ID_unary_minus).has_no_upper_bound()); } THEN("When we apply unary subtraction to it, it should be negated") @@ -52,6 +58,9 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") numeric_cast(five.eval(ID_unary_minus).get_lower()); REQUIRE(negated_val.has_value()); REQUIRE(negated_val.value() == -5); + + REQUIRE(max_interval.eval(ID_unary_minus).has_no_lower_bound()); + REQUIRE(min_interval.eval(ID_unary_minus).has_no_upper_bound()); } THEN("When we apply bitwise negation to it, is should be bitwise negated") @@ -62,4 +71,40 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") REQUIRE(bitwise_negated_val.value() == (~5)); } } + WHEN("Unary operations to an single element interval") + { + constant_interval_exprt five_to_eight = constant_interval_exprt( + from_integer(5, signedbv_typet(32)), from_integer(8, signedbv_typet(32))); + + THEN("When we apply unary addition to it, nothing should happen") + { + REQUIRE(five_to_eight.eval(ID_unary_plus) == five_to_eight); + } + + THEN("When we apply unary subtraction to it, it should be negated") + { + auto negated_val = numeric_cast( + five_to_eight.eval(ID_unary_minus).get_lower()); + REQUIRE(negated_val.has_value()); + REQUIRE(negated_val.value() == -8); + + auto upper_value = numeric_cast( + five_to_eight.eval(ID_unary_minus).get_upper()); + REQUIRE(upper_value.has_value()); + REQUIRE(upper_value.value() == -8); + } + + THEN("When we apply bitwise negation to it, is should be bitwise negated") + { + auto bitwise_negated_val = + numeric_cast(five_to_eight.eval(ID_bitnot).get_lower()); + REQUIRE(bitwise_negated_val.has_value()); + REQUIRE(bitwise_negated_val.value() == (-9 /* ~5 */)); + + auto upper_value = + numeric_cast(five_to_eight.eval(ID_bitnot).get_upper()); + REQUIRE(bitwise_negated_val.has_value()); + REQUIRE(bitwise_negated_val.value() == (-6 /* ~8 */)); + } + } } From b9d3dcf12845a7c5f6be89038d2da65808b8f08d Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 22 May 2020 17:56:33 +0100 Subject: [PATCH 38/59] Add missing coverage for multiply --- unit/util/interval/multiply.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/unit/util/interval/multiply.cpp b/unit/util/interval/multiply.cpp index 8eda40399d8..f5d62fe0fd1 100644 --- a/unit/util/interval/multiply.cpp +++ b/unit/util/interval/multiply.cpp @@ -22,6 +22,14 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") symbol_tablet symbol_table; namespacet ns(symbol_table); + WHEN("Single element multiplication") + { + constant_interval_exprt a(CEV(5)); + constant_interval_exprt b(CEV(10)); + const auto a_times_b = a.multiply(b); + REQUIRE(V(a_times_b.get_upper()) == 50); + } + WHEN("Both are positive [2,5]*[7,11]") { constant_interval_exprt a(CEV(2), CEV(5)); From bd34f7dad9e4f6b468cf1aef6073d707f997ed7d Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 22 May 2020 18:21:30 +0100 Subject: [PATCH 39/59] Fix equality Currently checks are equivalent intervals, but before wasn't even checking that --- src/util/interval.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 34161de013c..ae0f4883b4e 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -433,7 +433,7 @@ tvt constant_interval_exprt::equal(const constant_interval_exprt &o) const return tvt(equal(get_lower(), o.get_lower())); } - if(equal(get_upper(), o.get_upper()) && equal(get_upper(), o.get_upper())) + if(equal(get_upper(), o.get_upper()) && equal(get_lower(), o.get_lower())) { return tvt(true); } From 813c5b5645d20ef73ba390a3b6246848b1319b95 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 22 May 2020 18:21:49 +0100 Subject: [PATCH 40/59] Fix printing code ireps now use hex encoding, updated to modern version to get string of number --- src/util/interval.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index ae0f4883b4e..632b49e50a7 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -1442,8 +1442,7 @@ std::ostream &operator<<(std::ostream &out, const constant_interval_exprt &i) // FIXME Not everything that's a bitvector is also an integer if(i.is_bitvector(i.get_lower())) { - out << binary2integer( - id2string(i.get_lower().get(ID_value)), i.is_signed()); + out << integer2string(*numeric_cast(i.get_lower())); } else { @@ -1473,8 +1472,7 @@ std::ostream &operator<<(std::ostream &out, const constant_interval_exprt &i) { if(i.is_bitvector(i.get_upper())) { - out << binary2integer( - id2string(i.get_upper().get(ID_value)), i.is_signed()); + out << integer2string(*numeric_cast(i.get_upper())); } else { From 2c43d53b07e910b2dee98a50341ea71ffdc99115 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 10:45:38 +0100 Subject: [PATCH 41/59] Fix typo in unary plus tests for min and max --- unit/util/interval/eval.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp index b724866c019..f69af00d7c1 100644 --- a/unit/util/interval/eval.cpp +++ b/unit/util/interval/eval.cpp @@ -48,8 +48,8 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") THEN("When we apply unary addition to it, nothing should happen") { REQUIRE(five.eval(ID_unary_plus) == five); - REQUIRE(min_interval.eval(ID_unary_minus).has_no_lower_bound()); - REQUIRE(max_interval.eval(ID_unary_minus).has_no_upper_bound()); + REQUIRE(min_interval.eval(ID_unary_plus).has_no_lower_bound()); + REQUIRE(max_interval.eval(ID_unary_plus).has_no_upper_bound()); } THEN("When we apply unary subtraction to it, it should be negated") @@ -91,7 +91,7 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") auto upper_value = numeric_cast( five_to_eight.eval(ID_unary_minus).get_upper()); REQUIRE(upper_value.has_value()); - REQUIRE(upper_value.value() == -8); + REQUIRE(upper_value.value() == -5); } THEN("When we apply bitwise negation to it, is should be bitwise negated") From b62d5676336d6529a1d0dbbc478c8548c4153704 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 10:48:28 +0100 Subject: [PATCH 42/59] Disable unary minus tests on ranges These aren't currently supported and cause a crash when executed --- unit/util/interval/eval.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp index f69af00d7c1..826b6789408 100644 --- a/unit/util/interval/eval.cpp +++ b/unit/util/interval/eval.cpp @@ -59,8 +59,10 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") REQUIRE(negated_val.has_value()); REQUIRE(negated_val.value() == -5); - REQUIRE(max_interval.eval(ID_unary_minus).has_no_lower_bound()); - REQUIRE(min_interval.eval(ID_unary_minus).has_no_upper_bound()); + // TODO: unary minus does not work on intervals that contain extremes + // ADA-535 + // REQUIRE(max_interval.eval(ID_unary_minus).has_no_lower_bound()); + // REQUIRE(min_interval.eval(ID_unary_minus).has_no_upper_bound()); } THEN("When we apply bitwise negation to it, is should be bitwise negated") From 481f18156b93d565df3e443a2e1cbf1f234dd8e6 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 10:49:22 +0100 Subject: [PATCH 43/59] Adapt test for bitwise not on a range Currently this returns top rather than the actual range --- unit/util/interval/eval.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp index 826b6789408..f974ad7c704 100644 --- a/unit/util/interval/eval.cpp +++ b/unit/util/interval/eval.cpp @@ -98,15 +98,8 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") THEN("When we apply bitwise negation to it, is should be bitwise negated") { - auto bitwise_negated_val = - numeric_cast(five_to_eight.eval(ID_bitnot).get_lower()); - REQUIRE(bitwise_negated_val.has_value()); - REQUIRE(bitwise_negated_val.value() == (-9 /* ~5 */)); - - auto upper_value = - numeric_cast(five_to_eight.eval(ID_bitnot).get_upper()); - REQUIRE(bitwise_negated_val.has_value()); - REQUIRE(bitwise_negated_val.value() == (-6 /* ~8 */)); + // For intervals, bitwise not returns top + REQUIRE(five_to_eight.eval(ID_bitnot).is_top()); } } } From c1f60ad7810d7306bd93a099887648bb693d5df7 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 16:41:14 +0100 Subject: [PATCH 44/59] Tidy up shift test --- unit/util/interval/shift.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/unit/util/interval/shift.cpp b/unit/util/interval/shift.cpp index 35ff76030ee..516566a3341 100644 --- a/unit/util/interval/shift.cpp +++ b/unit/util/interval/shift.cpp @@ -15,23 +15,17 @@ #define V_(X) (bvrep2integer(X.c_str(), 32, true)) #define CEV(X) (from_integer(mp_integer(X), signedbv_typet(32))) -SCENARIO("shift interval domain", "[core][analyses][interval][shift]") +TEST_CASE("shift interval domain", "[core][analyses][interval][shift]") { - GIVEN("Two simple signed intervals") + SECTION("Left shift") + { + const constant_interval_exprt four_to_eight(CEV(4), CEV(8)); + const constant_interval_exprt one(CEV(1)); + REQUIRE( + constant_interval_exprt::left_shift(four_to_eight, one) == + constant_interval_exprt(CEV(8), CEV(16))); + } + SECTION("Right shift") { - symbol_tablet symbol_table; - namespacet ns(symbol_table); - - WHEN("Something") - { - THEN("Something else") - { - REQUIRE( - constant_interval_exprt::left_shift( - constant_interval_exprt(CEV(4), CEV(8)), - constant_interval_exprt(CEV(1))) == - constant_interval_exprt(CEV(8), CEV(16))); - } - } } } From 763b9068b149cd16eb05270f785554d8672ab5c0 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 16:49:50 +0100 Subject: [PATCH 45/59] Add remaining shift tests Move some shift tests from the bitwise set of tests --- unit/util/interval/bitwise.cpp | 16 ---------------- unit/util/interval/shift.cpp | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/unit/util/interval/bitwise.cpp b/unit/util/interval/bitwise.cpp index 6eceb86f920..dd9e5a86201 100644 --- a/unit/util/interval/bitwise.cpp +++ b/unit/util/interval/bitwise.cpp @@ -44,21 +44,5 @@ SCENARIO("bitwise interval domain", "[core][analyses][interval][bitwise]") constant_interval_exprt::bitwise_xor(five, nine) == constant_interval_exprt(from_integer(12, unsigned_int))); } - - THEN("Left shift on the 5 should produce 10") - { - REQUIRE( - constant_interval_exprt::left_shift( - five, constant_interval_exprt(from_integer(1, unsigned_int))) == - constant_interval_exprt(from_integer(10, unsigned_int))); - } - - THEN("Right shift on the 5 should produce 2") - { - REQUIRE( - constant_interval_exprt::right_shift( - five, constant_interval_exprt(from_integer(1, unsigned_int))) == - constant_interval_exprt(from_integer(2, unsigned_int))); - } } } diff --git a/unit/util/interval/shift.cpp b/unit/util/interval/shift.cpp index 516566a3341..f2bebb74d95 100644 --- a/unit/util/interval/shift.cpp +++ b/unit/util/interval/shift.cpp @@ -19,13 +19,36 @@ TEST_CASE("shift interval domain", "[core][analyses][interval][shift]") { SECTION("Left shift") { + REQUIRE( + constant_interval_exprt::left_shift( + constant_interval_exprt(CEV(5)), constant_interval_exprt(CEV(1))) == + constant_interval_exprt(CEV(10))); + const constant_interval_exprt four_to_eight(CEV(4), CEV(8)); const constant_interval_exprt one(CEV(1)); REQUIRE( constant_interval_exprt::left_shift(four_to_eight, one) == constant_interval_exprt(CEV(8), CEV(16))); + + const constant_interval_exprt negative_one(CEV(-1)); + REQUIRE(constant_interval_exprt::left_shift(four_to_eight, negative_one) + .is_top()); } SECTION("Right shift") { + REQUIRE( + constant_interval_exprt::right_shift( + constant_interval_exprt(CEV(5)), constant_interval_exprt(CEV(1))) == + constant_interval_exprt(CEV(2))); + + const constant_interval_exprt four_to_eight(CEV(4), CEV(8)); + const constant_interval_exprt one(CEV(1)); + REQUIRE( + constant_interval_exprt::right_shift(four_to_eight, one) == + constant_interval_exprt(CEV(2), CEV(4))); + + const constant_interval_exprt negative_one(CEV(-1)); + REQUIRE(constant_interval_exprt::right_shift(four_to_eight, negative_one) + .is_top()); } } From a0cff8213de9581bd2b9224d3e0b6aab0afe6cb0 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 17:06:35 +0100 Subject: [PATCH 46/59] Add missing tests for increment --- unit/util/interval/add.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/unit/util/interval/add.cpp b/unit/util/interval/add.cpp index 3b6aa07c88e..5ee1d0419b9 100644 --- a/unit/util/interval/add.cpp +++ b/unit/util/interval/add.cpp @@ -43,6 +43,17 @@ SCENARIO("add interval domain", "[core][analyses][interval][add]") REQUIRE(V(result.get_lower()) == 8); REQUIRE(V(result.get_upper()) == 12); } + + AND_WHEN("Incrementing the interval") + { + const auto incremented = left.increment(); + + THEN("The result is correct") + { + REQUIRE(V(incremented.get_lower()) == 3); + REQUIRE(V(incremented.get_upper()) == 5); + } + } } WHEN("One contains infinite [2,4]+[6,INF]") From 3722357c7eae9015a2b4b428cc2993c4b9df2d62 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 17:06:48 +0100 Subject: [PATCH 47/59] Add missing bitwise tests for actual intervals --- unit/util/interval/bitwise.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/unit/util/interval/bitwise.cpp b/unit/util/interval/bitwise.cpp index dd9e5a86201..c738f1620ad 100644 --- a/unit/util/interval/bitwise.cpp +++ b/unit/util/interval/bitwise.cpp @@ -21,11 +21,16 @@ SCENARIO("bitwise interval domain", "[core][analyses][interval][bitwise]") constant_interval_exprt nine = constant_interval_exprt(from_integer(9, unsigned_int)); + constant_interval_exprt five_to_nine( + from_integer(5, unsigned_int), from_integer(9, unsigned_int)); + THEN("Bitwise or should yield bitwise representation of 13") { REQUIRE( constant_interval_exprt::bitwise_or(five, nine) == constant_interval_exprt(from_integer(13, unsigned_int))); + + REQUIRE(constant_interval_exprt::bitwise_or(five_to_nine, nine).is_top()); } THEN("Bitwise and should yield bitwise representation of 1") @@ -36,6 +41,9 @@ SCENARIO("bitwise interval domain", "[core][analyses][interval][bitwise]") REQUIRE( (five & nine) == constant_interval_exprt(from_integer(1, unsigned_int))); + + REQUIRE( + constant_interval_exprt::bitwise_and(five_to_nine, nine).is_top()); } THEN("Bitwise xor should yield bitwise representation of 12") @@ -43,6 +51,9 @@ SCENARIO("bitwise interval domain", "[core][analyses][interval][bitwise]") REQUIRE( constant_interval_exprt::bitwise_xor(five, nine) == constant_interval_exprt(from_integer(12, unsigned_int))); + + REQUIRE( + constant_interval_exprt::bitwise_xor(five_to_nine, nine).is_top()); } } } From cc83805455d14939428f2a936cb82433bfda89f0 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 17:07:08 +0100 Subject: [PATCH 48/59] Add missing comparator tests --- unit/util/interval/comparisons.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/unit/util/interval/comparisons.cpp b/unit/util/interval/comparisons.cpp index 1a838bc0dd1..97fdfdb4c2a 100644 --- a/unit/util/interval/comparisons.cpp +++ b/unit/util/interval/comparisons.cpp @@ -120,6 +120,8 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") REQUIRE_FALSE( constant_interval_exprt(CEV(10), CEV(20)) > constant_interval_exprt(CEV(30), CEV(40))); + REQUIRE( + constant_interval_exprt(CEV(10)) < constant_interval_exprt(CEV(30))); } THEN( @@ -184,6 +186,9 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") constant_interval_exprt(CEV(10), CEV(31)) .less_than_or_equal(constant_interval_exprt(CEV(30), CEV(40))) == tvt::unknown()); + CHECK(constant_interval_exprt(CEV(10)) + .less_than_or_equal(constant_interval_exprt(CEV(30))) + .is_true()); } THEN( From d8387044359bdf72a8ba2d1b11a6464e636c172f Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 17:07:21 +0100 Subject: [PATCH 49/59] Add tests for definitely_true/false for numeric intervals --- unit/util/interval/comparisons.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/unit/util/interval/comparisons.cpp b/unit/util/interval/comparisons.cpp index 97fdfdb4c2a..5137b5c0b0b 100644 --- a/unit/util/interval/comparisons.cpp +++ b/unit/util/interval/comparisons.cpp @@ -208,6 +208,32 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") .greater_than_or_equal(constant_interval_exprt(CEV(30), CEV(40))) == tvt::unknown()); } + THEN("Intervals for truthyness") + { + constant_interval_exprt spans_zero(CEV(-1), CEV(1)); + REQUIRE(spans_zero.is_definitely_true().is_unknown()); + REQUIRE(spans_zero.is_definitely_false().is_unknown()); + + constant_interval_exprt includes_zero_positive(CEV(0), CEV(1)); + REQUIRE(includes_zero_positive.is_definitely_true().is_unknown()); + REQUIRE(includes_zero_positive.is_definitely_false().is_unknown()); + + constant_interval_exprt includes_zero_negative(CEV(-1), CEV(9)); + REQUIRE(includes_zero_negative.is_definitely_true().is_unknown()); + REQUIRE(includes_zero_negative.is_definitely_false().is_unknown()); + + constant_interval_exprt zero(CEV(0)); + REQUIRE(zero.is_definitely_false().is_true()); + REQUIRE(zero.is_definitely_true().is_false()); + + constant_interval_exprt positive_interval(CEV(1), CEV(5)); + REQUIRE(positive_interval.is_definitely_true().is_true()); + REQUIRE(positive_interval.is_definitely_false().is_false()); + + constant_interval_exprt negative_interval(CEV(-5), CEV(-1)); + REQUIRE(negative_interval.is_definitely_true().is_true()); + REQUIRE(negative_interval.is_definitely_false().is_false()); + } } } } From 1faf51674841408b7869f23547f0540e9616f775 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 17:08:56 +0100 Subject: [PATCH 50/59] Add missing tests for modulo --- unit/util/interval/modulo.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/unit/util/interval/modulo.cpp b/unit/util/interval/modulo.cpp index daf1214abf7..32bd8a99343 100644 --- a/unit/util/interval/modulo.cpp +++ b/unit/util/interval/modulo.cpp @@ -17,6 +17,25 @@ SCENARIO("modulo interval domain", "[core][analyses][interval][modulo]") { + GIVEN("Two single element internvals") + { + constant_interval_exprt a(CEV(5)); + constant_interval_exprt b(CEV(10)); + constant_interval_exprt zero(CEV(0)); + const auto a_mod_b = a.modulo(b); + REQUIRE(V(a_mod_b.get_upper()) == 5); + + const auto b_mod_a = b.modulo(a); + // TODO: precision with single element modulo + REQUIRE(V(b_mod_a.get_upper()) == 4); + + const auto zero_mod_a = zero.modulo(a); + REQUIRE(zero_mod_a == constant_interval_exprt(CEV(0))); + + // TODO: this causes an invariant as it is unable to simplify the + // TODO: simplify(a % 0) == a % 0 + // REQUIRE(a.modulo(zero).is_top()); + } GIVEN("Two simple signed intervals") { symbol_tablet symbol_table; @@ -52,6 +71,19 @@ SCENARIO("modulo interval domain", "[core][analyses][interval][modulo]") constant_interval_exprt(CEV(-10), CEV(20)), constant_interval_exprt(CEV(0), CEV(5))) == constant_interval_exprt::top(signedbv_typet(32))); + + REQUIRE( + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(-10), CEV(20)), + constant_interval_exprt(CEV(1), CEV(5))) == + constant_interval_exprt(CEV(-10), CEV(20))); + + REQUIRE( + constant_interval_exprt::modulo( + constant_interval_exprt(CEV(-10), CEV(-1)), + constant_interval_exprt(CEV(-5), CEV(-1))) == + constant_interval_exprt(CEV(-5), CEV(0))); + REQUIRE( constant_interval_exprt::modulo( constant_interval_exprt(CEV(-20), CEV(-10)), From 7c16a144fb4cdd18cec9970bcb6375535cfca44c Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Wed, 27 May 2020 17:27:20 +0100 Subject: [PATCH 51/59] Add tests for equality and inequality --- unit/util/interval/comparisons.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/unit/util/interval/comparisons.cpp b/unit/util/interval/comparisons.cpp index 5137b5c0b0b..30e1dcaa489 100644 --- a/unit/util/interval/comparisons.cpp +++ b/unit/util/interval/comparisons.cpp @@ -237,3 +237,32 @@ SCENARIO("comparison interval domain", "[core][analyses][interval][comparison]") } } } + +TEST_CASE("interval::equality", "[core][analyses][interval]") +{ + SECTION("Single element intervals") + { + constant_interval_exprt two(CEV(2)); + constant_interval_exprt four(CEV(4)); + + REQUIRE_FALSE(two.equal(four).is_true()); + REQUIRE(two.equal(two).is_true()); + + REQUIRE(two.not_equal(four).is_true()); + REQUIRE_FALSE(two.not_equal(two).is_true()); + } + SECTION("Proper intervals") + { + constant_interval_exprt two_to_four(CEV(2), CEV(4)); + constant_interval_exprt six_to_eight(CEV(6), CEV(8)); + constant_interval_exprt five_to_ten(CEV(5), CEV(10)); + + // TODO: wrongly concludes that these are unequal + // ADA-537 + // REQUIRE(two_to_four.equal(six_to_eight).is_unknown()); + REQUIRE_FALSE(two_to_four.equal(five_to_ten).is_true()); + + REQUIRE_FALSE(two_to_four.not_equal(six_to_eight).is_unknown()); + REQUIRE(two_to_four.not_equal(five_to_ten).is_true()); + } +} From 2d067f25bfa03607556a0bc797e2c2de5746e25f Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Thu, 28 May 2020 09:48:29 +0100 Subject: [PATCH 52/59] Fix error in binary eval for subtraction Was wrongly using the unary negation operator, rather than subtracting one interval from the other. --- src/util/interval.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/interval.cpp b/src/util/interval.cpp index 632b49e50a7..d2f55043f96 100644 --- a/src/util/interval.cpp +++ b/src/util/interval.cpp @@ -818,7 +818,7 @@ constant_interval_exprt constant_interval_exprt::eval( } if(binary_operator == ID_minus) { - return unary_minus(other); + return minus(other); } if(binary_operator == ID_mult) { From 39edeea0a555ae446bee8f200e5a0a1ab764a6a7 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Thu, 28 May 2020 09:52:04 +0100 Subject: [PATCH 53/59] Add test case for eval on binary operations --- unit/util/interval/eval.cpp | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp index f974ad7c704..f2628b67bc0 100644 --- a/unit/util/interval/eval.cpp +++ b/unit/util/interval/eval.cpp @@ -103,3 +103,62 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") } } } + +TEST_CASE("binary eval switch", "[core][analyses][interval]") +{ + const auto interval_of = [](const int value) { + return constant_interval_exprt(from_integer(value, signedbv_typet(32))); + }; + + const auto interval_from_to = [](const int lower, const int upper) { + return constant_interval_exprt( + from_integer(lower, signedbv_typet(32)), + from_integer(upper, signedbv_typet(32))); + }; + + const auto boolean_interval = [](const bool value) { + return constant_interval_exprt::tvt_to_interval(tvt(value)); + }; + + constant_interval_exprt two = interval_of(2); + constant_interval_exprt five = interval_of(5); + constant_interval_exprt eight = interval_of(8); + + SECTION("Numeric operations") + { + REQUIRE(five.eval(ID_plus, eight) == interval_of(13)); + REQUIRE(five.eval(ID_minus, eight) == interval_of(-3)); + REQUIRE(five.eval(ID_mult, eight) == interval_of(40)); + REQUIRE(five.eval(ID_div, eight) == interval_of(0)); + REQUIRE(five.eval(ID_mod, eight) == interval_from_to(0, 5)); + REQUIRE(five.eval(ID_shl, two) == interval_of(20 /* 5 << 2 */)); + REQUIRE(five.eval(ID_ashr, two) == interval_of(1 /* 5 >> 2 */)); + REQUIRE(five.eval(ID_bitor, eight) == interval_of(13)); + REQUIRE(five.eval(ID_bitand, eight) == interval_of(0)); + REQUIRE(five.eval(ID_bitxor, two) == interval_of(7)); + } + SECTION("Comparisons") + { + REQUIRE(five.eval(ID_lt, eight) == boolean_interval(true)); + REQUIRE(five.eval(ID_le, eight) == boolean_interval(true)); + REQUIRE(five.eval(ID_gt, eight) == boolean_interval(false)); + REQUIRE(five.eval(ID_ge, eight) == boolean_interval(false)); + REQUIRE(five.eval(ID_equal, eight) == boolean_interval(false)); + REQUIRE(five.eval(ID_notequal, eight) == boolean_interval(true)); + } + SECTION("Logical operators") + { + const auto true_interval = boolean_interval(true); + const auto false_interval = boolean_interval(false); + REQUIRE( + true_interval.eval(ID_and, false_interval) == boolean_interval(false)); + REQUIRE( + true_interval.eval(ID_or, false_interval) == boolean_interval(true)); + REQUIRE( + true_interval.eval(ID_xor, false_interval) == boolean_interval(true)); + } + SECTION("Invalid operations") + { + REQUIRE(five.eval(ID_type, eight).is_top()); + } +} From a84494c86e5a015672ff26c6f95fd1e3fa7dd5f6 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Thu, 28 May 2020 10:17:06 +0100 Subject: [PATCH 54/59] Add tests for the to_string operation --- unit/Makefile | 1 + unit/util/interval/to_string.cpp | 52 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 unit/util/interval/to_string.cpp diff --git a/unit/Makefile b/unit/Makefile index c1ce7f42531..f581bb010bf 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -87,6 +87,7 @@ SRC += analyses/ai/ai.cpp \ util/interval/multiply.cpp \ util/interval/shift.cpp \ util/interval/subtract.cpp \ + util/interval/to_string.cpp \ util/interval_constraint.cpp \ util/interval_union.cpp \ util/irep.cpp \ diff --git a/unit/util/interval/to_string.cpp b/unit/util/interval/to_string.cpp new file mode 100644 index 00000000000..ba90c54732e --- /dev/null +++ b/unit/util/interval/to_string.cpp @@ -0,0 +1,52 @@ +/*******************************************************************\ + Module: Unit tests for util/interval::to_string + Author: DiffBlue Limited +\*******************************************************************/ + +#include +#include +#include +#include + +TEST_CASE("interval::to_string", "[core][analyses][interval]") +{ + const signedbv_typet signed_int_type(32); + const unsignedbv_typet unsigned_int_type(32); + const auto signed_expr = [&](const int value) { + return from_integer(value, signed_int_type); + }; + const auto unsigned_expr = [&](const int value) { + return from_integer(value, unsigned_int_type); + }; + + REQUIRE(constant_interval_exprt(signed_expr(1)).to_string() == "[1,1]"); + REQUIRE( + constant_interval_exprt(signed_expr(1), signed_expr(2)).to_string() == + "[1,2]"); + + REQUIRE( + constant_interval_exprt::top(signed_int_type).to_string() == "[MIN,MAX]"); + + REQUIRE( + constant_interval_exprt::top(unsigned_int_type).to_string() == "[0,MAX]"); + + REQUIRE( + constant_interval_exprt(signed_expr(1), max_exprt{signed_int_type}) + .to_string() == "[1,MAX]"); + + REQUIRE( + constant_interval_exprt(min_exprt{signed_int_type}, signed_expr(1)) + .to_string() == "[MIN,1]"); + REQUIRE( + constant_interval_exprt(min_exprt{unsigned_int_type}, unsigned_expr(1)) + .to_string() == "[0,1]"); + + REQUIRE( + constant_interval_exprt( + min_exprt{signed_int_type}, max_exprt{signed_int_type}) + .to_string() == "[MIN,MAX]"); + REQUIRE( + constant_interval_exprt( + min_exprt{unsigned_int_type}, max_exprt{unsigned_int_type}) + .to_string() == "[0,MAX]"); +} From 7f619393f48f80b26cad4a8bbaf2f1a554c0142a Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 29 May 2020 10:01:33 +0100 Subject: [PATCH 55/59] fixup binary eval unit test commit --- unit/util/interval/eval.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp index f2628b67bc0..4c86ffe9ab6 100644 --- a/unit/util/interval/eval.cpp +++ b/unit/util/interval/eval.cpp @@ -124,12 +124,17 @@ TEST_CASE("binary eval switch", "[core][analyses][interval]") constant_interval_exprt five = interval_of(5); constant_interval_exprt eight = interval_of(8); + // Here we test only single element intervals, more robust testing of each + // opertion can be found in the method unit tests (e.g. + // unit/util/interval/add.cpp) + SECTION("Numeric operations") { REQUIRE(five.eval(ID_plus, eight) == interval_of(13)); REQUIRE(five.eval(ID_minus, eight) == interval_of(-3)); REQUIRE(five.eval(ID_mult, eight) == interval_of(40)); REQUIRE(five.eval(ID_div, eight) == interval_of(0)); + // Note modulo is implemented very imprecisely REQUIRE(five.eval(ID_mod, eight) == interval_from_to(0, 5)); REQUIRE(five.eval(ID_shl, two) == interval_of(20 /* 5 << 2 */)); REQUIRE(five.eval(ID_ashr, two) == interval_of(1 /* 5 >> 2 */)); From 42e2d5a96c0f13db989639c62a16625b4c672b64 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 29 May 2020 10:34:41 +0100 Subject: [PATCH 56/59] Tidy the test for unary minus --- unit/util/interval/eval.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/unit/util/interval/eval.cpp b/unit/util/interval/eval.cpp index 4c86ffe9ab6..1a086f1ab18 100644 --- a/unit/util/interval/eval.cpp +++ b/unit/util/interval/eval.cpp @@ -83,17 +83,14 @@ SCENARIO("Unary eval on intervals", "[core][analyses][interval][eval]") REQUIRE(five_to_eight.eval(ID_unary_plus) == five_to_eight); } - THEN("When we apply unary subtraction to it, it should be negated") + THEN("When we apply unary minus to it, it should be negated") { - auto negated_val = numeric_cast( - five_to_eight.eval(ID_unary_minus).get_lower()); - REQUIRE(negated_val.has_value()); - REQUIRE(negated_val.value() == -8); - - auto upper_value = numeric_cast( - five_to_eight.eval(ID_unary_minus).get_upper()); - REQUIRE(upper_value.has_value()); - REQUIRE(upper_value.value() == -5); + const constant_interval_exprt &negated_value = + five_to_eight.eval(ID_unary_minus); + REQUIRE( + negated_value == + constant_interval_exprt{from_integer(-8, signedbv_typet(32)), + from_integer(-5, signedbv_typet(32))}); } THEN("When we apply bitwise negation to it, is should be bitwise negated") From 536fc46588607f6243a925464aed1940a072b71a Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 29 May 2020 10:34:54 +0100 Subject: [PATCH 57/59] Make the equality comparison test easier to follow --- unit/util/interval/comparisons.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/unit/util/interval/comparisons.cpp b/unit/util/interval/comparisons.cpp index 30e1dcaa489..15b3f1760b5 100644 --- a/unit/util/interval/comparisons.cpp +++ b/unit/util/interval/comparisons.cpp @@ -257,12 +257,24 @@ TEST_CASE("interval::equality", "[core][analyses][interval]") constant_interval_exprt six_to_eight(CEV(6), CEV(8)); constant_interval_exprt five_to_ten(CEV(5), CEV(10)); - // TODO: wrongly concludes that these are unequal - // ADA-537 - // REQUIRE(two_to_four.equal(six_to_eight).is_unknown()); - REQUIRE_FALSE(two_to_four.equal(five_to_ten).is_true()); - - REQUIRE_FALSE(two_to_four.not_equal(six_to_eight).is_unknown()); - REQUIRE(two_to_four.not_equal(five_to_ten).is_true()); + SECTION("Same interval") + { + // TODO: wrongly concludes that these are equal + // ADA-537 + // REQUIRE(two_to_four.equal(two_to_four).is_unknown()); + // REQUIRE(two_to_four.not_equal(two_to_four).is_unknown()); + } + SECTION("Overlapping intervals") + { + // TODO: wrongly concludes that these are not equal + // ADA-537 + // REQUIRE_FALSE(six_to_eight.equal(five_to_ten).is_unknown()); + // REQUIRE_FALSE(six_to_eight.not_equal(five_to_ten).is_unknown()); + } + SECTION("Disjoint intervals") + { + REQUIRE_FALSE(two_to_four.equal(six_to_eight).is_true()); + REQUIRE(two_to_four.not_equal(six_to_eight).is_true()); + } } } From 296fe68d96177ba9dc88fb27207e3b0070f05b5f Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 29 May 2020 10:35:09 +0100 Subject: [PATCH 58/59] Add a comment explaining that modulo is imprecise --- unit/util/interval/modulo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/unit/util/interval/modulo.cpp b/unit/util/interval/modulo.cpp index 32bd8a99343..4c054917306 100644 --- a/unit/util/interval/modulo.cpp +++ b/unit/util/interval/modulo.cpp @@ -66,6 +66,7 @@ SCENARIO("modulo interval domain", "[core][analyses][interval][modulo]") constant_interval_exprt(CEV(-5), CEV(5))) == constant_interval_exprt::top(signedbv_typet(32))); + INFO("Taking modulo on interval that contains zero results in top"); REQUIRE( constant_interval_exprt::modulo( constant_interval_exprt(CEV(-10), CEV(20)), From 1d92ca0c7415deb72af8e951620b1d51acfe61b7 Mon Sep 17 00:00:00 2001 From: Thomas Kiley Date: Fri, 29 May 2020 10:35:19 +0100 Subject: [PATCH 59/59] Do a full check on the multiply test --- unit/util/interval/multiply.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit/util/interval/multiply.cpp b/unit/util/interval/multiply.cpp index f5d62fe0fd1..345abc20919 100644 --- a/unit/util/interval/multiply.cpp +++ b/unit/util/interval/multiply.cpp @@ -27,7 +27,7 @@ SCENARIO("multiply interval domain", "[core][analyses][interval][multiply]") constant_interval_exprt a(CEV(5)); constant_interval_exprt b(CEV(10)); const auto a_times_b = a.multiply(b); - REQUIRE(V(a_times_b.get_upper()) == 50); + REQUIRE(a_times_b == constant_interval_exprt(CEV(50), CEV(50))); } WHEN("Both are positive [2,5]*[7,11]")