@@ -587,7 +587,8 @@ static optionalt<smt_termt> try_relational_conversion(
587
587
588
588
static smt_termt convert_expr_to_smt (
589
589
const plus_exprt &plus,
590
- const sub_expression_mapt &converted)
590
+ const sub_expression_mapt &converted,
591
+ const type_size_mapt &pointer_sizes)
591
592
{
592
593
if (std::all_of (
593
594
plus.operands ().cbegin (), plus.operands ().cend (), [](exprt operand) {
@@ -597,6 +598,43 @@ static smt_termt convert_expr_to_smt(
597
598
return convert_multiary_operator_to_terms (
598
599
plus, converted, smt_bit_vector_theoryt::add);
599
600
}
601
+ else if (can_cast_type<pointer_typet>(plus.type ()))
602
+ {
603
+ INVARIANT (
604
+ plus.operands ().size () == 2 ,
605
+ " We are only handling a binary version of plus when it has a pointer "
606
+ " operand" );
607
+
608
+ exprt pointer;
609
+ exprt scalar;
610
+ for (auto &operand : plus.operands ())
611
+ {
612
+ if (can_cast_type<pointer_typet>(operand.type ()))
613
+ {
614
+ pointer = operand;
615
+ }
616
+ else
617
+ {
618
+ scalar = operand;
619
+ }
620
+ }
621
+
622
+ // We need to ensure that we follow this code path only if the expression
623
+ // our assumptions about the structure of the addition expression hold.
624
+ INVARIANT (
625
+ !can_cast_type<pointer_typet>(scalar.type ()),
626
+ " An addition expression with both operands being pointers when they are "
627
+ " not dereferenced is malformed" );
628
+
629
+ const pointer_typet pointer_type =
630
+ *type_try_dynamic_cast<pointer_typet>(pointer.type ());
631
+ const auto base_type = pointer_type.base_type ();
632
+ const auto pointer_size = pointer_sizes.at (base_type);
633
+
634
+ return smt_bit_vector_theoryt::add (
635
+ converted.at (pointer),
636
+ smt_bit_vector_theoryt::multiply (converted.at (scalar), pointer_size));
637
+ }
600
638
else
601
639
{
602
640
UNIMPLEMENTED_FEATURE (
@@ -606,17 +644,51 @@ static smt_termt convert_expr_to_smt(
606
644
607
645
static smt_termt convert_expr_to_smt (
608
646
const minus_exprt &minus,
609
- const sub_expression_mapt &converted)
647
+ const sub_expression_mapt &converted,
648
+ const type_size_mapt &pointer_sizes)
610
649
{
611
650
const bool both_operands_bitvector =
612
651
can_cast_type<integer_bitvector_typet>(minus.lhs ().type ()) &&
613
652
can_cast_type<integer_bitvector_typet>(minus.rhs ().type ());
614
653
654
+ const bool lhs_is_pointer = can_cast_type<pointer_typet>(minus.lhs ().type ());
655
+ const bool rhs_is_pointer = can_cast_type<pointer_typet>(minus.rhs ().type ());
656
+
657
+ const bool both_operands_pointers = lhs_is_pointer && rhs_is_pointer;
658
+
659
+ // We don't really handle this - we just compute this to fall
660
+ // into an if-else branch that gives proper error handling information.
661
+ const bool one_operand_pointer = lhs_is_pointer || rhs_is_pointer;
662
+
615
663
if (both_operands_bitvector)
616
664
{
617
665
return smt_bit_vector_theoryt::subtract (
618
666
converted.at (minus.lhs ()), converted.at (minus.rhs ()));
619
667
}
668
+ else if (both_operands_pointers)
669
+ {
670
+ const auto lhs_base_type = to_pointer_type (minus.lhs ().type ()).base_type ();
671
+ const auto rhs_base_type = to_pointer_type (minus.rhs ().type ()).base_type ();
672
+ INVARIANT (
673
+ lhs_base_type == rhs_base_type,
674
+ " only pointers of the same object type can be subtracted." );
675
+ return smt_bit_vector_theoryt::signed_divide (
676
+ smt_bit_vector_theoryt::subtract (
677
+ converted.at (minus.lhs ()), converted.at (minus.rhs ())),
678
+ pointer_sizes.at (lhs_base_type));
679
+ }
680
+ else if (one_operand_pointer)
681
+ {
682
+ UNIMPLEMENTED_FEATURE (
683
+ " convert_expr_to_smt::minus_exprt doesn't handle expressions where"
684
+ " only one operand is a pointer - this is because these expressions"
685
+ " are normally handled by convert_expr_to_smt::plus_exprt due to"
686
+ " transformations of the expressions by previous passes bringing"
687
+ " them into a form more suitably handled by that version of the function."
688
+ " If you are here, this is a mistake or something went wrong before."
689
+ " The expression that caused the problem is: " +
690
+ minus.pretty ());
691
+ }
620
692
else
621
693
{
622
694
UNIMPLEMENTED_FEATURE (
@@ -1299,6 +1371,7 @@ static smt_termt dispatch_expr_to_smt_conversion(
1299
1371
const exprt &expr,
1300
1372
const sub_expression_mapt &converted,
1301
1373
const smt_object_mapt &object_map,
1374
+ const type_size_mapt &pointer_sizes,
1302
1375
const smt_object_sizet::make_applicationt &call_object_size)
1303
1376
{
1304
1377
if (const auto symbol = expr_try_dynamic_cast<symbol_exprt>(expr))
@@ -1415,11 +1488,11 @@ static smt_termt dispatch_expr_to_smt_conversion(
1415
1488
}
1416
1489
if (const auto plus = expr_try_dynamic_cast<plus_exprt>(expr))
1417
1490
{
1418
- return convert_expr_to_smt (*plus, converted);
1491
+ return convert_expr_to_smt (*plus, converted, pointer_sizes );
1419
1492
}
1420
1493
if (const auto minus = expr_try_dynamic_cast<minus_exprt>(expr))
1421
1494
{
1422
- return convert_expr_to_smt (*minus, converted);
1495
+ return convert_expr_to_smt (*minus, converted, pointer_sizes );
1423
1496
}
1424
1497
if (const auto divide = expr_try_dynamic_cast<div_exprt>(expr))
1425
1498
{
@@ -1658,6 +1731,7 @@ at_scope_exitt<functiont> at_scope_exit(functiont exit_function)
1658
1731
smt_termt convert_expr_to_smt (
1659
1732
const exprt &expr,
1660
1733
const smt_object_mapt &object_map,
1734
+ const type_size_mapt &pointer_sizes,
1661
1735
const smt_object_sizet::make_applicationt &object_size)
1662
1736
{
1663
1737
#ifndef CPROVER_INVARIANT_DO_NOT_CHECK
@@ -1676,7 +1750,7 @@ smt_termt convert_expr_to_smt(
1676
1750
if (find_result != sub_expression_map.cend ())
1677
1751
return ;
1678
1752
smt_termt term = dispatch_expr_to_smt_conversion (
1679
- expr, sub_expression_map, object_map, object_size);
1753
+ expr, sub_expression_map, object_map, pointer_sizes, object_size);
1680
1754
sub_expression_map.emplace_hint (find_result, expr, std::move (term));
1681
1755
});
1682
1756
return std::move (sub_expression_map.at (expr));
0 commit comments