Skip to content

Commit 6c7c885

Browse files
committed
Add unit tests for pointer arithmetic conversion.
1 parent dacc33c commit 6c7c885

File tree

1 file changed

+101
-1
lines changed

1 file changed

+101
-1
lines changed

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

6363
private:
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::unsigned_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

Comments
 (0)