@@ -595,10 +595,35 @@ simplify_exprt::simplify_minus(const minus_exprt &expr)
595
595
is_number (minus_expr.type ()) && operands[0 ].type ().id () == ID_pointer &&
596
596
operands[1 ].type ().id () == ID_pointer)
597
597
{
598
- // pointer arithmetic: rewrite "p-p" to "0"
598
+ exprt ptr_op0 = simplify_object (operands[0 ]).expr ;
599
+ exprt ptr_op1 = simplify_object (operands[1 ]).expr ;
599
600
600
- if (operands[0 ]==operands[1 ])
601
- return from_integer (0 , minus_expr.type ());
601
+ auto address_of = expr_try_dynamic_cast<address_of_exprt>(ptr_op0);
602
+ if (ptr_op0 == ptr_op1 && address_of)
603
+ {
604
+ exprt offset_op0 = simplify_pointer_offset (
605
+ pointer_offset_exprt{operands[0 ], minus_expr.type ()});
606
+ exprt offset_op1 = simplify_pointer_offset (
607
+ pointer_offset_exprt{operands[1 ], minus_expr.type ()});
608
+
609
+ const auto object_size =
610
+ pointer_offset_size (address_of->object ().type (), ns);
611
+ auto element_size =
612
+ size_of_expr (to_pointer_type (operands[0 ].type ()).base_type (), ns);
613
+
614
+ if (
615
+ offset_op0.is_constant () && offset_op1.is_constant () &&
616
+ object_size.has_value () && element_size.has_value () &&
617
+ numeric_cast_v<mp_integer>(to_constant_expr (offset_op0)) <=
618
+ *object_size &&
619
+ numeric_cast_v<mp_integer>(to_constant_expr (offset_op1)) <=
620
+ *object_size)
621
+ {
622
+ return changed (simplify_rec (div_exprt{
623
+ minus_exprt{offset_op0, offset_op1},
624
+ typecast_exprt{*element_size, minus_expr.type ()}}));
625
+ }
626
+ }
602
627
}
603
628
604
629
return unchanged (expr);
0 commit comments