@@ -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,29 @@ 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+ const auto constructed_term = test.convert (pointer_arith_expr);
382+ const auto expected_term = smt_bit_vector_theoryt::add (
383+ smt_term_a,
384+ smt_bit_vector_theoryt::multiply (
385+ smt_term_two_32bit, smt_term_four_32bit));
386+
387+ CHECK (constructed_term == expected_term);
388+ }
389+
353390 SECTION (
354391 " Addition of four constant size bit-vectors - testing multi-ary handling "
355392 " of plus_exprt" )
@@ -396,6 +433,69 @@ TEST_CASE(
396433 REQUIRE_THROWS (test.convert (plus_exprt{one_operand, signedbv_typet{8 }}));
397434 }
398435
436+ SECTION (" Subtraction of constant value from pointer" )
437+ {
438+ // (int32_t *)a - 2
439+ const auto minus_two_bvint =
440+ from_integer (-2 , signedbv_typet{pointer_width});
441+ // NOTE: not a mistake! An expression in source code of the form
442+ // (int *)a - 2 is coming to us as (int *)a + (-2), so a design decision
443+ // was made to handle only that form.
444+ const auto pointer_arith_expr = plus_exprt{pointer_a, minus_two_bvint};
445+ const symbol_tablet symbol_table;
446+ const namespacet ns{symbol_table};
447+ track_expression_objects (pointer_arith_expr, ns, test.object_map );
448+ associate_pointer_sizes (
449+ pointer_arith_expr,
450+ ns,
451+ test.pointer_sizes ,
452+ test.object_map ,
453+ test.object_size_function .make_application );
454+
455+ const auto constructed_term = test.convert (pointer_arith_expr);
456+ const auto expected_term = smt_bit_vector_theoryt::add (
457+ smt_term_a,
458+ smt_bit_vector_theoryt::multiply (
459+ smt_bit_vector_theoryt::negate (smt_term_two_32bit),
460+ smt_term_four_32bit));
461+ }
462+
463+ SECTION (
464+ " Ensure that conversion of a minus node with only one operand"
465+ " being a pointer fails" )
466+ {
467+ // (*int32_t)a - 2
468+ const cbmc_invariants_should_throwt invariants_throw;
469+ // We don't support that - look at the test above.
470+ const auto pointer_arith_expr = minus_exprt{pointer_a, two_bvint};
471+ REQUIRE_THROWS_MATCHES (
472+ test.convert (pointer_arith_expr),
473+ invariant_failedt,
474+ invariant_failure_containing (
475+ " convert_expr_to_smt::minus_exprt doesn't handle expressions where"
476+ " only one operand is a pointer - this is because these expressions" ));
477+ }
478+
479+ SECTION (" Subtraction of two pointer arguments" )
480+ {
481+ // (int32_t *)a - (int32_t *)b
482+ const auto pointer_subtraction = minus_exprt{pointer_b, pointer_a};
483+ const symbol_tablet symbol_table;
484+ const namespacet ns{symbol_table};
485+ track_expression_objects (pointer_subtraction, ns, test.object_map );
486+ associate_pointer_sizes (
487+ pointer_subtraction,
488+ ns,
489+ test.pointer_sizes ,
490+ test.object_map ,
491+ test.object_size_function .make_application );
492+ const auto constructed_term = test.convert (pointer_subtraction);
493+ const auto expected_term = smt_bit_vector_theoryt::signed_divide (
494+ smt_bit_vector_theoryt::subtract (smt_term_b, smt_term_a),
495+ smt_term_four_32bit);
496+ CHECK (constructed_term == expected_term);
497+ }
498+
399499 SECTION (" Subtraction of two constant size bit-vectors" )
400500 {
401501 const auto constructed_term =
0 commit comments