Skip to content

Commit ecec3b3

Browse files
committed
Implement conversion of boolean casts into SMT2 terms
1 parent f882958 commit ecec3b3

File tree

2 files changed

+87
-5
lines changed

2 files changed

+87
-5
lines changed

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
// Author: Diffblue Ltd.
22

3-
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
4-
5-
#include <solvers/prop/literal_expr.h>
6-
#include <solvers/smt2_incremental/smt_bit_vector_theory.h>
7-
#include <solvers/smt2_incremental/smt_core_theory.h>
83
#include <util/arith_tools.h>
94
#include <util/bitvector_expr.h>
105
#include <util/byte_operators.h>
6+
#include <util/c_types.h>
117
#include <util/expr.h>
128
#include <util/expr_cast.h>
139
#include <util/floatbv_expr.h>
@@ -18,6 +14,11 @@
1814
#include <util/std_expr.h>
1915
#include <util/string_constant.h>
2016

17+
#include <solvers/prop/literal_expr.h>
18+
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
19+
#include <solvers/smt2_incremental/smt_bit_vector_theory.h>
20+
#include <solvers/smt2_incremental/smt_core_theory.h>
21+
2122
#include <functional>
2223
#include <numeric>
2324

@@ -98,8 +99,37 @@ static smt_termt convert_expr_to_smt(const nondet_symbol_exprt &nondet_symbol)
9899
nondet_symbol.pretty());
99100
}
100101

102+
/// \brief Makes a term which is true if \p input is not 0 / false.
103+
static smt_termt make_not_zero(const smt_termt &input, const typet &source_type)
104+
{
105+
if(input.get_sort().cast<smt_bool_sortt>())
106+
return input;
107+
return smt_core_theoryt::distinct(
108+
input, convert_expr_to_smt(from_integer(0, source_type)));
109+
}
110+
111+
/// \brief Returns a cast to C bool expressed in smt terms.
112+
static smt_termt convert_c_bool_cast(
113+
const smt_termt &from_term,
114+
const typet &from_type,
115+
const c_bool_typet &to_type)
116+
{
117+
const std::size_t c_bool_width = to_type.get_width();
118+
return smt_core_theoryt::if_then_else(
119+
make_not_zero(from_term, from_type),
120+
smt_bit_vector_constant_termt{1, c_bool_width},
121+
smt_bit_vector_constant_termt{0, c_bool_width});
122+
}
123+
101124
static smt_termt convert_expr_to_smt(const typecast_exprt &cast)
102125
{
126+
const auto from_term = convert_expr_to_smt(cast.op());
127+
const typet &from_type = cast.op().type();
128+
const typet &to_type = cast.type();
129+
if(const auto bool_type = type_try_dynamic_cast<bool_typet>(to_type))
130+
return make_not_zero(from_term, cast.op().type());
131+
if(const auto c_bool_type = type_try_dynamic_cast<c_bool_typet>(to_type))
132+
return convert_c_bool_cast(from_term, from_type, *c_bool_type);
103133
UNIMPLEMENTED_FEATURE(
104134
"Generation of SMT formula for type cast expression: " + cast.pretty());
105135
}

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
#include <util/arith_tools.h>
44
#include <util/bitvector_expr.h>
55
#include <util/bitvector_types.h>
6+
#include <util/c_types.h>
7+
#include <util/config.h>
68
#include <util/format.h>
79
#include <util/std_expr.h>
810

911
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
1012
#include <solvers/smt2_incremental/smt_bit_vector_theory.h>
1113
#include <solvers/smt2_incremental/smt_core_theory.h>
1214
#include <solvers/smt2_incremental/smt_terms.h>
15+
#include <solvers/smt2_incremental/smt_to_smt2_string.h>
1316
#include <testing-utils/use_catch.h>
1417

1518
TEST_CASE("\"typet\" to smt sort conversion", "[core][smt2_incremental]")
@@ -814,3 +817,52 @@ SCENARIO(
814817
}
815818
}
816819
}
820+
821+
TEST_CASE("expr to smt conversion for type casts", "[core][smt2_incremental]")
822+
{
823+
const symbol_exprt bool_expr{"foo", bool_typet{}};
824+
const smt_termt bool_term = smt_identifier_termt{"foo", smt_bool_sortt{}};
825+
const symbol_exprt bv_expr{"bar", signedbv_typet(12)};
826+
const smt_termt bv_term =
827+
smt_identifier_termt{"bar", smt_bit_vector_sortt{12}};
828+
SECTION("Casts to bool")
829+
{
830+
CHECK(
831+
convert_expr_to_smt(typecast_exprt{bool_expr, bool_typet{}}) ==
832+
bool_term);
833+
CHECK(
834+
convert_expr_to_smt(typecast_exprt{bv_expr, bool_typet{}}) ==
835+
smt_core_theoryt::distinct(
836+
bv_term, smt_bit_vector_constant_termt{0, 12}));
837+
}
838+
SECTION("Casts to C bool")
839+
{
840+
// The config lines are necessary because when we do casting to C bool the
841+
// bit width depends on the configuration.
842+
config.ansi_c.mode = configt::ansi_ct::flavourt::GCC;
843+
config.ansi_c.set_arch_spec_i386();
844+
const std::size_t c_bool_width = config.ansi_c.bool_width;
845+
const smt_bit_vector_constant_termt c_true{1, c_bool_width};
846+
const smt_bit_vector_constant_termt c_false{0, c_bool_width};
847+
SECTION("from bool")
848+
{
849+
const auto cast_bool =
850+
convert_expr_to_smt(typecast_exprt{bool_expr, c_bool_type()});
851+
const auto expected_bool_conversion =
852+
smt_core_theoryt::if_then_else(bool_term, c_true, c_false);
853+
CHECK(cast_bool == expected_bool_conversion);
854+
}
855+
SECTION("from bit vector")
856+
{
857+
const auto cast_bit_vector =
858+
convert_expr_to_smt(typecast_exprt{bv_expr, c_bool_type()});
859+
const auto expected_bit_vector_conversion =
860+
smt_core_theoryt::if_then_else(
861+
smt_core_theoryt::distinct(
862+
bv_term, smt_bit_vector_constant_termt{0, 12}),
863+
c_true,
864+
c_false);
865+
CHECK(cast_bit_vector == expected_bit_vector_conversion);
866+
}
867+
}
868+
}

0 commit comments

Comments
 (0)