20#define ENABLE_ARRAY_FIELD_SENSITIVITY
29 return std::move(ssa_expr);
58 widest.has_value() && union_size.has_value() &&
59 widest->second == *union_size)
67 return apply(ns, state, std::move(new_be), write);
85 auto recursive_member =
87 if(!recursive_member.has_value())
95 exprt full_exprt = *recursive_member;
96 exprt *for_ssa = &full_exprt;
97 exprt *parent = for_ssa;
98 while(parent->
id() == ID_typecast)
100 while(parent->
id() == ID_member || parent->
id() == ID_index)
102 if(parent->
id() == ID_member)
109#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
124 if(for_ssa->
id() == ID_index || for_ssa->
id() == ID_member)
131 apply(ns, state, state.
rename(std::move(tmp), ns).get(), write);
134 *for_ssa =
apply(ns, state, std::move(tmp), write);
138 else if(for_ssa->
id() == ID_typecast)
142 *for_ssa =
apply(ns, state, state.
rename(*for_ssa, ns).get(), write);
145 *for_ssa =
apply(ns, state, std::move(*for_ssa), write);
160 if(expr.
id() != ID_address_of)
163 *it =
apply(ns, state, std::move(*it), write);
171 !write && expr.
id() == ID_member &&
176#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
178 !write && expr.
id() == ID_index &&
184 else if(expr.
id() == ID_member)
207 return apply(ns, state, state.
rename(std::move(tmp), ns).get(), write);
209 return apply(ns, state, std::move(tmp), write);
213 !write && (expr.
id() == ID_byte_extract_little_endian ||
214 expr.
id() == ID_byte_extract_big_endian))
218#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
219 else if(expr.
id() == ID_index)
238 auto l2_index = state.
rename(index.
index(), ns).get();
253 if(array_from_symbol_table !=
nullptr)
262 if(l2_index.is_constant())
269 index.
index() = l2_index;
274 ns, state, state.
rename(std::move(tmp), ns).get(), write);
277 return apply(ns, state, std::move(tmp), write);
282 exprt expanded_array =
297 bool disjoined_fields_only)
const
300 ssa_expr.
type().
id() == ID_struct ||
301 ssa_expr.
type().
id() == ID_struct_tag ||
302 (!disjoined_fields_only && (ssa_expr.
type().
id() == ID_union ||
303 ssa_expr.
type().
id() == ID_union_tag)))
306 (ssa_expr.
type().
id() == ID_struct_tag ||
307 ssa_expr.
type().
id() == ID_union_tag)
313 fields.reserve(components.size());
317 for(
const auto &comp : components)
327 fields.emplace_back(state.
rename(std::move(field), ns).get());
330 fields.emplace_back(std::move(field));
334 disjoined_fields_only && (ssa_expr.
type().
id() == ID_struct ||
335 ssa_expr.
type().
id() == ID_struct_tag))
342#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
344 ssa_expr.
type().
id() == ID_array &&
356 elements.reserve(array_size);
360 for(std::size_t i = 0; i < array_size; ++i)
370 elements.emplace_back(state.
rename(std::move(element), ns).get());
373 elements.emplace_back(std::move(element));
376 if(disjoined_fields_only)
392 bool allow_pointer_unsoundness)
const
399 ns, state, lhs_fs, rhs, target, allow_pointer_unsoundness);
425 const exprt &ssa_rhs,
427 bool allow_pointer_unsoundness)
const
434 .
assignment(l1_lhs, ssa_rhs, ns,
true,
true, allow_pointer_unsoundness)
456 ssa_rhs.
type().
id() == ID_struct || ssa_rhs.
type().
id() == ID_struct_tag)
459 ssa_rhs.
type().
id() == ID_struct_tag
465 components.empty() ||
468 exprt::operandst::const_iterator fs_it = lhs_fs.
operands().begin();
469 for(
const auto &comp : components)
480 const exprt &member_lhs = *fs_it;
488 fs_ssa->get_object_ssa(),
491 allow_pointer_unsoundness);
495 ns, state, member_lhs, member_rhs, target, allow_pointer_unsoundness);
500 ssa_rhs.
type().
id() == ID_union || ssa_rhs.
type().
id() == ID_union_tag)
503 ssa_rhs.
type().
id() == ID_union_tag
509 components.empty() ||
512 exprt::operandst::const_iterator fs_it = lhs_fs.
operands().begin();
513 for(
const auto &comp : components)
525 const exprt &member_lhs = *fs_it;
533 fs_ssa->get_object_ssa(),
536 allow_pointer_unsoundness);
540 ns, state, member_lhs, member_rhs, target, allow_pointer_unsoundness);
544#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
547 const std::size_t array_size =
554 exprt::operandst::const_iterator fs_it = lhs_fs.
operands().begin();
555 for(std::size_t i = 0; i < array_size; ++i)
566 const exprt &index_lhs = *fs_it;
574 fs_ssa->get_object_ssa(),
577 allow_pointer_unsoundness);
581 ns, state, index_lhs, index_rhs, target, allow_pointer_unsoundness);
592 exprt::operandst::const_iterator fs_it = lhs_fs.
operands().begin();
600 fs_ssa->get_object_ssa(),
603 allow_pointer_unsoundness);
607 ns, state, *fs_it, op, target, allow_pointer_unsoundness);
619 bool disjoined_fields_only)
const
621 if(expr.
type().
id() == ID_struct || expr.
type().
id() == ID_struct_tag)
624#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
626 expr.
type().
id() == ID_array &&
636 !disjoined_fields_only &&
637 (expr.
type().
id() == ID_union || expr.
type().
id() == ID_union_tag))
byte_extract_exprt make_byte_extract(const exprt &_op, const exprt &_offset, const typet &_type)
Construct a byte_extract_exprt with endianness and byte width matching the current configuration.
Expression classes for byte-level operators.
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
bitvector_typet c_index_type()
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Array constructor from list of elements.
typet index_type() const
The type of the index expressions into any instance of this type.
const exprt & size() const
Base class for all expressions.
std::vector< exprt > operandst
bool has_operands() const
Return true if there is at least one operand.
bool is_constant() const
Return whether the expression is a constant.
typet & type()
Return the type of the expression.
exprt simplify_opt(exprt e, const value_sett &value_set, const namespacet &ns) const
const bool should_simplify
exprt apply_byte_extract(const namespacet &ns, goto_symex_statet &state, const byte_extract_exprt &expr, bool write) const
Turn an expression expr into a field-sensitive SSA expression.
const std::size_t max_field_sensitivity_array_size
exprt get_fields(const namespacet &ns, goto_symex_statet &state, const ssa_exprt &ssa_expr, bool disjoined_fields_only) const
Compute an expression representing the individual components of a field-sensitive SSA representation ...
void field_assignments_rec(const namespacet &ns, goto_symex_statet &state, const exprt &lhs_fs, const exprt &ssa_rhs, symex_targett &target, bool allow_pointer_unsoundness) const
Assign to the individual fields lhs_fs of a non-expanded symbol lhs.
exprt apply(const namespacet &ns, goto_symex_statet &state, exprt expr, bool write) const
Turn an expression expr into a field-sensitive SSA expression.
void field_assignments(const namespacet &ns, goto_symex_statet &state, const ssa_exprt &lhs, const exprt &rhs, symex_targett &target, bool allow_pointer_unsoundness) const
Assign to the individual fields of a non-expanded symbol lhs.
const irep_idt & language_mode
bool is_divisible(const ssa_exprt &expr, bool disjoined_fields_only) const
Determine whether expr would translate to an atomic SSA expression (returns false) or a composite obj...
sharing_mapt< irep_idt, exprt > propagation
value_sett value_set
Uses level 1 names, and is used to do dereferencing.
Central data structure: state.
renamedt< ssa_exprt, L2 > assignment(ssa_exprt lhs, const exprt &rhs, const namespacet &ns, bool rhs_is_simplified, bool record_value, bool allow_pointer_unsoundness=false)
renamedt< exprt, level > rename(exprt expr, const namespacet &ns)
Rewrites symbol expressions in exprt, applying a suffix to each symbol reflecting its most recent ver...
symex_targett::sourcet source
const irep_idt & id() const
Extract member of struct or union.
const exprt & compound() const
const exprt & struct_op() const
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
const symbol_table_baset & get_symbol_table() const
Return first symbol table registered with the namespace.
virtual bool simplify(exprt &expr)
Expression providing an SSA-renamed symbol of expressions.
void set_expression(exprt expr)
Replace the underlying, original expression by expr while maintaining SSA indices.
const irep_idt get_level_2() const
const exprt & get_original_expr() const
Struct constructor from list of elements.
Structure type, corresponds to C style structs.
const componentst & components() const
std::vector< componentt > componentst
const irep_idt & get_identifier() const
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
typet type
Type of symbol.
The interface of the target container for symbolic execution to record its symbolic steps into.
virtual void assignment(const exprt &guard, const ssa_exprt &ssa_lhs, const exprt &ssa_full_lhs, const exprt &original_full_lhs, const exprt &ssa_rhs, const sourcet &source, assignment_typet assignment_type)=0
Write to a local variable.
std::optional< std::pair< struct_union_typet::componentt, mp_integer > > find_widest_union_component(const namespacet &ns) const
Determine the member of maximum bit width in a union type.
State type in value_set_domaint, used in value-set analysis and goto-symex.
void erase_symbol(const symbol_exprt &symbol_expr, const namespacet &ns)
#define Forall_operands(it, expr)
auto type_try_dynamic_cast(TType &base) -> typename detail::expr_try_dynamic_cast_return_typet< T, TType >::type
Try to cast a reference to a generic typet to a specific derived class.
auto expr_try_dynamic_cast(TExpr &base) -> typename detail::expr_try_dynamic_cast_return_typet< T, TExpr >::type
Try to cast a reference to a generic exprt to a specific derived class.
std::optional< exprt > get_subexpression_at_offset(const exprt &expr, const mp_integer &offset_bytes, const typet &target_type_raw, const namespacet &ns)
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
#define UNREACHABLE
This should be used to mark dead code.
#define PRECONDITION(CONDITION)
bool is_ssa_expr(const exprt &expr)
const ssa_exprt & to_ssa_expr(const exprt &expr)
Cast a generic exprt to an ssa_exprt.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
const struct_or_union_tag_typet & to_struct_or_union_tag_type(const typet &type)
Cast a typet to a struct_or_union_tag_typet.
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Generate Equation using Symbolic Execution.