@@ -99,9 +99,11 @@ static json_objectt value_set_dereference_stats_to_json(
99
99
return json_result;
100
100
}
101
101
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)
105
107
{
106
108
if (const auto *index_expr = expr_try_dynamic_cast<index_exprt>(expr))
107
109
{
@@ -123,6 +125,13 @@ optionalt<exprt> value_set_dereferencet::try_add_offset_to_indices(
123
125
return {};
124
126
return if_exprt{if_expr->cond (), *true_case, *false_case};
125
127
}
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
+ }
126
135
else
127
136
{
128
137
return {};
@@ -572,12 +581,12 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
572
581
else if (
573
582
root_object_type.id () == ID_array &&
574
583
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))
576
587
{
577
588
// We have an array with a subtype that matches
578
589
// the dereferencing type.
579
- // We will require well-alignedness!
580
-
581
590
exprt offset;
582
591
583
592
// 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(
586
595
else
587
596
offset=pointer_offset (pointer_expr);
588
597
589
- exprt adjusted_offset;
590
-
591
598
// are we doing a byte?
592
599
auto element_size =
593
600
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(
597
604
throw " unknown or invalid type size of:\n " +
598
605
to_array_type (root_object_type).element_type ().pretty ();
599
606
}
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 ());
608
607
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 ());
611
609
612
- // TODO: need to assert well-alignedness
613
- }
610
+ exprt adjusted_offset =
611
+ simplify_expr (div_exprt{offset, element_size_expr}, ns);
614
612
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};
619
614
result.value =
620
615
typecast_exprt::conditional_cast (index_expr, dereference_type);
621
616
result.pointer = typecast_exprt::conditional_cast (
0 commit comments