Skip to content

Commit 10a2a53

Browse files
committed
Add implementation of negation (unary minus - bvneg) operator.
Along with conversion tests and tests of the factory method integrity.
1 parent a1c923c commit 10a2a53

File tree

5 files changed

+71
-3
lines changed

5 files changed

+71
-3
lines changed

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,19 @@ static smt_termt convert_expr_to_smt(const bitnot_exprt &bitwise_not)
154154

155155
static smt_termt convert_expr_to_smt(const unary_minus_exprt &unary_minus)
156156
{
157-
UNIMPLEMENTED_FEATURE(
158-
"Generation of SMT formula for unary minus expression: " +
159-
unary_minus.pretty());
157+
const bool operand_is_bitvector =
158+
can_cast_type<integer_bitvector_typet>(unary_minus.op().type());
159+
if(operand_is_bitvector)
160+
{
161+
return smt_bit_vector_theoryt::negate(
162+
convert_expr_to_smt(unary_minus.op()));
163+
}
164+
else
165+
{
166+
UNIMPLEMENTED_FEATURE(
167+
"Generation of SMT formula for unary minus expression: " +
168+
unary_minus.pretty());
169+
}
160170
}
161171

162172
static smt_termt convert_expr_to_smt(const unary_plus_exprt &unary_plus)

src/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,22 @@ void smt_bit_vector_theoryt::signed_remaindert::validate(
365365
const smt_function_application_termt::factoryt<
366366
smt_bit_vector_theoryt::signed_remaindert>
367367
smt_bit_vector_theoryt::signed_remainder{};
368+
369+
const char *smt_bit_vector_theoryt::negatet::identifier()
370+
{
371+
return "bvneg";
372+
}
373+
374+
smt_sortt smt_bit_vector_theoryt::negatet::return_sort(const smt_termt &operand)
375+
{
376+
return operand.get_sort();
377+
}
378+
379+
void smt_bit_vector_theoryt::negatet::validate(const smt_termt &operand)
380+
{
381+
const auto operand_sort = operand.get_sort().cast<smt_bit_vector_sortt>();
382+
INVARIANT(operand_sort, "The operand is expected to have a bit-vector sort.");
383+
}
384+
385+
const smt_function_application_termt::factoryt<smt_bit_vector_theoryt::negatet>
386+
smt_bit_vector_theoryt::negate{};

src/solvers/smt2_incremental/smt_bit_vector_theory.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@ class smt_bit_vector_theoryt
144144
};
145145
static const smt_function_application_termt::factoryt<signed_remaindert>
146146
signed_remainder;
147+
148+
struct negatet final
149+
{
150+
static const char *identifier();
151+
static smt_sortt return_sort(const smt_termt &operand);
152+
static void validate(const smt_termt &operand);
153+
};
154+
static const smt_function_application_termt::factoryt<negatet> negate;
147155
};
148156

149157
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT_BIT_VECTOR_THEORY_H

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,4 +399,20 @@ TEST_CASE(
399399
const cbmc_invariants_should_throwt invariants_throw;
400400
REQUIRE_THROWS(convert_expr_to_smt(mod_exprt{one_bvint, false_exprt{}}));
401401
}
402+
403+
SECTION("Unary minus of constant size bit-vector")
404+
{
405+
const auto constructed_term =
406+
convert_expr_to_smt(unary_minus_exprt{one_bvint});
407+
const auto expected_term = smt_bit_vector_theoryt::negate(smt_term_one);
408+
CHECK(constructed_term == expected_term);
409+
}
410+
411+
SECTION(
412+
"Ensure that unary minus node conversion fails if the operand is not a "
413+
"bit-vector")
414+
{
415+
const cbmc_invariants_should_throwt invariants_throw;
416+
REQUIRE_THROWS(convert_expr_to_smt(unary_minus_exprt{true_exprt{}}));
417+
}
402418
}

unit/solvers/smt2_incremental/smt_bit_vector_theory.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,19 @@ TEST_CASE(
309309
// A remainder of a bool and a bitvector should hit an invariant violation.
310310
REQUIRE_THROWS(smt_bit_vector_theoryt::signed_remainder(true_val, three));
311311
}
312+
313+
SECTION("Unary Minus")
314+
{
315+
const auto function_application = smt_bit_vector_theoryt::negate(two);
316+
REQUIRE(
317+
function_application.function_identifier() ==
318+
smt_identifier_termt("bvneg", smt_bit_vector_sortt{8}));
319+
REQUIRE(function_application.get_sort() == smt_bit_vector_sortt{8});
320+
REQUIRE(function_application.arguments().size() == 1);
321+
REQUIRE(function_application.arguments()[0].get() == two);
322+
323+
cbmc_invariants_should_throwt invariants_throw;
324+
// Negation of a value of bool sort should fail with an invariant violation.
325+
REQUIRE_THROWS(smt_bit_vector_theoryt::negate(true_val));
326+
}
312327
}

0 commit comments

Comments
 (0)