@@ -577,23 +577,27 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
577577 result.value = typecast_exprt::conditional_cast (object, dereference_type);
578578 result.pointer =
579579 typecast_exprt::conditional_cast (object_pointer, pointer_type);
580+
581+ return result;
580582 }
581- else if (
583+
584+ // this is relative to the root object
585+ exprt offset;
586+ if (o.offset ().is_constant ())
587+ offset = o.offset ();
588+ else
589+ offset = simplify_expr (pointer_offset (pointer_expr), ns);
590+
591+ if (
582592 root_object_type.id () == ID_array &&
583593 dereference_type_compare (
584594 to_array_type (root_object_type).element_type (), dereference_type, ns) &&
585595 pointer_offset_bits (to_array_type (root_object_type).element_type (), ns) ==
586- pointer_offset_bits (dereference_type, ns))
596+ pointer_offset_bits (dereference_type, ns) &&
597+ offset.is_constant ())
587598 {
588599 // We have an array with a subtype that matches
589600 // the dereferencing type.
590- exprt offset;
591-
592- // this should work as the object is essentially the root object
593- if (o.offset ().is_constant ())
594- offset=o.offset ();
595- else
596- offset=pointer_offset (pointer_expr);
597601
598602 // are we doing a byte?
599603 auto element_size =
@@ -605,18 +609,25 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
605609 to_array_type (root_object_type).element_type ().pretty ();
606610 }
607611
608- exprt element_size_expr = from_integer (*element_size, offset.type ());
612+ const auto offset_int =
613+ numeric_cast_v<mp_integer>(to_constant_expr (offset));
609614
610- exprt adjusted_offset =
611- simplify_expr (div_exprt{offset, element_size_expr}, ns);
615+ if (offset_int % *element_size == 0 )
616+ {
617+ index_exprt index_expr{
618+ root_object,
619+ from_integer (
620+ offset_int / *element_size,
621+ to_array_type (root_object_type).index_type ())};
622+ result.value =
623+ typecast_exprt::conditional_cast (index_expr, dereference_type);
624+ result.pointer = typecast_exprt::conditional_cast (
625+ address_of_exprt{index_expr}, pointer_type);
612626
613- index_exprt index_expr{root_object, adjusted_offset};
614- result.value =
615- typecast_exprt::conditional_cast (index_expr, dereference_type);
616- result.pointer = typecast_exprt::conditional_cast (
617- address_of_exprt{index_expr}, pointer_type);
627+ return result;
628+ }
618629 }
619- else
630+
620631 {
621632 // try to build a member/index expression - do not use byte_extract
622633 auto subexpr = get_subexpression_at_offset (
@@ -641,13 +652,6 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
641652 result.pointer = typecast_exprt::conditional_cast (
642653 address_of_exprt{skip_typecast (o.root_object ())}, pointer_type);
643654
644- // this is relative to the root object
645- exprt offset;
646- if (o.offset ().id ()==ID_unknown)
647- offset=pointer_offset (pointer_expr);
648- else
649- offset=o.offset ();
650-
651655 if (memory_model (result.value , dereference_type, offset, ns))
652656 {
653657 // ok, done
0 commit comments