1414
1515#include < solvers/smt2_incremental/convert_expr_to_smt.h>
1616#include < solvers/smt2_incremental/object_tracking.h>
17- #include < solvers/smt2_incremental/pointer_size_mapping.h>
1817#include < solvers/smt2_incremental/smt_bit_vector_theory.h>
1918#include < solvers/smt2_incremental/smt_core_theory.h>
2019#include < solvers/smt2_incremental/smt_terms.h>
2120#include < solvers/smt2_incremental/smt_to_smt2_string.h>
21+ #include < solvers/smt2_incremental/type_size_mapping.h>
2222#include < testing-utils/invariant.h>
2323#include < testing-utils/use_catch.h>
2424
@@ -58,7 +58,7 @@ struct expr_to_smt_conversion_test_environmentt
5858
5959 smt_object_mapt object_map;
6060 smt_object_sizet object_size_function;
61- pointer_size_mapt pointer_sizes;
61+ type_size_mapt pointer_sizes;
6262
6363private:
6464 // This is private to ensure the above make() function is used to make
@@ -334,13 +334,27 @@ TEST_CASE(
334334 auto test = expr_to_smt_conversion_test_environmentt::make (test_archt::i386);
335335 const smt_termt smt_term_one = smt_bit_vector_constant_termt{1 , 8 };
336336 const smt_termt smt_term_two = smt_bit_vector_constant_termt{2 , 8 };
337+ const auto two_bvint_32bit = from_integer ({2 }, signedbv_typet{32 });
337338
338339 // Just regular (bit-vector) integers, to be used for the comparison
339340 const auto one_bvint = from_integer ({1 }, signedbv_typet{8 });
340341 const auto two_bvint = from_integer ({2 }, signedbv_typet{8 });
341342 const auto one_bvint_unsigned = from_integer ({1 }, unsignedbv_typet{8 });
342343 const auto two_bvint_unsigned = from_integer ({2 }, unsignedbv_typet{8 });
343344
345+ // Pointer variables, used for comparisons
346+ const std::size_t pointer_width = 32 ;
347+ const auto pointer_type = pointer_typet (signedbv_typet{32 }, pointer_width);
348+ const symbol_exprt pointer_a (" a" , pointer_type);
349+ const symbol_exprt pointer_b (" b" , pointer_type);
350+ // SMT terms needed for pointer comparisons
351+ const smt_termt smt_term_a =
352+ smt_identifier_termt{" a" , smt_bit_vector_sortt{pointer_width}};
353+ const smt_termt smt_term_b =
354+ smt_identifier_termt{" b" , smt_bit_vector_sortt{pointer_width}};
355+ const smt_termt smt_term_four_32bit = smt_bit_vector_constant_termt{4 , 32 };
356+ const smt_termt smt_term_two_32bit = smt_bit_vector_constant_termt{2 , 32 };
357+
344358 SECTION (" Addition of two constant size bit-vectors" )
345359 {
346360 const auto constructed_term =
@@ -350,6 +364,30 @@ TEST_CASE(
350364 CHECK (constructed_term == expected_term);
351365 }
352366
367+ SECTION (" Addition of a pointer and a constant" )
368+ {
369+ // (int32_t *)a + 2
370+ const auto pointer_arith_expr = plus_exprt{pointer_a, two_bvint_32bit};
371+ const symbol_tablet symbol_table;
372+ const namespacet ns{symbol_table};
373+ track_expression_objects (pointer_arith_expr, ns, test.object_map );
374+ associate_pointer_sizes (
375+ pointer_arith_expr,
376+ ns,
377+ test.pointer_sizes ,
378+ test.object_map ,
379+ test.object_size_function .make_application );
380+
381+ INFO (" Input expr: " + pointer_arith_expr.pretty (2 , 0 ));
382+ const auto constructed_term = test.convert (pointer_arith_expr);
383+ const auto expected_term = smt_bit_vector_theoryt::add (
384+ smt_term_a,
385+ smt_bit_vector_theoryt::multiply (
386+ smt_term_two_32bit, smt_term_four_32bit));
387+
388+ CHECK (constructed_term == expected_term);
389+ }
390+
353391 SECTION (
354392 " Addition of four constant size bit-vectors - testing multi-ary handling "
355393 " of plus_exprt" )
@@ -396,6 +434,71 @@ TEST_CASE(
396434 REQUIRE_THROWS (test.convert (plus_exprt{one_operand, signedbv_typet{8 }}));
397435 }
398436
437+ SECTION (" Subtraction of constant value from pointer" )
438+ {
439+ // (int32_t *)a - 2
440+ const auto minus_two_bvint =
441+ from_integer (-2 , signedbv_typet{pointer_width});
442+ // NOTE: not a mistake! An expression in source code of the form
443+ // (int *)a - 2 is coming to us as (int *)a + (-2), so a design decision
444+ // was made to handle only that form.
445+ const auto pointer_arith_expr = plus_exprt{pointer_a, minus_two_bvint};
446+ const symbol_tablet symbol_table;
447+ const namespacet ns{symbol_table};
448+ track_expression_objects (pointer_arith_expr, ns, test.object_map );
449+ associate_pointer_sizes (
450+ pointer_arith_expr,
451+ ns,
452+ test.pointer_sizes ,
453+ test.object_map ,
454+ test.object_size_function .make_application );
455+
456+ INFO (" Input expr: " + pointer_arith_expr.pretty (2 , 0 ));
457+ const auto constructed_term = test.convert (pointer_arith_expr);
458+ const auto expected_term = smt_bit_vector_theoryt::add (
459+ smt_term_a,
460+ smt_bit_vector_theoryt::multiply (
461+ smt_bit_vector_theoryt::negate (smt_term_two_32bit),
462+ smt_term_four_32bit));
463+ }
464+
465+ SECTION (
466+ " Ensure that conversion of a minus node with only one operand"
467+ " being a pointer fails" )
468+ {
469+ // (*int32_t)a - 2
470+ const cbmc_invariants_should_throwt invariants_throw;
471+ // We don't support that - look at the test above.
472+ const auto pointer_arith_expr = minus_exprt{pointer_a, two_bvint};
473+ REQUIRE_THROWS_MATCHES (
474+ test.convert (pointer_arith_expr),
475+ invariant_failedt,
476+ invariant_failure_containing (
477+ " convert_expr_to_smt::minus_exprt doesn't handle expressions where"
478+ " only one operand is a pointer - this is because these expressions" ));
479+ }
480+
481+ SECTION (" Subtraction of two pointer arguments" )
482+ {
483+ // (int32_t *)a - (int32_t *)b
484+ const auto pointer_subtraction = minus_exprt{pointer_b, pointer_a};
485+ const symbol_tablet symbol_table;
486+ const namespacet ns{symbol_table};
487+ track_expression_objects (pointer_subtraction, ns, test.object_map );
488+ associate_pointer_sizes (
489+ pointer_subtraction,
490+ ns,
491+ test.pointer_sizes ,
492+ test.object_map ,
493+ test.object_size_function .make_application );
494+ INFO (" Input expr: " + pointer_subtraction.pretty (2 , 0 ));
495+ const auto constructed_term = test.convert (pointer_subtraction);
496+ const auto expected_term = smt_bit_vector_theoryt::signed_divide (
497+ smt_bit_vector_theoryt::subtract (smt_term_b, smt_term_a),
498+ smt_term_four_32bit);
499+ CHECK (constructed_term == expected_term);
500+ }
501+
399502 SECTION (" Subtraction of two constant size bit-vectors" )
400503 {
401504 const auto constructed_term =
0 commit comments