14
14
15
15
#include < solvers/smt2_incremental/convert_expr_to_smt.h>
16
16
#include < solvers/smt2_incremental/object_tracking.h>
17
- #include < solvers/smt2_incremental/pointer_size_mapping.h>
18
17
#include < solvers/smt2_incremental/smt_bit_vector_theory.h>
19
18
#include < solvers/smt2_incremental/smt_core_theory.h>
20
19
#include < solvers/smt2_incremental/smt_terms.h>
21
20
#include < solvers/smt2_incremental/smt_to_smt2_string.h>
21
+ #include < solvers/smt2_incremental/type_size_mapping.h>
22
22
#include < testing-utils/invariant.h>
23
23
#include < testing-utils/use_catch.h>
24
24
@@ -58,7 +58,7 @@ struct expr_to_smt_conversion_test_environmentt
58
58
59
59
smt_object_mapt object_map;
60
60
smt_object_sizet object_size_function;
61
- pointer_size_mapt pointer_sizes;
61
+ type_size_mapt pointer_sizes;
62
62
63
63
private:
64
64
// This is private to ensure the above make() function is used to make
@@ -334,13 +334,27 @@ TEST_CASE(
334
334
auto test = expr_to_smt_conversion_test_environmentt::make (test_archt::i386);
335
335
const smt_termt smt_term_one = smt_bit_vector_constant_termt{1 , 8 };
336
336
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 });
337
338
338
339
// Just regular (bit-vector) integers, to be used for the comparison
339
340
const auto one_bvint = from_integer ({1 }, signedbv_typet{8 });
340
341
const auto two_bvint = from_integer ({2 }, signedbv_typet{8 });
341
342
const auto one_bvint_unsigned = from_integer ({1 }, unsignedbv_typet{8 });
342
343
const auto two_bvint_unsigned = from_integer ({2 }, unsignedbv_typet{8 });
343
344
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
+
344
358
SECTION (" Addition of two constant size bit-vectors" )
345
359
{
346
360
const auto constructed_term =
@@ -350,6 +364,30 @@ TEST_CASE(
350
364
CHECK (constructed_term == expected_term);
351
365
}
352
366
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
+
353
391
SECTION (
354
392
" Addition of four constant size bit-vectors - testing multi-ary handling "
355
393
" of plus_exprt" )
@@ -396,6 +434,71 @@ TEST_CASE(
396
434
REQUIRE_THROWS (test.convert (plus_exprt{one_operand, signedbv_typet{8 }}));
397
435
}
398
436
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
+
399
502
SECTION (" Subtraction of two constant size bit-vectors" )
400
503
{
401
504
const auto constructed_term =
0 commit comments