48 id==
"value_set::return_value" ||
49 id==
"value_set::memory")
53 return type.
id() == ID_struct || type.
id() == ID_struct_tag;
59 return !found.has_value() ? nullptr : &(found->get());
76 if(existing_entry.has_value())
106 auto entry=dest.
read().find(n);
108 if(entry==dest.
read().end())
113 else if(!entry->second)
115 else if(offset && *entry->second == *offset)
130 auto &new_offset = dest.
write()[n];
146 display_name = id2string(e.identifier) + e.suffix;
149 else if(e.
identifier ==
"value_set::return_value")
151 display_name =
"RETURN_VALUE" + e.suffix;
157 const symbolt &symbol=ns.lookup(e.identifier);
158 display_name=id2string(symbol.display_name())+e.suffix;
159 identifier=symbol.name;
161 identifier = id2string(e.identifier);
162 display_name = id2string(identifier) + e.suffix;
166 out << indent << display_name <<
" = { ";
170 std::size_t width = 0;
172 for(object_map_dt::const_iterator o_it = object_map.begin();
173 o_it != object_map.end();
176 const exprt &o = object_numbering[o_it->first];
178 std::ostringstream stream;
180 if(o.id() == ID_invalid || o.id() == ID_unknown)
184 stream <<
"<" << format(o) <<
", ";
187 stream << *o_it->second;
191 if(o.type().is_nil())
194 stream <<
", " << format(o.type());
199 const std::string result = stream.str();
201 width += result.size();
203 object_map_dt::const_iterator next(o_it);
206 if(next != object_map.end())
210 out <<
"\n" << std::string(indent.size(),
' ') <<
" ";
222 if(
object.
id()==ID_invalid ||
223 object.
id()==ID_unknown)
235 return std::move(od);
246 for(
const auto &delta_entry : delta_view)
248 if(delta_entry.is_in_both_maps())
251 delta_entry.get_other_map_value().object_map,
252 delta_entry.m.object_map))
255 make_union(existing_entry.object_map, delta_entry.m.object_map);
274 for(
const auto &number_and_offset : src.
read())
278 dest, number_and_offset.first, number_and_offset.second) !=
292 for(object_map_dt::const_iterator it=src.
read().begin();
293 it!=src.
read().end();
309 if(expr.
id()==ID_pointer_offset)
318 for(object_map_dt::const_iterator
319 it=object_map.begin();
320 it!=object_map.end();
329 if(!ptr_offset.has_value())
332 *ptr_offset += *it->second;
334 if(mod && *ptr_offset != previous_offset)
338 previous_offset = *ptr_offset;
359 .map([&](
const object_map_dt::value_type &pair) {
return to_expr(pair); });
365 bool is_simplified)
const
379 const std::string &suffix,
const std::string &field)
384 suffix.compare(1, field.length(), field) == 0 &&
385 (suffix.length() == field.length() + 1 ||
386 suffix[field.length() + 1] ==
'.' ||
387 suffix[field.length() + 1] ==
'[');
391 const std::string &suffix,
const std::string &field)
395 "suffix should start with " + field);
396 return suffix.substr(field.length() + 1);
402 const std::string &suffix,
406 type.
id() != ID_pointer && type.
id() != ID_signedbv &&
407 type.
id() != ID_unsignedbv && type.
id() != ID_array &&
408 type.
id() != ID_struct && type.
id() != ID_struct_tag &&
409 type.
id() != ID_union && type.
id() != ID_union_tag)
418 return std::move(index);
420 const typet &followed_type = type.
id() == ID_struct_tag
422 : type.
id() == ID_union_tag
427 if(followed_type.
id() == ID_struct || followed_type.
id() == ID_union)
434 const irep_idt &first_component_name =
435 struct_union_type.
components().front().get_name();
441 return std::move(index);
448 return std::move(identifier);
456 const std::string &suffix,
457 const typet &original_type,
461 std::cout <<
"GET_VALUE_SET_REC EXPR: " <<
format(expr) <<
"\n";
462 std::cout <<
"GET_VALUE_SET_REC SUFFIX: " << suffix <<
'\n';
467 if(expr.
id()==ID_unknown || expr.
id()==ID_invalid)
471 else if(expr.
id()==ID_index)
476 type.
id() == ID_array,
"operand 0 of index expression must be an array");
479 to_index_expr(expr).array(), dest,
"[]" + suffix, original_type, ns);
481 else if(expr.
id()==ID_member)
486 type.
id() == ID_struct || type.
id() == ID_union,
487 "compound of member expression must be struct or union");
489 const std::string &component_name=
495 "." + component_name + suffix,
499 else if(expr.
id()==ID_symbol)
504 if(entry_index.has_value())
509 else if(expr.
id() == ID_nondet_symbol)
511 if(expr.
type().
id() == ID_pointer)
528 else if(expr.
id()==ID_if)
531 to_if_expr(expr).true_case(), dest, suffix, original_type, ns);
533 to_if_expr(expr).false_case(), dest, suffix, original_type, ns);
535 else if(expr.
id()==ID_address_of)
539 else if(expr.
id()==ID_dereference)
545 if(object_map.begin()==object_map.end())
549 for(object_map_dt::const_iterator
550 it1=object_map.begin();
551 it1!=object_map.end();
571 else if(expr_type.
id()==ID_unsignedbv ||
572 expr_type.
id()==ID_signedbv)
580 else if(expr.
id()==ID_typecast)
585 const typet &op_type = op.type();
587 if(op_type.
id()==ID_pointer)
592 else if(op_type.
id()==ID_unsignedbv ||
593 op_type.
id()==ID_signedbv)
611 if(tmp.
read().empty())
616 else if(tmp.
read().size()==1 &&
633 expr.
id() == ID_plus || expr.
id() == ID_minus || expr.
id() == ID_bitor ||
634 expr.
id() == ID_bitand || expr.
id() == ID_bitxor ||
635 expr.
id() == ID_bitnand || expr.
id() == ID_bitnor ||
636 expr.
id() == ID_bitxnor)
639 throw expr.
id_string()+
" expected to have at least two operands";
647 expr_type.
id() == ID_pointer &&
648 (expr.
id() == ID_plus || expr.
id() == ID_minus))
650 bool non_const_offset =
false;
651 for(
const auto &op : expr.
operands())
653 if(op.type().id() == ID_pointer)
655 if(ptr_operand.has_value())
663 else if(!non_const_offset)
665 auto offset = numeric_cast<mp_integer>(op);
666 if(!offset.has_value())
669 non_const_offset =
true;
680 if(ptr_operand.has_value() && i.has_value())
682 typet pointer_base_type =
684 if(pointer_base_type.
id() == ID_empty)
689 if(!size.has_value() || (*size) == 0)
697 if(expr.
id()==ID_minus)
701 "unexpected subtraction of pointer from integer");
708 if(ptr_operand.has_value())
711 *ptr_operand, pointer_expr_set,
"", ptr_operand->type(), ns);
719 *it, pointer_expr_set,
"", it->type(), ns);
723 for(object_map_dt::const_iterator
724 it=pointer_expr_set.
read().begin();
725 it!=pointer_expr_set.
read().end();
731 if(offset && i.has_value())
736 insert(dest, it->first, offset);
739 else if(expr.
id()==ID_mult)
745 throw expr.
id_string()+
" expected to have at least two operands";
753 *it, pointer_expr_set,
"", it->type(), ns);
756 for(object_map_dt::const_iterator
757 it=pointer_expr_set.
read().begin();
758 it!=pointer_expr_set.
read().end();
766 insert(dest, it->first, offset);
769 else if(expr.
id() == ID_lshr || expr.
id() == ID_ashr || expr.
id() == ID_shl)
775 binary_expr.
op0(), pointer_expr_set,
"", binary_expr.
op0().
type(), ns);
777 for(
const auto &object_map_entry : pointer_expr_set.
read())
779 offsett offset = object_map_entry.second;
784 insert(dest, object_map_entry.first, offset);
787 else if(expr.
id()==ID_side_effect)
791 if(statement==ID_function_call)
794 throw "unexpected function_call sideeffect";
796 else if(statement==ID_allocate)
800 const typet &dynamic_type=
801 static_cast<const typet &
>(expr.
find(ID_C_cxx_alloc_type));
809 else if(statement==ID_cpp_new ||
810 statement==ID_cpp_new_array)
813 assert(expr_type.
id()==ID_pointer);
825 else if(expr.
id()==ID_struct)
829 struct_components.size() == expr.
operands().size(),
830 "struct expression should have an operand per component");
831 auto component_iter = struct_components.begin();
832 bool found_component =
false;
838 const std::string &component_name =
842 std::string remaining_suffix =
845 found_component =
true;
859 else if(expr.
id() == ID_union)
864 else if(expr.
id()==ID_with)
870 if(expr_type.
id() == ID_struct && !suffix.
empty())
876 std::string remaining_suffix =
879 with_expr.
new_value(), dest, remaining_suffix, original_type, ns);
895 else if(expr_type.
id() == ID_array && !suffix.
empty())
897 std::string new_value_suffix;
899 new_value_suffix = suffix.substr(2);
906 with_expr.
new_value(), dest, new_value_suffix, original_type, ns);
916 else if(expr.
id()==ID_array)
919 std::string new_suffix = suffix;
921 new_suffix = suffix.substr(2);
928 else if(expr.
id()==ID_array_of)
931 std::string new_suffix = suffix;
933 new_suffix = suffix.substr(2);
940 else if(expr.
id()==ID_dynamic_object)
945 const std::string prefix=
946 "value_set::dynamic_object"+
950 const std::string full_name=prefix+suffix;
964 else if(expr.
id()==ID_byte_extract_little_endian ||
965 expr.
id()==ID_byte_extract_big_endian)
971 const typet &op_type = ns.
follow(byte_extract_expr.op().type());
972 if(op_type.
id() == ID_struct)
974 exprt offset = byte_extract_expr.offset();
978 const auto offset_int = numeric_cast<mp_integer>(offset);
985 const irep_idt &name = c.get_name();
987 if(offset_int.has_value())
990 if(comp_offset.has_value())
993 type_size.has_value() && *offset_int + *type_size <= *comp_offset)
1000 member_size.has_value() &&
1001 *offset_int >= *comp_offset + *member_size)
1015 if(op_type.
id() == ID_union)
1020 const irep_idt &name = c.get_name();
1021 member_exprt member(byte_extract_expr.op(), name, c.type());
1029 byte_extract_expr.op(), dest, suffix, original_type, ns);
1031 else if(expr.
id()==ID_byte_update_little_endian ||
1032 expr.
id()==ID_byte_update_big_endian)
1039 byte_update_expr.value(), dest, suffix, original_type, ns);
1043 else if(expr.
id() == ID_let)
1048 value_sett value_set_with_local_definition = *
this;
1049 value_set_with_local_definition.
assign(
1050 let_expr.symbol(), let_expr.value(), ns,
false,
false);
1053 let_expr.where(), dest, suffix, original_type, ns);
1061 std::cout <<
"GET_VALUE_SET_REC RESULT:\n";
1062 for(
const auto &obj : dest.
read())
1065 std::cout <<
" " <<
format(e) <<
"\n";
1076 if(src.
id()==ID_typecast)
1078 assert(src.
type().
id()==ID_pointer);
1094 for(object_map_dt::const_iterator
1095 it=object_map.
read().begin();
1096 it!=object_map.
read().end();
1107 std::cout <<
"GET_REFERENCE_SET_REC EXPR: " <<
format(expr)
1111 if(expr.
id()==ID_symbol ||
1112 expr.
id()==ID_dynamic_object ||
1113 expr.
id()==ID_string_constant ||
1114 expr.
id()==ID_array)
1117 expr.
type().
id() == ID_array &&
1125 else if(expr.
id()==ID_dereference)
1132 for(
const auto &map_entry : dest.
read())
1141 else if(expr.
id()==ID_index)
1144 throw "index expected to have two operands";
1151 array.
type().
id() == ID_array,
"index takes array-typed operand");
1160 for(object_map_dt::const_iterator
1161 a_it=object_map.begin();
1162 a_it!=object_map.end();
1167 if(
object.
id()==ID_unknown)
1176 const auto i = numeric_cast<mp_integer>(offset);
1181 else if(i.has_value() && o)
1185 if(!size.has_value() || *size == 0)
1193 insert(dest, deref_index_expr, o);
1199 else if(expr.
id()==ID_member)
1201 const irep_idt &component_name=expr.
get(ID_component_name);
1210 for(object_map_dt::const_iterator
1211 it=object_map.begin();
1212 it!=object_map.end();
1217 if(
object.
id()==ID_unknown)
1220 object.type().
id() == ID_struct ||
1221 object.type().
id() == ID_struct_tag ||
object.type().
id() == ID_union ||
1222 object.type().
id() == ID_union_tag)
1231 const typet &final_object_type = ns.
follow(
object.type());
1233 if(final_object_type.
id()==ID_struct ||
1234 final_object_type.
id()==ID_union)
1237 if(ns.
follow(struct_op.
type())!=final_object_type)
1243 insert(dest, member_expr, o);
1254 else if(expr.
id()==ID_if)
1272 std::cout <<
"ASSIGN LHS: " <<
format(lhs) <<
" : "
1274 std::cout <<
"ASSIGN RHS: " <<
format(rhs) <<
" : "
1276 std::cout <<
"--------------------------------------------\n";
1282 if(type.
id() == ID_struct)
1286 const typet &subtype = c.type();
1287 const irep_idt &name = c.get_name();
1290 if(subtype.
id() == ID_code || c.get_is_padding())
1297 if(rhs.
id()==ID_unknown ||
1298 rhs.
id()==ID_invalid)
1303 rhs_member=
exprt(rhs.
id(), subtype);
1309 "value_sett::assign types should match, got: "
1315 if(followed.
id() == ID_struct || followed.
id() == ID_union)
1323 assign(lhs_member, rhs_member, ns,
true, add_to_sets);
1328 else if(type.
id()==ID_array)
1335 if(rhs.
id()==ID_unknown ||
1336 rhs.
id()==ID_invalid)
1349 "value_sett::assign types should match, got: "
1353 if(rhs.
id()==ID_array_of)
1362 else if(rhs.
id()==ID_array ||
1363 rhs.
id()==ID_constant)
1367 assign(lhs_index, *o_it, ns, is_simplified, add_to_sets);
1371 else if(rhs.
id()==ID_with)
1378 assign(lhs_index, op0_index, ns, is_simplified, add_to_sets);
1380 lhs_index,
to_with_expr(rhs).new_value(), ns, is_simplified,
true);
1388 assign(lhs_index, rhs_index, ns, is_simplified,
true);
1403 assign_rec(lhs, values_rhs,
"", ns, add_to_sets);
1410 const std::string &suffix,
1415 std::cout <<
"ASSIGN_REC LHS: " <<
format(lhs) <<
'\n';
1416 std::cout <<
"ASSIGN_REC LHS ID: " << lhs.
id() <<
'\n';
1417 std::cout <<
"ASSIGN_REC SUFFIX: " << suffix <<
'\n';
1419 for(object_map_dt::const_iterator it=values_rhs.
read().begin();
1420 it!=values_rhs.
read().end();
1422 std::cout <<
"ASSIGN_REC RHS: " <<
1427 if(lhs.
id()==ID_symbol)
1432 entryt{identifier, suffix}, lhs.
type(), values_rhs, add_to_sets);
1434 else if(lhs.
id()==ID_dynamic_object)
1439 const std::string name=
1440 "value_set::dynamic_object"+
1445 else if(lhs.
id()==ID_dereference)
1448 throw lhs.
id_string()+
" expected to have one operand";
1453 if(reference_set.
read().size()!=1)
1456 for(object_map_dt::const_iterator
1457 it=reference_set.
read().begin();
1458 it!=reference_set.
read().end();
1465 if(
object.
id()!=ID_unknown)
1466 assign_rec(
object, values_rhs, suffix, ns, add_to_sets);
1469 else if(lhs.
id()==ID_index)
1473 const typet &type = array.type();
1476 type.
id() == ID_array,
"operand 0 of index expression must be an array");
1478 assign_rec(array, values_rhs,
"[]" + suffix, ns,
true);
1480 else if(lhs.
id()==ID_member)
1483 const auto &component_name = lhs_member_expr.get_component_name();
1485 const typet &type = ns.
follow(lhs_member_expr.compound().type());
1488 type.
id() == ID_struct || type.
id() == ID_union,
1489 "operand 0 of member expression must be struct or union");
1492 lhs_member_expr.compound(),
1494 "." +
id2string(component_name) + suffix,
1498 else if(lhs.
id()==
"valid_object" ||
1499 lhs.
id()==
"dynamic_type" ||
1500 lhs.
id()==
"is_zero_string" ||
1501 lhs.
id()==
"zero_string" ||
1502 lhs.
id()==
"zero_string_length")
1506 else if(lhs.
id()==ID_string_constant)
1511 else if(lhs.
id() == ID_null_object)
1515 else if(lhs.
id()==ID_typecast)
1519 assign_rec(typecast_expr.
op(), values_rhs, suffix, ns, add_to_sets);
1521 else if(lhs.
id()==ID_byte_extract_little_endian ||
1522 lhs.
id()==ID_byte_extract_big_endian)
1526 else if(lhs.
id()==ID_integer_address)
1532 throw "assign NYI: '" + lhs.
id_string() +
"'";
1550 for(std::size_t i=0; i<arguments.size(); i++)
1552 const std::string identifier=
"value_set::dummy_arg_"+
std::to_string(i);
1553 const symbol_exprt dummy_lhs(identifier, arguments[i].type());
1554 assign(dummy_lhs, arguments[i], ns,
false,
false);
1561 for(code_typet::parameterst::const_iterator
1562 it=parameter_types.begin();
1563 it!=parameter_types.end();
1566 const irep_idt &identifier=it->get_identifier();
1567 if(identifier.
empty())
1574 assign(actual_lhs, v_expr, ns,
true,
true);
1590 assign(lhs, rhs, ns,
false,
false);
1599 if(statement==ID_block)
1604 else if(statement==ID_function_call)
1609 else if(statement==ID_assign)
1612 throw "assignment expected to have two operands";
1616 else if(statement==ID_decl)
1619 throw "decl expected to have one operand";
1623 if(lhs.
id()!=ID_symbol)
1624 throw "decl expected to have symbol on lhs";
1629 lhs_type.
id() == ID_pointer ||
1630 (lhs_type.
id() == ID_array &&
1637 assign(lhs, address_of_expr, ns,
false,
false);
1643 else if(statement==ID_expression)
1647 else if(statement == ID_cpp_delete || statement == ID_cpp_delete_array)
1651 else if(statement==
"lock" || statement==
"unlock")
1655 else if(statement==ID_asm)
1659 else if(statement==ID_nondet)
1663 else if(statement==ID_printf)
1667 else if(statement==ID_return)
1675 else if(statement==ID_array_set)
1678 else if(statement==ID_array_copy)
1681 else if(statement==ID_array_replace)
1684 else if(statement == ID_array_equal)
1687 else if(statement==ID_assume)
1691 else if(statement==ID_user_specified_predicate ||
1692 statement==ID_user_specified_parameter_predicates ||
1693 statement==ID_user_specified_return_predicates)
1697 else if(statement==ID_fence)
1704 else if(statement==ID_dead)
1708 else if(statement == ID_havoc_object)
1714 throw "value_sett: unexpected statement: "+
id2string(statement);
1722 if(expr.
id()==ID_and)
1727 else if(expr.
id()==ID_equal)
1730 else if(expr.
id()==ID_notequal)
1733 else if(expr.
id()==ID_not)
1736 else if(expr.
id()==ID_dynamic_object)
1752 const std::unordered_set<exprt, irep_hash> &values_to_erase)
1754 if(values_to_erase.empty())
1761 std::vector<object_map_dt::key_type> keys_to_erase;
1763 for(
auto &key_value : entry->object_map.read())
1765 const auto &rhs_object =
to_expr(key_value);
1766 if(values_to_erase.count(rhs_object))
1768 keys_to_erase.emplace_back(key_value.first);
1773 keys_to_erase.size() == values_to_erase.size(),
1774 "value_sett::erase_value_from_entry() should erase exactly one value for "
1775 "each element in the set it is given");
1777 entryt replacement = *entry;
1778 for(
const auto &key_to_erase : keys_to_erase)
1787 const std::string &erase_prefix,
1790 for(
const auto &c : struct_union_type.
components())
1792 const typet &subtype = c.type();
1793 const irep_idt &name = c.get_name();
1796 if(subtype.
id() == ID_code || c.get_is_padding())
1805 const std::string &erase_prefix,
1808 if(type.
id() == ID_struct_tag)
1811 else if(type.
id() == ID_union_tag)
1814 else if(type.
id() == ID_array)
1816 to_array_type(type).element_type(), erase_prefix +
"[]", ns);