bool to_integer(const exprt &expr, mp_integer &int_value) { if(!expr.is_constant()) return true; const std::string &value = expr.value().as_string(); const irep_idt &type_id = expr.type().id(); if(type_id == "pointer") { if(value == "NULL") { int_value = 0; return false; } } else if(type_id == "c_enum" || type_id == "symbol") { int_value = string2integer(value); return false; } else if(type_id == "unsignedbv") { int_value = binary2integer(value, false); return false; } else if(type_id == "signedbv") { int_value = binary2integer(value, true); return false; } return true; }
std::string expr2javat::convert( const exprt &src, unsigned &precedence) { if(src.id()=="java-this") return convert_java_this(src, precedence=15); if(src.id()=="java_instanceof") return convert_java_instanceof(src, precedence=15); else if(src.id()==ID_side_effect && (src.get(ID_statement)==ID_java_new || src.get(ID_statement)==ID_java_new_array)) return convert_java_new(src, precedence=15); else if(src.id()==ID_side_effect && src.get(ID_statement)==ID_throw) return convert_function(src, "throw", precedence=16); else if(src.is_constant() && to_constant_expr(src).get_value()==ID_nullptr) return "nullptr"; else if(src.id()==ID_unassigned) return "?"; else if(src.id()=="pod_constructor") return "pod_constructor"; else if(src.id()==ID_virtual_function) return convert_function(src, "VIRTUAL_FUNCTION", precedence=16); else if(src.id()==ID_java_string_literal) return '"'+id2string(src.get(ID_value))+'"'; // Todo: add escaping as needed else return expr2ct::convert(src, precedence); }
void goto_convertt::read(exprt &expr, goto_programt &dest) { if(expr.is_constant()) return; if(expr.id()=="symbol") { // see if we already renamed it } symbolt &new_symbol=new_tmp_symbol(expr.type()); codet assignment("assign"); assignment.reserve_operands(2); assignment.copy_to_operands(symbol_expr(new_symbol)); assignment.move_to_operands(expr); goto_programt tmp_program; convert(assignment, tmp_program); dest.destructive_append(tmp_program); expr=symbol_expr(new_symbol); }
std::string format_constantt::operator()(const exprt &expr) { if(expr.is_constant()) { if(expr.type().id()==ID_natural || expr.type().id()==ID_integer || expr.type().id()==ID_unsignedbv || expr.type().id()==ID_signedbv) { mp_integer i; if(to_integer(expr, i)) return "(number conversion failed)"; return integer2string(i); } else if(expr.type().id()==ID_fixedbv) { return fixedbvt(expr).format(*this); } else if(expr.type().id()==ID_floatbv) { return ieee_floatt(expr).format(*this); } } else if(expr.id()==ID_string_constant) return expr.get_string(ID_value); return "(format-constant failed: "+expr.id_string()+")"; }
std::string inv_object_storet::build_string(const exprt &expr) const { // we ignore some casts if(expr.id()==ID_typecast) { assert(expr.operands().size()==1); if(expr.type().id()==ID_signedbv || expr.type().id()==ID_unsignedbv) { if(expr.op0().type().id()==ID_signedbv || expr.op0().type().id()==ID_unsignedbv) { if(to_bitvector_type(expr.type()).get_width()>= to_bitvector_type(expr.op0().type()).get_width()) return build_string(expr.op0()); } else if(expr.op0().type().id()==ID_bool) { return build_string(expr.op0()); } } } // we always track constants, but make sure they are uniquely // represented if(expr.is_constant()) { // NULL? if(expr.type().id()==ID_pointer) if(expr.get(ID_value)==ID_NULL) return "0"; mp_integer i; if(!to_integer(expr, i)) return integer2string(i); } // we also like "address_of" and "reference_to" // if the object is constant if(is_constant_address(expr)) return from_expr(ns, "", expr); if(expr.id()==ID_member) { assert(expr.operands().size()==1); return build_string(expr.op0())+"."+expr.get_string(ID_component_name); } if(expr.id()==ID_symbol) return expr.get_string(ID_identifier); return ""; }
std::string expr2javat::convert( const exprt &src, unsigned &precedence) { if(src.id()=="java-this") return convert_java_this(src, precedence=15); else if(src.id()==ID_side_effect && (src.get(ID_statement)==ID_java_new || src.get(ID_statement)==ID_java_new_array)) return convert_java_new(src, precedence=15); else if(src.id()==ID_side_effect && src.get(ID_statement)==ID_throw) return convert_function(src, "throw", precedence=16); else if(src.is_constant() && to_constant_expr(src).get_value()==ID_nullptr) return "nullptr"; else if(src.id()==ID_unassigned) return "?"; else if(src.id()=="pod_constructor") return "pod_constructor"; else return expr2ct::convert(src, precedence); }
void value_sett::get_value_set_rec( const exprt &expr, object_mapt &dest, const std::string &suffix, const typet &original_type, const namespacet &ns) const { #if 0 std::cout << "GET_VALUE_SET_REC EXPR: " << from_expr(ns, "", expr) << "\n"; std::cout << "GET_VALUE_SET_REC SUFFIX: " << suffix << std::endl; #endif const typet &expr_type=ns.follow(expr.type()); if(expr.id()==ID_unknown || expr.id()==ID_invalid) { insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_index) { assert(expr.operands().size()==2); const typet &type=ns.follow(expr.op0().type()); assert(type.id()==ID_array || type.id()==ID_incomplete_array); get_value_set_rec(expr.op0(), dest, "[]"+suffix, original_type, ns); } 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 || type.id()==ID_incomplete_struct || type.id()==ID_incomplete_union); const std::string &component_name= expr.get_string(ID_component_name); get_value_set_rec(expr.op0(), dest, "."+component_name+suffix, original_type, ns); } else if(expr.id()==ID_symbol) { irep_idt identifier=to_symbol_expr(expr).get_identifier(); // is it a pointer, integer, array or struct? if(expr_type.id()==ID_pointer || expr_type.id()==ID_signedbv || expr_type.id()==ID_unsignedbv || expr_type.id()==ID_struct || expr_type.id()==ID_union || expr_type.id()==ID_array) { // look it up valuest::const_iterator v_it= values.find(id2string(identifier)+suffix); // try first component name as suffix if not yet found if(v_it==values.end() && (expr_type.id()==ID_struct || expr_type.id()==ID_union)) { const struct_union_typet &struct_union_type= to_struct_union_type(expr_type); const std::string first_component_name= struct_union_type.components().front().get_string(ID_name); v_it=values.find( id2string(identifier)+"."+first_component_name+suffix); } // not found? try without suffix if(v_it==values.end()) v_it=values.find(identifier); if(v_it!=values.end()) make_union(dest, v_it->second.object_map); else insert(dest, exprt(ID_unknown, original_type)); } else insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_if) { if(expr.operands().size()!=3) throw "if takes three operands"; get_value_set_rec(expr.op1(), dest, suffix, original_type, ns); get_value_set_rec(expr.op2(), dest, suffix, original_type, ns); } else if(expr.id()==ID_address_of) { if(expr.operands().size()!=1) throw expr.id_string()+" expected to have one operand"; get_reference_set(expr.op0(), dest, ns); } else if(expr.id()==ID_dereference) { object_mapt reference_set; get_reference_set(expr, reference_set, ns); const object_map_dt &object_map=reference_set.read(); if(object_map.begin()==object_map.end()) insert(dest, exprt(ID_unknown, original_type)); else { for(object_map_dt::const_iterator it1=object_map.begin(); it1!=object_map.end(); it1++) { const exprt &object=object_numbering[it1->first]; get_value_set_rec(object, dest, suffix, original_type, ns); } } } else if(expr.id()=="reference_to") { // old stuff, will go away object_mapt reference_set; get_reference_set(expr, reference_set, ns); const object_map_dt &object_map=reference_set.read(); if(object_map.begin()==object_map.end()) insert(dest, exprt(ID_unknown, original_type)); else { for(object_map_dt::const_iterator it=object_map.begin(); it!=object_map.end(); it++) { const exprt &object=object_numbering[it->first]; get_value_set_rec(object, dest, suffix, original_type, ns); } } } else if(expr.is_constant()) { // check if NULL if(expr.get(ID_value)==ID_NULL && expr_type.id()==ID_pointer) { insert(dest, exprt("NULL-object", expr_type.subtype()), 0); } else if(expr_type.id()==ID_unsignedbv || expr_type.id()==ID_signedbv) { // an integer constant got turned into a pointer insert(dest, exprt(ID_integer_address, unsigned_char_type())); } else insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_typecast) { if(expr.operands().size()!=1) throw "typecast takes one operand"; // let's see what gets converted to what const typet &op_type=ns.follow(expr.op0().type()); if(op_type.id()==ID_pointer) { // pointer-to-pointer -- we just ignore these get_value_set_rec(expr.op0(), dest, suffix, original_type, ns); } else if(op_type.id()==ID_unsignedbv || op_type.id()==ID_signedbv) { // integer-to-pointer if(expr.op0().is_zero()) insert(dest, exprt("NULL-object", expr_type.subtype()), 0); else { // see if we have something for the integer object_mapt tmp; get_value_set_rec(expr.op0(), tmp, suffix, original_type, ns); if(tmp.read().size()==0) { // if not, throw in integer insert(dest, exprt(ID_integer_address, unsigned_char_type())); } else if(tmp.read().size()==1 && object_numbering[tmp.read().begin()->first].id()==ID_unknown) { // if not, throw in integer insert(dest, exprt(ID_integer_address, unsigned_char_type())); } else { // use as is dest.write().insert(tmp.read().begin(), tmp.read().end()); } } } else insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_plus || expr.id()==ID_minus) { if(expr.operands().size()<2) throw expr.id_string()+" expected to have at least two operands"; object_mapt pointer_expr_set; mp_integer i; bool i_is_set=false; // special case for pointer+integer if(expr.operands().size()==2 && expr_type.id()==ID_pointer) { exprt ptr_operand; if(expr.op0().type().id()!=ID_pointer && expr.op0().is_constant()) { i_is_set=!to_integer(expr.op0(), i); ptr_operand=expr.op1(); } else { i_is_set=!to_integer(expr.op1(), i); ptr_operand=expr.op0(); } if(i_is_set) { i*=pointer_offset_size(ptr_operand.type().subtype(), ns); if(expr.id()==ID_minus) i.negate(); } get_value_set_rec( ptr_operand, pointer_expr_set, "", ptr_operand.type(), ns); } else { // we get the points-to for all operands, even integers forall_operands(it, expr) { get_value_set_rec( *it, pointer_expr_set, "", it->type(), ns); } } for(object_map_dt::const_iterator it=pointer_expr_set.read().begin(); it!=pointer_expr_set.read().end(); it++) { objectt object=it->second; // adjust by offset if(object.offset_is_zero() && i_is_set) object.offset=i; else object.offset_is_set=false; insert(dest, it->first, object); } }
void abstract_expression( const predicatest &predicates, exprt &expr, const namespacet &ns) { if(expr.type().id()!=ID_bool) throw "abstract_expression expects expression of type Boolean"; simplify(expr, ns); if(is_valid(expr, ns)) { // If expr is valid, we can abstract it as 'true' expr.make_true(); } else if(is_unsatisfiable(expr, ns)) { // If expr is unsatisfiable, we can abstract it as 'false' expr.make_false(); } else if(expr.id()==ID_and || expr.id()==ID_or || expr.id()==ID_implies || expr.id()==ID_xor) { Forall_operands(it, expr) abstract_expression(predicates, *it, ns); } else if(expr.id()==ID_not) { assert(expr.operands().size()==1); abstract_expression(predicates, expr.op0(), ns); // remove double negation if(expr.op0().id()==ID_not && expr.op0().operands().size()==1) { exprt tmp; tmp.swap(expr.op0().op0()); expr.swap(tmp); } } else if(expr.id()==ID_if) { assert(expr.operands().size()==3); Forall_operands(it, expr) abstract_expression(predicates, *it, ns); exprt true_expr(ID_and, bool_typet()); true_expr.copy_to_operands(expr.op0(), expr.op1()); exprt false_expr(ID_and, bool_typet()); false_expr.copy_to_operands(gen_not(expr.op0()), expr.op2()); exprt or_expr(ID_or, bool_typet()); or_expr.move_to_operands(true_expr, false_expr); expr.swap(or_expr); } else if(expr.id()==ID_equal || expr.id()==ID_notequal) { if(expr.operands().size()!=2) throw expr.id_string()+" takes two operands"; // Is it equality on Booleans? if(expr.op0().type().id()==ID_bool && expr.op1().type().id()==ID_bool) { // leave it in Forall_operands(it, expr) abstract_expression(predicates, *it, ns); } else // other types, make it a predicate { if(has_non_boolean_if(expr)) { lift_if(expr); abstract_expression(predicates, expr, ns); } else make_it_a_predicate(predicates, expr, ns); } } else if(expr.is_constant()) { // leave it as is } else if(has_non_boolean_if(expr)) { lift_if(expr); abstract_expression(predicates, expr, ns); } else { make_it_a_predicate(predicates, expr, ns); } }
void bv_arithmetict::from_expr(const exprt &expr) { assert(expr.is_constant()); spec=expr.type(); value=binary2integer(expr.get_string(ID_value), spec.is_signed); }
void ieee_floatt::from_expr(const exprt &expr) { assert(expr.is_constant()); spec=to_floatbv_type(expr.type()); unpack(binary2integer(expr.get_string(ID_value), false)); }
bool inv_object_storet::is_constant(const exprt &expr) const { return expr.is_constant() || is_constant_address(expr); }