File tree Expand file tree Collapse file tree 5 files changed +86
-3
lines changed
src/solvers/smt2_incremental
unit/solvers/smt2_incremental Expand file tree Collapse file tree 5 files changed +86
-3
lines changed Original file line number Diff line number Diff line change @@ -401,9 +401,22 @@ static smt_termt convert_expr_to_smt(const ieee_float_op_exprt &float_operation)
401
401
402
402
static smt_termt convert_expr_to_smt (const mod_exprt &truncation_modulo)
403
403
{
404
- UNIMPLEMENTED_FEATURE (
405
- " Generation of SMT formula for truncation modulo expression: " +
406
- truncation_modulo.pretty ());
404
+ const bool both_operands_bitvector =
405
+ can_cast_type<integer_bitvector_typet>(truncation_modulo.lhs ().type ()) &&
406
+ can_cast_type<integer_bitvector_typet>(truncation_modulo.rhs ().type ());
407
+
408
+ if (both_operands_bitvector)
409
+ {
410
+ return smt_bit_vector_theoryt::unsigned_remainder (
411
+ convert_expr_to_smt (truncation_modulo.lhs ()),
412
+ convert_expr_to_smt (truncation_modulo.rhs ()));
413
+ }
414
+ else
415
+ {
416
+ UNIMPLEMENTED_FEATURE (
417
+ " Generation of SMT formula for remainder (modulus) expression: " +
418
+ truncation_modulo.pretty ());
419
+ }
407
420
}
408
421
409
422
static smt_termt
Original file line number Diff line number Diff line change @@ -319,3 +319,26 @@ void smt_bit_vector_theoryt::signed_dividet::validate(
319
319
const smt_function_application_termt::factoryt<
320
320
smt_bit_vector_theoryt::signed_dividet>
321
321
smt_bit_vector_theoryt::signed_divide{};
322
+
323
+ const char *smt_bit_vector_theoryt::unsigned_remaindert::identifier ()
324
+ {
325
+ return " bvurem" ;
326
+ }
327
+
328
+ smt_sortt smt_bit_vector_theoryt::unsigned_remaindert::return_sort (
329
+ const smt_termt &lhs,
330
+ const smt_termt &rhs)
331
+ {
332
+ return lhs.get_sort ();
333
+ }
334
+
335
+ void smt_bit_vector_theoryt::unsigned_remaindert::validate (
336
+ const smt_termt &lhs,
337
+ const smt_termt &rhs)
338
+ {
339
+ validate_bit_vector_predicate_arguments (lhs, rhs);
340
+ }
341
+
342
+ const smt_function_application_termt::factoryt<
343
+ smt_bit_vector_theoryt::unsigned_remaindert>
344
+ smt_bit_vector_theoryt::unsigned_remainder{};
Original file line number Diff line number Diff line change @@ -126,6 +126,15 @@ class smt_bit_vector_theoryt
126
126
};
127
127
static const smt_function_application_termt::factoryt<signed_dividet>
128
128
signed_divide;
129
+
130
+ struct unsigned_remaindert final
131
+ {
132
+ static const char *identifier ();
133
+ static smt_sortt return_sort (const smt_termt &lhs, const smt_termt &rhs);
134
+ static void validate (const smt_termt &lhs, const smt_termt &rhs);
135
+ };
136
+ static const smt_function_application_termt::factoryt<unsigned_remaindert>
137
+ unsigned_remainder;
129
138
};
130
139
131
140
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_BIT_VECTOR_THEORY_H
Original file line number Diff line number Diff line change @@ -372,4 +372,23 @@ TEST_CASE(
372
372
const cbmc_invariants_should_throwt invariants_throw;
373
373
REQUIRE_THROWS (convert_expr_to_smt (div_exprt{one_bvint, false_exprt{}}));
374
374
}
375
+
376
+ SECTION (
377
+ " Unsigned remainder (modulus) from truncating division of two constant "
378
+ " size bit-vectors" )
379
+ {
380
+ const auto constructed_term =
381
+ convert_expr_to_smt (mod_exprt{one_bvint_unsigned, two_bvint_unsigned});
382
+ const auto expected_term =
383
+ smt_bit_vector_theoryt::unsigned_remainder (smt_term_one, smt_term_two);
384
+ CHECK (constructed_term == expected_term);
385
+ }
386
+
387
+ SECTION (
388
+ " Ensure that remainder (truncated modulo) node conversion fails if the "
389
+ " operands are not bit-vector based" )
390
+ {
391
+ const cbmc_invariants_should_throwt invariants_throw;
392
+ REQUIRE_THROWS (convert_expr_to_smt (mod_exprt{one_bvint, false_exprt{}}));
393
+ }
375
394
}
Original file line number Diff line number Diff line change @@ -269,4 +269,23 @@ TEST_CASE(
269
269
// A division of a bool and a bitvector should hit an invariant violation.
270
270
REQUIRE_THROWS (smt_bit_vector_theoryt::signed_divide (true_val, three));
271
271
}
272
+
273
+ SECTION (" Unsigned Remainder" )
274
+ {
275
+ const auto function_application =
276
+ smt_bit_vector_theoryt::unsigned_remainder (two, three);
277
+ REQUIRE (
278
+ function_application.function_identifier () ==
279
+ smt_identifier_termt (" bvurem" , smt_bit_vector_sortt{8 }));
280
+ REQUIRE (function_application.get_sort () == smt_bit_vector_sortt{8 });
281
+ REQUIRE (function_application.arguments ().size () == 2 );
282
+ REQUIRE (function_application.arguments ()[0 ].get () == two);
283
+ REQUIRE (function_application.arguments ()[1 ].get () == three);
284
+
285
+ cbmc_invariants_should_throwt invariants_throw;
286
+ // Bit-vectors of mismatched sorts are going to hit an invariant violation.
287
+ REQUIRE_THROWS (smt_bit_vector_theoryt::unsigned_remainder (three, four));
288
+ // A remainder of a bool and a bitvector should hit an invariant violation.
289
+ REQUIRE_THROWS (smt_bit_vector_theoryt::unsigned_remainder (true_val, three));
290
+ }
272
291
}
You can’t perform that action at this time.
0 commit comments