@@ -99,9 +99,11 @@ static json_objectt value_set_dereference_stats_to_json(
9999 return json_result;
100100}
101101
102- optionalt<exprt> value_set_dereferencet::try_add_offset_to_indices (
103- const exprt &expr,
104- const exprt &offset_elements)
102+ // / If `expr` is of the form (c1 ? e1[o1] : c2 ? e2[o2] : c3 ? ...)
103+ // / then return `c1 ? e1[o1 + offset] : e2[o2 + offset] : c3 ? ...`
104+ // / otherwise return an empty optionalt.
105+ static optionalt<exprt>
106+ try_add_offset_to_indices (const exprt &expr, const exprt &offset_elements)
105107{
106108 if (const auto *index_expr = expr_try_dynamic_cast<index_exprt>(expr))
107109 {
@@ -123,6 +125,13 @@ optionalt<exprt> value_set_dereferencet::try_add_offset_to_indices(
123125 return {};
124126 return if_exprt{if_expr->cond (), *true_case, *false_case};
125127 }
128+ else if (can_cast_expr<typecast_exprt>(expr))
129+ {
130+ // the case of a type cast is _not_ handled here, because that would require
131+ // doing arithmetic on the offset, and may result in an offset into some
132+ // sub-element
133+ return {};
134+ }
126135 else
127136 {
128137 return {};
@@ -572,12 +581,12 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
572581 else if (
573582 root_object_type.id () == ID_array &&
574583 dereference_type_compare (
575- to_array_type (root_object_type).element_type (), dereference_type, ns))
584+ to_array_type (root_object_type).element_type (), dereference_type, ns) &&
585+ pointer_offset_bits (to_array_type (root_object_type).element_type (), ns) ==
586+ pointer_offset_bits (dereference_type, ns))
576587 {
577588 // We have an array with a subtype that matches
578589 // the dereferencing type.
579- // We will require well-alignedness!
580-
581590 exprt offset;
582591
583592 // this should work as the object is essentially the root object
@@ -586,8 +595,6 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
586595 else
587596 offset=pointer_offset (pointer_expr);
588597
589- exprt adjusted_offset;
590-
591598 // are we doing a byte?
592599 auto element_size =
593600 pointer_offset_size (to_array_type (root_object_type).element_type (), ns);
@@ -597,25 +604,13 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
597604 throw " unknown or invalid type size of:\n " +
598605 to_array_type (root_object_type).element_type ().pretty ();
599606 }
600- else if (*element_size == 1 )
601- {
602- // no need to adjust offset
603- adjusted_offset = offset;
604- }
605- else
606- {
607- exprt element_size_expr = from_integer (*element_size, offset.type ());
608607
609- adjusted_offset=binary_exprt (
610- offset, ID_div, element_size_expr, offset.type ());
608+ exprt element_size_expr = from_integer (*element_size, offset.type ());
611609
612- // TODO: need to assert well-alignedness
613- }
610+ exprt adjusted_offset =
611+ simplify_expr (div_exprt{offset, element_size_expr}, ns);
614612
615- const index_exprt &index_expr = index_exprt (
616- root_object,
617- adjusted_offset,
618- to_array_type (root_object_type).element_type ());
613+ index_exprt index_expr{root_object, adjusted_offset};
619614 result.value =
620615 typecast_exprt::conditional_cast (index_expr, dereference_type);
621616 result.pointer = typecast_exprt::conditional_cast (
0 commit comments