diff --git a/src/solvers/flattening/bv_minimize.cpp b/src/solvers/flattening/bv_minimize.cpp index 5bc26cee316..5d3869ab02c 100644 --- a/src/solvers/flattening/bv_minimize.cpp +++ b/src/solvers/flattening/bv_minimize.cpp @@ -8,8 +8,6 @@ Author: Georg Weissenbacher, georg.weissenbacher@inf.ethz.ch #include "bv_minimize.h" -#include - #include void bv_minimizet::add_objective( diff --git a/src/solvers/flattening/bv_pointers.cpp b/src/solvers/flattening/bv_pointers.cpp index a95587715ed..a41964a06bf 100644 --- a/src/solvers/flattening/bv_pointers.cpp +++ b/src/solvers/flattening/bv_pointers.cpp @@ -11,12 +11,12 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include literalt bv_pointerst::convert_rest(const exprt &expr) { - if(expr.type().id()!=ID_bool) - throw "bv_pointerst::convert_rest got non-boolean operand"; + PRECONDITION(expr.type().id() == ID_bool); const exprt::operandst &operands=expr.operands(); @@ -112,9 +112,6 @@ bool bv_pointerst::convert_address_of_rec( } else if(expr.id()==ID_index) { - if(expr.operands().size()!=2) - throw "index takes two operands"; - const index_exprt &index_expr=to_index_expr(expr); const exprt &array=index_expr.array(); const exprt &index=index_expr.index(); @@ -182,12 +179,13 @@ bool bv_pointerst::convert_address_of_rec( // add offset offset_arithmetic(bv, offset); } - else if(struct_op_type.id()==ID_union) + else { + INVARIANT( + struct_op_type.id() == ID_union, + "member expression should operate on struct or union"); // nothing to do, all members have offset 0 } - else - throw "member takes struct or union operand"; return false; } @@ -222,8 +220,7 @@ bool bv_pointerst::convert_address_of_rec( bvt bv_pointerst::convert_pointer_type(const exprt &expr) { - if(expr.type().id()!=ID_pointer) - throw "convert_pointer_type got non-pointer type"; + PRECONDITION(expr.type().id() == ID_pointer); // make sure the config hasn't been changed PRECONDITION(bits==boolbv_width(expr.type())); @@ -252,10 +249,9 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) } else if(expr.id()==ID_typecast) { - if(expr.operands().size()!=1) - throw "typecast takes one operand"; + const typecast_exprt &typecast_expr = to_typecast_expr(expr); - const exprt &op=expr.op0(); + const exprt &op = typecast_expr.op(); const typet &op_type=ns.follow(op.type()); if(op_type.id()==ID_pointer) @@ -288,15 +284,14 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) } else if(expr.id()==ID_address_of) { - if(expr.operands().size()!=1) - throw expr.id_string()+" takes one operand"; + const address_of_exprt &address_of_expr = to_address_of_expr(expr); bvt bv; bv.resize(bits); - if(convert_address_of_rec(expr.op0(), bv)) + if(convert_address_of_rec(address_of_expr.op(), bv)) { - conversion_failed(expr, bv); + conversion_failed(address_of_expr, bv); return bv; } @@ -324,15 +319,14 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) { // this has to be pointer plus integer - if(expr.operands().size()<2) - throw "operator + takes at least two operands"; + const plus_exprt &plus_expr = to_plus_expr(expr); bvt bv; mp_integer size=0; std::size_t count=0; - forall_operands(it, expr) + forall_operands(it, plus_expr) { if(it->type().id()==ID_pointer) { @@ -356,14 +350,13 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) } } - if(count==0) - throw "found no pointer in pointer-type sum"; - else if(count!=1) - throw "found more than one pointer in sum"; + INVARIANT( + count == 1, + "there should be exactly one pointer-type operand in a pointer-type sum"); bvt sum=bv_utils.build_constant(0, bits); - forall_operands(it, expr) + forall_operands(it, plus_expr) { if(it->type().id()==ID_pointer) continue; @@ -372,7 +365,7 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) it->type().id()!=ID_signedbv) { bvt bv; - conversion_failed(expr, bv); + conversion_failed(plus_expr, bv); return bv; } @@ -381,9 +374,7 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) bv_utilst::representationt::UNSIGNED; bvt op=convert_bv(*it); - - if(op.empty()) - throw "unexpected pointer arithmetic operand width"; + CHECK_RETURN(!op.empty()); // we cut any extra bits off @@ -403,27 +394,28 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) { // this is pointer-integer - if(expr.operands().size()!=2) - throw "operator "+expr.id_string()+" takes two operands"; + const minus_exprt &minus_expr = to_minus_expr(expr); - if(expr.op0().type().id()!=ID_pointer) - throw "found no pointer in pointer type in difference"; + INVARIANT( + minus_expr.op0().type().id() == ID_pointer, + "first operand should be of pointer type"); bvt bv; - if(expr.op1().type().id()!=ID_unsignedbv && - expr.op1().type().id()!=ID_signedbv) + if( + minus_expr.op1().type().id() != ID_unsignedbv && + minus_expr.op1().type().id() != ID_signedbv) { bvt bv; - conversion_failed(expr, bv); + conversion_failed(minus_expr, bv); return bv; } - const unary_minus_exprt neg_op1(expr.op1()); + const unary_minus_exprt neg_op1(minus_expr.op1()); - bv=convert_bv(expr.op0()); + bv = convert_bv(minus_expr.op0()); - typet pointer_sub_type=expr.op0().type().subtype(); + typet pointer_sub_type = minus_expr.op0().type().subtype(); mp_integer element_size; if(pointer_sub_type.id()==ID_empty) @@ -462,11 +454,15 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) { return SUB::convert_byte_extract(to_byte_extract_expr(expr)); } - else if( - expr.id() == ID_byte_update_little_endian || - expr.id() == ID_byte_update_big_endian) + else { - throw "byte-wise updates of pointers are unsupported"; + INVARIANT( + expr.id() != ID_byte_update_little_endian, + "byte-wise pointer updates are unsupported"); + + INVARIANT( + expr.id() != ID_byte_update_big_endian, + "byte-wise pointer updates are unsupported"); } return conversion_failed(expr); @@ -723,11 +719,13 @@ void bv_pointerst::add_addr(const exprt &expr, bvt &bv) std::size_t a=pointer_logic.add_object(expr); const std::size_t max_objects=std::size_t(1)< &pps) { - assert(!pps.empty()); + PRECONDITION(!pps.empty()); if(pps.size()==1) return pps.front(); @@ -605,7 +606,8 @@ bvt bv_utilst::wallace_tree(const std::vector &pps) &b=pps[i*3+1], &c=pps[i*3+2]; - assert(a.size()==b.size() && a.size()==c.size()); + INVARIANT(a.size() == b.size(), "groups should be of equal size"); + INVARIANT(a.size() == c.size(), "groups should be of equal size"); bvt s(a.size()), t(a.size()); @@ -625,7 +627,7 @@ bvt bv_utilst::wallace_tree(const std::vector &pps) for(std::size_t i=no_full_adders*3; i= 2); + PRECONDITION(var.size() == size); + PRECONDITION(!is_constant(var)); + PRECONDITION(is_constant(constant)); + PRECONDITION(size >= 2); // These get modified : be careful! bvt var_upper; @@ -1091,8 +1094,12 @@ literalt bv_utilst::equal_const(const bvt &var, const bvt &constant) } // Check we have split the array correctly - assert(var_upper.size() + var_lower.size() == size); - assert(constant_upper.size() + constant_lower.size() == size); + INVARIANT( + var_upper.size() + var_lower.size() == size, + "lower size plus upper size should equal the total size"); + INVARIANT( + constant_upper.size() + constant_lower.size() == size, + "lower size plus upper size should equal the total size"); literalt top_comparison = equal_const_rec(var_upper, constant_upper); literalt bottom_comparison = equal_const_rec(var_lower, constant_lower); @@ -1107,7 +1114,7 @@ literalt bv_utilst::equal_const(const bvt &var, const bvt &constant) /// \return The literal that is true if and only if they are equal. literalt bv_utilst::equal(const bvt &op0, const bvt &op1) { - assert(op0.size()==op1.size()); + PRECONDITION(op0.size() == op1.size()); #ifdef COMPACT_EQUAL_CONST // simplify_expr should put the constant on the right @@ -1150,7 +1157,7 @@ literalt bv_utilst::lt_or_le( const bvt &bv1, representationt rep) { - assert(bv0.size() == bv1.size()); + PRECONDITION(bv0.size() == bv1.size()); literalt top0=bv0[bv0.size()-1], top1=bv1[bv1.size()-1]; @@ -1169,7 +1176,8 @@ literalt bv_utilst::lt_or_le( if(rep==SIGNED) { - assert(bv0.size() >= 2); + INVARIANT( + bv0.size() >= 2, "signed bitvectors should have at least two bits"); start = compareBelow.size() - 2; literalt firstComp=compareBelow[start]; @@ -1247,10 +1255,13 @@ literalt bv_utilst::lt_or_le( if(rep==representationt::SIGNED) result=prop.lxor(prop.lequal(top0, top1), carry); - else if(rep==representationt::UNSIGNED) - result=!carry; else - assert(false); + { + INVARIANT( + rep == representationt::UNSIGNED, + "representation has either value signed or unsigned"); + result = !carry; + } if(or_equal) result=prop.lor(result, equal(bv0, bv1)); @@ -1314,7 +1325,7 @@ void bv_utilst::cond_implies_equal( const bvt &a, const bvt &b) { - assert(a.size()==b.size()); + PRECONDITION(a.size() == b.size()); if(prop.cnf_handled_well()) { diff --git a/src/util/exception_utils.cpp b/src/util/exception_utils.cpp index d43ccba01d8..ffd0b638f87 100644 --- a/src/util/exception_utils.cpp +++ b/src/util/exception_utils.cpp @@ -60,18 +60,28 @@ incorrect_goto_program_exceptiont::incorrect_goto_program_exceptiont( { } +std::string incorrect_goto_program_exceptiont::what() const +{ + return message + " (at: " + source_location.as_string() + ")"; +} + unsupported_operation_exceptiont::unsupported_operation_exceptiont( std::string message) : message(std::move(message)) { } -std::string incorrect_goto_program_exceptiont::what() const +std::string unsupported_operation_exceptiont::what() const { - return message + " (at: " + source_location.as_string() + ")"; + return message; } -std::string unsupported_operation_exceptiont::what() const +analysis_exceptiont::analysis_exceptiont(std::string reason) + : reason(std::move(reason)) { - return message; +} + +std::string analysis_exceptiont::what() const +{ + return reason; } diff --git a/src/util/exception_utils.h b/src/util/exception_utils.h index 163284cf2ca..9cc6c1fd608 100644 --- a/src/util/exception_utils.h +++ b/src/util/exception_utils.h @@ -107,4 +107,17 @@ class unsupported_operation_exceptiont : public cprover_exception_baset std::string message; }; +/// Thrown when an unexpected error occurs during the analysis (e.g., when the +/// SAT solver returns an error) +class analysis_exceptiont : public cprover_exception_baset +{ +public: + explicit analysis_exceptiont(std::string reason); + std::string what() const override; + +private: + /// The reason this exception was generated. + std::string reason; +}; + #endif // CPROVER_UTIL_EXCEPTION_UTILS_H