diff --git a/src/solvers/flattening/boolbv.cpp b/src/solvers/flattening/boolbv.cpp index 53f1cdcb44e..8eb8a1bea57 100644 --- a/src/solvers/flattening/boolbv.cpp +++ b/src/solvers/flattening/boolbv.cpp @@ -251,9 +251,8 @@ bvt boolbvt::convert_bitvector(const exprt &expr) expr.id()==ID_bitxnor || expr.id()==ID_bitnor || expr.id()==ID_bitnand) return convert_bitwise(expr); - else if(expr.id()==ID_unary_minus || - expr.id()=="no-overflow-unary-minus") - return convert_unary_minus(to_unary_expr(expr)); + else if(expr.id() == ID_unary_minus) + return convert_unary_minus(to_unary_minus_expr(expr)); else if(expr.id()==ID_unary_plus) { return convert_bitvector(to_unary_plus_expr(expr).op()); @@ -281,7 +280,7 @@ bvt boolbvt::convert_bitvector(const exprt &expr) else if(expr.id()==ID_array) return convert_array(expr); else if(expr.id()==ID_vector) - return convert_vector(expr); + return convert_vector(to_vector_expr(expr)); else if(expr.id()==ID_complex) return convert_complex(to_complex_expr(expr)); else if(expr.id()==ID_complex_real) diff --git a/src/solvers/flattening/boolbv.h b/src/solvers/flattening/boolbv.h index c51f3a3803b..94e1860a057 100644 --- a/src/solvers/flattening/boolbv.h +++ b/src/solvers/flattening/boolbv.h @@ -142,7 +142,7 @@ class boolbvt:public arrayst virtual bvt convert_if(const if_exprt &expr); virtual bvt convert_struct(const struct_exprt &expr); virtual bvt convert_array(const exprt &expr); - virtual bvt convert_vector(const exprt &expr); + virtual bvt convert_vector(const vector_exprt &expr); virtual bvt convert_complex(const complex_exprt &expr); virtual bvt convert_complex_real(const complex_real_exprt &expr); virtual bvt convert_complex_imag(const complex_imag_exprt &expr); @@ -164,7 +164,7 @@ class boolbvt:public arrayst virtual bvt convert_cond(const exprt &expr); virtual bvt convert_shift(const binary_exprt &expr); virtual bvt convert_bitwise(const exprt &expr); - virtual bvt convert_unary_minus(const unary_exprt &expr); + virtual bvt convert_unary_minus(const unary_minus_exprt &expr); virtual bvt convert_abs(const abs_exprt &expr); virtual bvt convert_concatenation(const concatenation_exprt &expr); virtual bvt convert_replication(const replication_exprt &expr); diff --git a/src/solvers/flattening/boolbv_unary_minus.cpp b/src/solvers/flattening/boolbv_unary_minus.cpp index 05424f29914..77d8498bb76 100644 --- a/src/solvers/flattening/boolbv_unary_minus.cpp +++ b/src/solvers/flattening/boolbv_unary_minus.cpp @@ -12,9 +12,12 @@ Author: Daniel Kroening, kroening@kroening.com #include +#include +#include + #include "boolbv_type.h" -bvt boolbvt::convert_unary_minus(const unary_exprt &expr) +bvt boolbvt::convert_unary_minus(const unary_minus_exprt &expr) { const typet &type=ns.follow(expr.type()); @@ -23,23 +26,12 @@ bvt boolbvt::convert_unary_minus(const unary_exprt &expr) if(width==0) return conversion_failed(expr); - const exprt::operandst &operands=expr.operands(); - - if(operands.size()!=1) - throw "unary minus takes one operand"; + const exprt &op = expr.op(); - const exprt &op0=expr.op0(); - - const bvt &op_bv=convert_bv(op0); + const bvt &op_bv = convert_bv(op, width); bvtypet bvtype=get_bvtype(type); - bvtypet op_bvtype=get_bvtype(op0.type()); - std::size_t op_width=op_bv.size(); - - bool no_overflow=(expr.id()=="no-overflow-unary-minus"); - - if(op_width==0 || op_width!=width) - return conversion_failed(expr); + bvtypet op_bvtype = get_bvtype(op.type()); if(bvtype==bvtypet::IS_UNKNOWN && (type.id()==ID_vector || type.id()==ID_complex)) @@ -48,68 +40,54 @@ bvt boolbvt::convert_unary_minus(const unary_exprt &expr) std::size_t sub_width=boolbv_width(subtype); - if(sub_width==0 || width%sub_width!=0) - throw "unary-: unexpected vector operand width"; + INVARIANT( + sub_width > 0, + "bitvector representation of type needs to have at least one bit"); + + INVARIANT( + width % sub_width == 0, + "total bitvector width needs to be a multiple of the component bitvector " + "widths"); - std::size_t size=width/sub_width; bvt bv; - bv.resize(width); - for(std::size_t i=0; i #include +#include #include #include @@ -79,39 +80,35 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const else if(type_id==ID_c_bool) { entry.total_width=to_c_bool_type(type).get_width(); - assert(entry.total_width!=0); } else if(type_id==ID_signedbv) { entry.total_width=to_signedbv_type(type).get_width(); - assert(entry.total_width!=0); } else if(type_id==ID_unsignedbv) { entry.total_width=to_unsignedbv_type(type).get_width(); - assert(entry.total_width!=0); } else if(type_id==ID_floatbv) { entry.total_width=to_floatbv_type(type).get_width(); - assert(entry.total_width!=0); } else if(type_id==ID_fixedbv) { entry.total_width=to_fixedbv_type(type).get_width(); - assert(entry.total_width!=0); } else if(type_id==ID_bv) { entry.total_width=to_bv_type(type).get_width(); - assert(entry.total_width!=0); } else if(type_id==ID_verilog_signedbv || type_id==ID_verilog_unsignedbv) { // we encode with two bits - entry.total_width = type.get_size_t(ID_width) * 2; - assert(entry.total_width!=0); + std::size_t size = type.get_size_t(ID_width); + DATA_INVARIANT( + size > 0, "verilog bitvector width shall be greater than zero"); + entry.total_width = size * 2; } else if(type_id==ID_range) { @@ -123,7 +120,7 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const if(size>=1) { entry.total_width = address_bits(size); - assert(entry.total_width!=0); + CHECK_RETURN(entry.total_width > 0); } } else if(type_id==ID_array) @@ -142,7 +139,7 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const { mp_integer total=array_size*sub_width; if(total>(1<<30)) // realistic limit - throw "array too large for flattening"; + throw analysis_exceptiont("array too large for flattening"); entry.total_width=integer2unsigned(total); } @@ -163,7 +160,7 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const { mp_integer total=vector_size*sub_width; if(total>(1<<30)) // realistic limit - throw "vector too large for flattening"; + analysis_exceptiont("vector too large for flattening"); entry.total_width=integer2unsigned(vector_size*sub_width); } @@ -181,13 +178,13 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const // get number of necessary bits std::size_t size=to_enumeration_type(type).elements().size(); entry.total_width = address_bits(size); - assert(entry.total_width!=0); + CHECK_RETURN(entry.total_width > 0); } else if(type_id==ID_c_enum) { // these have a subtype entry.total_width = type.subtype().get_size_t(ID_width); - assert(entry.total_width!=0); + CHECK_RETURN(entry.total_width > 0); } else if(type_id==ID_incomplete_c_enum) { diff --git a/src/util/std_types.h b/src/util/std_types.h index c4b18bbbc6f..99c4d5abed1 100644 --- a/src/util/std_types.h +++ b/src/util/std_types.h @@ -1210,6 +1210,11 @@ inline bool can_cast_type(const typet &type) return type.id() == ID_bv; } +inline void validate_type(const bv_typet &type) +{ + DATA_INVARIANT(!type.get(ID_width).empty(), "bitvector type must have width"); +} + /// \brief Cast a typet to a \ref bv_typet /// /// This is an unchecked conversion. \a type must be known to be \ref @@ -1221,14 +1226,18 @@ inline bool can_cast_type(const typet &type) inline const bv_typet &to_bv_type(const typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + const bv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// \copydoc to_bv_type(const typet &) inline bv_typet &to_bv_type(typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + bv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// Fixed-width bit-vector with unsigned binary interpretation @@ -1256,6 +1265,12 @@ inline bool can_cast_type(const typet &type) return type.id() == ID_unsignedbv; } +inline void validate_type(const unsignedbv_typet &type) +{ + DATA_INVARIANT( + !type.get(ID_width).empty(), "unsigned bitvector type must have width"); +} + /// \brief Cast a typet to an \ref unsignedbv_typet /// /// This is an unchecked conversion. \a type must be known to be \ref @@ -1267,14 +1282,18 @@ inline bool can_cast_type(const typet &type) inline const unsignedbv_typet &to_unsignedbv_type(const typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + const unsignedbv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// \copydoc to_unsignedbv_type(const typet &) inline unsignedbv_typet &to_unsignedbv_type(typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + unsignedbv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// Fixed-width bit-vector with two's complement interpretation @@ -1302,6 +1321,12 @@ inline bool can_cast_type(const typet &type) return type.id() == ID_signedbv; } +inline void validate_type(const signedbv_typet &type) +{ + DATA_INVARIANT( + !type.get(ID_width).empty(), "signed bitvector type must have width"); +} + /// \brief Cast a typet to a \ref signedbv_typet /// /// This is an unchecked conversion. \a type must be known to be \ref @@ -1313,14 +1338,18 @@ inline bool can_cast_type(const typet &type) inline const signedbv_typet &to_signedbv_type(const typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + const signedbv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// \copydoc to_signedbv_type(const typet &) inline signedbv_typet &to_signedbv_type(typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + signedbv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// Fixed-width bit-vector with signed fixed-point interpretation @@ -1356,6 +1385,12 @@ inline bool can_cast_type(const typet &type) return type.id() == ID_fixedbv; } +inline void validate_type(const fixedbv_typet &type) +{ + DATA_INVARIANT( + !type.get(ID_width).empty(), "fixed bitvector type must have width"); +} + /// \brief Cast a typet to a \ref fixedbv_typet /// /// This is an unchecked conversion. \a type must be known to be \ref @@ -1367,14 +1402,18 @@ inline bool can_cast_type(const typet &type) inline const fixedbv_typet &to_fixedbv_type(const typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + const fixedbv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// \copydoc to_fixedbv_type(const typet &) inline fixedbv_typet &to_fixedbv_type(typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + fixedbv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// Fixed-width bit-vector with IEEE floating-point interpretation @@ -1408,6 +1447,12 @@ inline bool can_cast_type(const typet &type) return type.id() == ID_floatbv; } +inline void validate_type(const floatbv_typet &type) +{ + DATA_INVARIANT( + !type.get(ID_width).empty(), "float bitvector type must have width"); +} + /// \brief Cast a typet to a \ref floatbv_typet /// /// This is an unchecked conversion. \a type must be known to be \ref @@ -1419,14 +1464,18 @@ inline bool can_cast_type(const typet &type) inline const floatbv_typet &to_floatbv_type(const typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + const floatbv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// \copydoc to_floatbv_type(const typet &) inline floatbv_typet &to_floatbv_type(typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + floatbv_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// Type for C bit fields @@ -1495,6 +1544,11 @@ inline bool can_cast_type(const typet &type) return type.id() == ID_pointer; } +inline void validate_type(const pointer_typet &type) +{ + DATA_INVARIANT(!type.get(ID_width).empty(), "pointer must have width"); +} + /// \brief Cast a typet to a \ref pointer_typet /// /// This is an unchecked conversion. \a type must be known to be \ref @@ -1520,12 +1574,6 @@ inline pointer_typet &to_pointer_type(typet &type) return ret; } -inline void validate_type(const pointer_typet &type) -{ - DATA_INVARIANT(!type.get(ID_width).empty(), "pointer must have width"); - DATA_INVARIANT(type.get_width() > 0, "pointer must have non-zero width"); -} - /// The reference type /// /// Intends to model C++ reference. Comparing to \ref pointer_typet should @@ -1598,6 +1646,11 @@ inline bool can_cast_type(const typet &type) return type.id() == ID_c_bool; } +inline void validate_type(const c_bool_typet &type) +{ + DATA_INVARIANT(!type.get(ID_width).empty(), "C bool type must have width"); +} + /// \brief Cast a typet to a \ref c_bool_typet /// /// This is an unchecked conversion. \a type must be known to be \ref @@ -1609,14 +1662,18 @@ inline bool can_cast_type(const typet &type) inline const c_bool_typet &to_c_bool_type(const typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + const c_bool_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// \copydoc to_c_bool_type(const typet &) inline c_bool_typet &to_c_bool_type(typet &type) { PRECONDITION(can_cast_type(type)); - return static_cast(type); + c_bool_typet &ret = static_cast(type); + validate_type(ret); + return ret; } /// String type