@@ -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,29 @@ 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
+ 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
+
353
390
SECTION (
354
391
" Addition of four constant size bit-vectors - testing multi-ary handling "
355
392
" of plus_exprt" )
@@ -396,6 +433,69 @@ TEST_CASE(
396
433
REQUIRE_THROWS (test.convert (plus_exprt{one_operand, signedbv_typet{8 }}));
397
434
}
398
435
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
+
399
499
SECTION (" Subtraction of two constant size bit-vectors" )
400
500
{
401
501
const auto constructed_term =
0 commit comments