Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion src/goto-symex/field_sensitivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,21 @@ exprt field_sensitivityt::apply(
return expr;
}

#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
/// True if the array index type permits field-sensitive element enumeration
/// via from_integer(i, index_type). Arrays keyed by a non-scalar type (e.g.
/// Strata's `Map Ref _` heap, indexed by a struct reference) cannot be
/// enumerated this way and must be handled monolithically. Boolean index types
/// are deliberately excluded: from_integer(i, bool) collapses every i > 1 to
/// `true`, so enumerating i = 0..size-1 would produce duplicate indices.
static bool is_enumerable_array_index_type(const typet &index_type)
{
const irep_idt &id = index_type.id();
return id == ID_unsignedbv || id == ID_signedbv || id == ID_bv ||
id == ID_integer || id == ID_c_enum || id == ID_c_enum_tag;
}
#endif // ENABLE_ARRAY_FIELD_SENSITIVITY

exprt field_sensitivityt::get_fields(
const namespacet &ns,
goto_symex_statet &state,
Expand Down Expand Up @@ -350,6 +365,13 @@ exprt field_sensitivityt::get_fields(
return ssa_expr;

const array_typet &type = to_array_type(ssa_expr.type());
// Element enumeration below builds integer indices via from_integer(i,
// index_type), so it only applies to arrays with an enumerable index type;
// arrays keyed by a non-scalar type (e.g. a map keyed by a struct
// reference, as in Strata's heap model `Map Ref _`) are treated
// monolithically.
if(!is_enumerable_array_index_type(type.index_type()))
return ssa_expr;
const std::size_t array_size = numeric_cast_v<std::size_t>(mp_array_size);

array_exprt::operandst elements;
Expand Down Expand Up @@ -628,7 +650,12 @@ bool field_sensitivityt::is_divisible(
numeric_cast_v<mp_integer>(to_constant_expr(
to_array_type(expr.type()).size())) <= max_field_sensitivity_array_size)
{
return true;
// Only field-decompose arrays whose index type is enumerable (element
// enumeration builds from_integer(i, index_type)). Arrays keyed by a
// non-scalar type (e.g. Strata's `Map Ref _` heap, indexed by a struct
// reference) must be handled monolithically.
if(is_enumerable_array_index_type(to_array_type(expr.type()).index_type()))
return true;
}
#endif

Expand Down
14 changes: 12 additions & 2 deletions src/pointer-analysis/value_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1592,9 +1592,19 @@ void value_sett::assign(
}
else
{
// For array assignments the indices were abstracted to
// exprt(ID_unknown, c_index_type()) above, so the array's index type
// does not affect materialisation here. We therefore require only the
// element types to match and intentionally ignore both the array size
// and the index type (the latter being what enables struct-keyed
// "map" arrays to be assigned).
DATA_INVARIANT(
rhs.type() == lhs.type(),
"value_sett::assign types should match, got: "
rhs.type() == lhs.type() ||
(rhs.type().id() == ID_array && lhs.type().id() == ID_array &&
to_array_type(rhs.type()).element_type() ==
to_array_type(lhs.type()).element_type()),
"value_sett::assign types should match (for arrays, modulo array size "
"and index type, as array indices are abstracted here), got: "
"rhs.type():\n" +
rhs.type().pretty() + "\n" + "type:\n" + lhs.type().pretty());
Comment thread
tautschnig marked this conversation as resolved.

Expand Down
Loading