Skip to content

Commit 34b2985

Browse files
committed
Add unit tests for pointer arithmetic conversion.
1 parent ee56b4f commit 34b2985

File tree

1 file changed

+105
-2
lines changed

1 file changed

+105
-2
lines changed

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

+105-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
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

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,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

Comments
 (0)