void goto_checkt::pointer_rel_check( const exprt &expr, const guardt &guard) { if(!enable_pointer_check) return; if(expr.operands().size()!=2) throw expr.id_string()+" takes two arguments"; if(expr.op0().type().id()==ID_pointer && expr.op1().type().id()==ID_pointer) { // add same-object subgoal if(enable_pointer_check) { exprt same_object=::same_object(expr.op0(), expr.op1()); add_guarded_claim( same_object, "same object violation", "pointer", expr.find_source_location(), expr, guard); } } }
bool simplify_exprt::simplify_ieee_float_relation(exprt &expr) { assert(expr.id()==ID_ieee_float_equal || expr.id()==ID_ieee_float_notequal); exprt::operandst &operands=expr.operands(); if(expr.type().id()!=ID_bool) return true; if(operands.size()!=2) return true; // types must match if(expr.op0().type()!=expr.op1().type()) return true; if(expr.op0().type().id()!=ID_floatbv) return true; // first see if we compare to a constant if(expr.op0().is_constant() && expr.op1().is_constant()) { ieee_floatt f0(to_constant_expr(expr.op0())); ieee_floatt f1(to_constant_expr(expr.op1())); if(expr.id()==ID_ieee_float_notequal) expr.make_bool(f0.ieee_not_equal(f1)); else if(expr.id()==ID_ieee_float_equal) expr.make_bool(f0.ieee_equal(f1)); else assert(false); return false; } if(expr.op0()==expr.op1()) { // x!=x is the same as saying isnan(op) exprt isnan(ID_isnan, bool_typet()); isnan.copy_to_operands(expr.op0()); if(expr.id()==ID_ieee_float_notequal) { } else if(expr.id()==ID_ieee_float_equal) isnan.make_not(); else assert(false); expr.swap(isnan); return false; } return true; }
void boolbvt::convert_div(const exprt &expr, bvt &bv) { if(expr.type().id()!=ID_unsignedbv && expr.type().id()!=ID_signedbv && expr.type().id()!=ID_fixedbv) return conversion_failed(expr, bv); unsigned width=boolbv_width(expr.type()); if(width==0) return conversion_failed(expr, bv); if(expr.operands().size()!=2) throw "division takes two operands"; if(expr.op0().type().id()!=expr.type().id() || expr.op1().type().id()!=expr.type().id()) return conversion_failed(expr, bv); bvt op0=convert_bv(expr.op0()); bvt op1=convert_bv(expr.op1()); if(op0.size()!=width || op1.size()!=width) throw "convert_div: unexpected operand width"; bvt res, rem; if(expr.type().id()==ID_fixedbv) { unsigned fraction_bits= to_fixedbv_type(expr.type()).get_fraction_bits(); bvt zeros; zeros.resize(fraction_bits, const_literal(false)); // add fraction_bits least-significant bits op0.insert(op0.begin(), zeros.begin(), zeros.end()); op1=bv_utils.sign_extension(op1, op1.size()+fraction_bits); bv_utils.divider(op0, op1, res, rem, bv_utilst::SIGNED); // cut it down again res.resize(width); } else { bv_utilst::representationt rep= expr.type().id()==ID_signedbv?bv_utilst::SIGNED: bv_utilst::UNSIGNED; bv_utils.divider(op0, op1, res, rem, rep); } bv=res; }
void invariant_sett::strengthen_rec(const exprt &expr) { if(expr.type().id()!=ID_bool) throw "non-Boolean argument to strengthen()"; #if 0 std::cout << "S: " << from_expr(*ns, "", expr) << '\n'; #endif if(is_false) { // we can't get any stronger return; } if(expr.is_true()) { // do nothing, it's useless } else if(expr.is_false()) { // wow, that's strong make_false(); } else if(expr.id()==ID_not) { // give up, we expect NNF } else if(expr.id()==ID_and) { forall_operands(it, expr) strengthen_rec(*it); } else if(expr.id()==ID_le || expr.id()==ID_lt) { assert(expr.operands().size()==2); // special rule: x <= (a & b) // implies: x<=a && x<=b if(expr.op1().id()==ID_bitand) { const exprt &bitand_op=expr.op1(); forall_operands(it, bitand_op) { exprt tmp(expr); tmp.op1()=*it; strengthen_rec(tmp); } return; }
void boolbvt::convert_replication(const exprt &expr, bvt &bv) { unsigned width=boolbv_width(expr.type()); if(width==0) return conversion_failed(expr, bv); if(expr.operands().size()!=2) throw "replication takes two operands"; mp_integer times; if(to_integer(expr.op0(), times)) throw "replication takes constant as first parameter"; const unsigned u_times=integer2unsigned(times); const bvt &op=convert_bv(expr.op1()); unsigned offset=0; bv.resize(width); for(unsigned i=0; i<u_times; i++) { if(op.size()+offset>width) throw "replication operand width too big"; for(unsigned i=0; i<op.size(); i++) bv[i+offset]=op[i]; offset+=op.size(); } if(offset!=bv.size()) throw "replication operand width too small"; }
exprt dereferencet::dereference_plus( const exprt &expr, const exprt &offset, const typet &type) { if(expr.operands().size()>2) return dereference_rec(make_binary(expr), offset, type); // binary exprt pointer=expr.op0(), integer=expr.op1(); if(ns.follow(integer.type()).id()==ID_pointer) std::swap(pointer, integer); // multiply integer by object size exprt size=size_of_expr(pointer.type().subtype(), ns); if(size.is_nil()) throw "dereference failed to get object size for pointer arithmetic"; // make types of offset and size match if(size.type()!=integer.type()) integer.make_typecast(size.type()); exprt new_offset=plus_exprt(offset, mult_exprt(size, integer)); return dereference_rec(pointer, new_offset, type); }
exprt modelchecker_smvt::convert_schoose_expression( const exprt &expr, const exprt &guard) { nondet_symbolst::const_iterator it= nondet_symbols.find(static_cast<const exprt &>(expr.find("expression"))); if(it==nondet_symbols.end()) throw "failed to find nondet_symbol"; exprt nondet("symbol", typet("bool")); nondet.set("identifier", it->second); exprt conj("and", typet("bool")); conj.move_to_operands(nondet); conj.copy_to_operands(expr.op1()); conj.op1().make_not(); //exprt disj("or", typet("bool")); //disj.copy_to_operands(expr.op0(), guard); exprt target("or", typet("bool")); target.move_to_operands(conj); target.copy_to_operands(expr.op0()); return target; }
/// checks whether a termination argument implies termination threevalt summarizer_fw_termt::check_termination_argument(exprt expr) { if(expr.is_false()) return YES; // should be of the form /\_i g_i=> R_i if(expr.id()==ID_and) { threevalt result=YES; for(exprt::operandst::iterator it=expr.operands().begin(); it!=expr.operands().end(); it++) { if(it->is_true()) result=UNKNOWN; if(it->id()==ID_implies) { if(it->op1().is_true()) result=UNKNOWN; } } return result; } else { if(expr.id()==ID_implies) { if(expr.op1().is_true()) return UNKNOWN; } else return !expr.is_true() ? YES : UNKNOWN; } return YES; }
literalt boolbvt::convert_ieee_float_rel(const exprt &expr) { const exprt::operandst &operands=expr.operands(); const irep_idt &rel=expr.id(); if(operands.size()==2) { const exprt &op0=expr.op0(); const exprt &op1=expr.op1(); bvtypet bvtype0=get_bvtype(op0.type()); bvtypet bvtype1=get_bvtype(op1.type()); const bvt &bv0=convert_bv(op0); const bvt &bv1=convert_bv(op1); if(bv0.size()==bv1.size() && !bv0.empty() && bvtype0==IS_FLOAT && bvtype1==IS_FLOAT) { float_utilst float_utils(prop); float_utils.spec=to_floatbv_type(op0.type()); if(rel==ID_ieee_float_equal) return float_utils.relation(bv0, float_utilst::EQ, bv1); else if(rel==ID_ieee_float_notequal) return !float_utils.relation(bv0, float_utilst::EQ, bv1); else return SUB::convert_rest(expr); } } return SUB::convert_rest(expr); }
void jsil_typecheckt::typecheck_expr_ref(exprt &expr) { if(expr.operands().size()!=3) { err_location(expr); error() << "operator `" << expr.id() << "' expects three operands" << eom; throw 0; } make_type_compatible(expr.op0(), jsil_value_type(), true); make_type_compatible(expr.op1(), string_typet(), true); exprt &operand3=expr.op2(); make_type_compatible(operand3, jsil_kind(), true); if(operand3.id()==ID_member) expr.type()=jsil_member_reference_type(); else if(operand3.id()=="variable") expr.type()=jsil_variable_reference_type(); else { err_location(expr); error() << "operator `" << expr.id() << "' expects reference type in the third parameter. Got:" << operand3.pretty() << eom; throw 0; } }
void goto_checkt::pointer_rel_check(const exprt &expr, const guardt &guard) { if (expr.operands().size() != 2) throw expr.id_string() + " takes one argument"; if (expr.op0().type().id() == "pointer" && expr.op1().type().id() == "pointer") { // add same-object subgoal if (!options.get_bool_option("no-pointer-check")) { exprt same_object("same-object", bool_typet()); same_object.copy_to_operands(expr.op0(), expr.op1()); add_guarded_claim(same_object, "same object violation", "pointer", expr.find_location(), guard); } } }
void jsil_typecheckt::typecheck_expr_index(exprt &expr) { if(expr.operands().size()!=2) { err_location(expr); error() << "operator `" << expr.id() << "' expects two operands" << eom; throw 0; } make_type_compatible(expr.op0(), jsil_object_type(), true); make_type_compatible(expr.op1(), string_typet(), true); // special case for function identifiers if (expr.op1().id()=="fid" || expr.op1().id()=="constructid") expr.type()=code_typet(); else expr.type()=jsil_value_type(); }
void bv_refinementt::convert_mod(const exprt &expr, bvt &bv) { // we catch any mod // unless it's integer + constant assert(expr.operands().size()==2); if(expr.op1().is_constant()) return SUB::convert_mod(expr, bv); add_approximation(expr, bv); }
void goto_checkt::div_by_zero_check(const exprt &expr, const guardt &guard) { if (options.get_bool_option("no-div-by-zero-check")) return; if (expr.operands().size() != 2) throw expr.id_string() + " takes two arguments"; // add divison by zero subgoal exprt zero = gen_zero(expr.op1().type()); if (zero.is_nil()) throw "no zero of argument type of operator " + expr.id_string(); exprt inequality("notequal", bool_typet()); inequality.copy_to_operands(expr.op1(), zero); add_guarded_claim(inequality, "division by zero", "division-by-zero", expr.find_location(), guard); }
std::string expr2javat::convert_java_instanceof( const exprt &src, unsigned precedence) { if(src.operands().size()!=2) { unsigned precedence; return convert_norep(src, precedence); } return convert(src.op0())+" instanceof "+convert(src.op1().type()); }
mp_integer compute_pointer_offset( const namespacet &ns, const exprt &expr) { if(expr.id()==ID_symbol) return 0; else if(expr.id()==ID_index) { assert(expr.operands().size()==2); const typet &array_type=ns.follow(expr.op0().type()); assert(array_type.id()==ID_array); mp_integer o=compute_pointer_offset(ns, expr.op0()); if(o!=-1) { mp_integer sub_size= pointer_offset_size(ns, array_type.subtype()); mp_integer i; if(sub_size!=0 && !to_integer(expr.op1(), i)) return o+i*sub_size; } // don't know } else if(expr.id()==ID_member) { assert(expr.operands().size()==1); const typet &type=ns.follow(expr.op0().type()); assert(type.id()==ID_struct || type.id()==ID_union); mp_integer o=compute_pointer_offset(ns, expr.op0()); if(o!=-1) { if(type.id()==ID_union) return o; return o+member_offset( ns, to_struct_type(type), expr.get(ID_component_name)); } } else if(expr.id()==ID_string_constant) return 0; return -1; // don't know }
bool simplify_exprt::simplify_inequality_address_of(exprt &expr) { assert(expr.type().id()==ID_bool); assert(expr.operands().size()==2); assert(expr.id()==ID_equal || expr.id()==ID_notequal); exprt tmp0=expr.op0(); if(tmp0.id()==ID_typecast) tmp0=expr.op0().op0(); if(tmp0.op0().id()==ID_index && to_index_expr(tmp0.op0()).index().is_zero()) tmp0=address_of_exprt(to_index_expr(tmp0.op0()).array()); exprt tmp1=expr.op1(); if(tmp1.id()==ID_typecast) tmp1=expr.op1().op0(); if(tmp1.op0().id()==ID_index && to_index_expr(tmp1.op0()).index().is_zero()) tmp1=address_of_exprt(to_index_expr(tmp1.op0()).array()); assert(tmp0.id()==ID_address_of); assert(tmp1.id()==ID_address_of); if(tmp0.operands().size()!=1) return true; if(tmp1.operands().size()!=1) return true; if(tmp0.op0().id()==ID_symbol && tmp1.op0().id()==ID_symbol) { bool equal= tmp0.op0().get(ID_identifier)== tmp1.op0().get(ID_identifier); expr.make_bool(expr.id()==ID_equal?equal:!equal); return false; } return true; }
void jsil_typecheckt::typecheck_expr_binary_compare(exprt &expr) { if(expr.operands().size()!=2) { err_location(expr); error() << "operator `" << expr.id() << "' expects two operands" << eom; throw 0; } make_type_compatible(expr.op0(), floatbv_typet(), true); make_type_compatible(expr.op1(), floatbv_typet(), true); expr.type()=bool_typet(); }
void jsil_typecheckt::typecheck_expr_concatenation(exprt &expr) { if(expr.operands().size()!=2) { err_location(expr); error() << "operator `" << expr.id() << "' expects two operands" << eom; throw 0; } make_type_compatible(expr.op0(), string_typet(), true); make_type_compatible(expr.op1(), string_typet(), true); expr.type()=string_typet(); }
void goto_symext::rewrite_quantifiers(exprt &expr, statet &state) { if(expr.id()==ID_forall) { // forall X. P -> P // we keep the quantified variable unique by means of L2 renaming assert(expr.operands().size()==2); assert(expr.op0().id()==ID_symbol); symbol_exprt tmp0= to_symbol_expr(to_ssa_expr(expr.op0()).get_original_expr()); symex_decl(state, tmp0); exprt tmp=expr.op1(); expr.swap(tmp); } }
void jsil_typecheckt::typecheck_expr_proto_obj(exprt &expr) { if(expr.operands().size()!=2) { err_location(expr); error() << "operator `" << expr.id() << "' expects two operands"; throw 0; } make_type_compatible(expr.op0(), jsil_object_type(), true); make_type_compatible(expr.op1(), jsil_object_type(), true); expr.type()=bool_typet(); }
void jsil_typecheckt::typecheck_expr_proto_field(exprt &expr) { if(expr.operands().size()!=2) { err_location(expr); error() << "operator `" << expr.id() << "' expects two operands" << eom; throw 0; } make_type_compatible(expr.op0(), jsil_object_type(), true); make_type_compatible(expr.op1(), string_typet(), true); expr.type()=jsil_value_or_empty_type(); }
void goto_symext::replace_array_equal(exprt &expr) { if(expr.id()==ID_array_equal) { assert(expr.operands().size()==2); // we expect two index expressions process_array_expr(expr.op0()); process_array_expr(expr.op1()); // type checking if(ns.follow(expr.op0().type())!= ns.follow(expr.op1().type())) expr=false_exprt(); else { equal_exprt equality_expr(expr.op0(), expr.op1()); expr.swap(equality_expr); } } Forall_operands(it, expr) replace_array_equal(*it); }
void bv_refinementt::set_to(const exprt &expr, bool value) { #if 0 unsigned prev=prop.no_variables(); SUB::set_to(expr, value); unsigned n=prop.no_variables()-prev; std::cout << n << " EEE " << expr.id() << "@" << expr.type().id(); forall_operands(it, expr) std::cout << " " << it->id() << "@" << it->type().id(); if(expr.id()=="=" && expr.operands().size()==2) forall_operands(it, expr.op1()) std::cout << " " << it->id() << "@" << it->type().id(); std::cout << std::endl; #else SUB::set_to(expr, value); #endif }
bool inv_object_storet::is_constant_address_rec(const exprt &expr) { if(expr.id()==ID_symbol) return true; else if(expr.id()==ID_member) { assert(expr.operands().size()==1); return is_constant_address_rec(expr.op0()); } else if(expr.id()==ID_index) { assert(expr.operands().size()==2); if(expr.op1().is_constant()) return is_constant_address_rec(expr.op0()); } return false; }
void interval_domaint::assume_rec( const exprt &cond, bool negation) { if(cond.id()==ID_lt || cond.id()==ID_le || cond.id()==ID_gt || cond.id()==ID_ge || cond.id()==ID_equal || cond.id()==ID_notequal) { assert(cond.operands().size()==2); if(negation) // !x<y ---> x>=y { if(cond.id()==ID_lt) assume_rec(cond.op0(), ID_ge, cond.op1()); else if(cond.id()==ID_le) assume_rec(cond.op0(), ID_gt, cond.op1()); else if(cond.id()==ID_gt) assume_rec(cond.op0(), ID_le, cond.op1()); else if(cond.id()==ID_ge) assume_rec(cond.op0(), ID_lt, cond.op1()); else if(cond.id()==ID_equal) assume_rec(cond.op0(), ID_notequal, cond.op1()); else if(cond.id()==ID_notequal) assume_rec(cond.op0(), ID_equal, cond.op1()); } else assume_rec(cond.op0(), cond.id(), cond.op1()); } else if(cond.id()==ID_not) { assume_rec(to_not_expr(cond).op(), !negation); } else if(cond.id()==ID_and) { if(!negation) forall_operands(it, cond) assume_rec(*it, false); } else if(cond.id()==ID_or) { if(negation) forall_operands(it, cond) assume_rec(*it, true); } }
void boolbvt::convert_update(const exprt &expr, bvt &bv) { const exprt::operandst &ops=expr.operands(); if(ops.size()!=3) throw "update takes at three operands"; std::size_t width=boolbv_width(expr.type()); if(width==0) return conversion_failed(expr, bv); bv=convert_bv(ops[0]); if(bv.size()!=width) throw "update: unexpected operand 0 width"; // start the recursion convert_update_rec( expr.op1().operands(), 0, expr.type(), 0, expr.op2(), bv); }
literalt dplib_convt::convert_rest(const exprt &expr) { //dplib_prop.out << "%% E: " << expr << std::endl; literalt l=prop.new_variable(); find_symbols(expr); if(expr.id()==ID_equal || expr.id()==ID_notequal) { assert(expr.operands().size()==2); dplib_prop.out << "ASSERT " << dplib_prop.dplib_literal(l) << " <=> ("; convert_dplib_expr(expr.op0()); dplib_prop.out << ((expr.id()==ID_equal)?"=":"/="); convert_dplib_expr(expr.op1()); dplib_prop.out << ");" << std::endl; } return l; }
void path_slicert::get_symbols(const exprt &expr, string_sett &s) { if(expr.id()==ID_symbol) { s.insert(to_symbol_expr(expr).get_identifier()); } else if(expr.id()==ID_index) { assert(expr.operands().size()==2); string_sett tmp; get_symbols(expr.op0(), tmp); get_symbols(expr.op1(), s); for(string_sett::const_iterator it=tmp.begin(); it!=tmp.end(); it++) s.insert(id2string(*it)+"[]"); } else if(expr.id()==ID_member) { assert(expr.operands().size()==1); string_sett tmp; get_symbols(expr.op0(), tmp); std::string suffix="."+expr.get_string(ID_component_name); for(string_sett::const_iterator it=tmp.begin(); it!=tmp.end(); it++) s.insert(id2string(*it)+suffix); } else forall_operands(it, expr) get_symbols(*it, s); }
void boolbvt::convert_shift(const exprt &expr, bvt &bv) { if(expr.type().id()!=ID_unsignedbv && expr.type().id()!=ID_signedbv) return conversion_failed(expr, bv); unsigned width=boolbv_width(expr.type()); if(width==0) return conversion_failed(expr, bv); if(width==0) throw "zero length bit vector type: "+expr.type().to_string(); if(expr.operands().size()!=2) throw "shifting takes two operands"; bvt op, dist; convert_bv(expr.op0(), op); convert_bv(expr.op1(), dist); if(op.size()!=width) throw "convert_shift: unexpected operand width"; bv_utilst::shiftt shift; if(expr.id()==ID_shl) shift=bv_utilst::LEFT; else if(expr.id()==ID_ashr) shift=bv_utilst::ARIGHT; else if(expr.id()==ID_lshr) shift=bv_utilst::LRIGHT; else throw "unexpected operand"; bv=bv_utils.shift(op, shift, dist); }