Skip to content

Commit b7ada58

Browse files
author
Enrico Steffinlongo
authored
Merge pull request #7061 from diffblue/esteffin/nondet-symbol-to-new-SMT2
Add nondet_symbol_exprt translation to new SMT2 backend
2 parents 43e7a55 + 0851c80 commit b7ada58

File tree

7 files changed

+122
-11
lines changed

7 files changed

+122
-11
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
extern int undefined_function();
2+
3+
int main()
4+
{
5+
int nondet1 = undefined_function();
6+
__CPROVER_assume(nondet1 == 10);
7+
__CPROVER_assert(nondet1 < 11, "");
8+
__CPROVER_assert(undefined_function() == 0, "");
9+
10+
__CPROVER_assert(undefined_function() == undefined_function(), "");
11+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
nondet_symbol.c
3+
4+
Passing problem to incremental SMT2 solving
5+
\[main\.assertion\.1\] line 7 assertion: SUCCESS
6+
\[main\.assertion\.2\] line 8 assertion: FAILURE
7+
\[main\.assertion\.3\] line 10 assertion: FAILURE
8+
^EXIT=10$
9+
^SIGNAL=0$
10+
--
11+
--
12+
Test that running cbmc with the `--incremental-smt2-solver` supports nondet_symbol expressions.

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,11 @@ static smt_termt convert_expr_to_smt(
124124
const nondet_symbol_exprt &nondet_symbol,
125125
const sub_expression_mapt &converted)
126126
{
127-
UNIMPLEMENTED_FEATURE(
128-
"Generation of SMT formula for nondet symbol expression: " +
129-
nondet_symbol.pretty());
127+
// A nondet_symbol is a reference to an unconstrained function. This function
128+
// will already have been added as a dependency.
129+
return smt_identifier_termt{
130+
nondet_symbol.get_identifier(),
131+
convert_type_to_smt_sort(nondet_symbol.type())};
130132
}
131133

132134
/// \brief Makes a term which is true if \p input is not 0 / false.

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,16 @@ get_problem_messages(const smt_responset &response)
6262
/// `convert_expr_to_smt`. This is because any sub expressions which
6363
/// `convert_expr_to_smt` translates into function applications, must also be
6464
/// returned by this`gather_dependent_expressions` function.
65+
/// \details `symbol_exprt`, `array_exprt` and `nondet_symbol_exprt` add
66+
/// dependant expressions.
6567
static std::vector<exprt> gather_dependent_expressions(const exprt &expr)
6668
{
6769
std::vector<exprt> dependent_expressions;
6870
expr.visit_pre([&](const exprt &expr_node) {
6971
if(
7072
can_cast_expr<symbol_exprt>(expr_node) ||
71-
can_cast_expr<array_exprt>(expr_node))
73+
can_cast_expr<array_exprt>(expr_node) ||
74+
can_cast_expr<nondet_symbol_exprt>(expr_node))
7275
{
7376
dependent_expressions.push_back(expr_node);
7477
}
@@ -100,6 +103,21 @@ void smt2_incremental_decision_proceduret::define_array_function(
100103
expression_identifiers.emplace(array, array_identifier);
101104
}
102105

106+
void send_function_definition(
107+
const exprt &expr,
108+
const irep_idt &symbol_identifier,
109+
const std::unique_ptr<smt_base_solver_processt> &solver_process,
110+
std::unordered_map<exprt, smt_identifier_termt, irep_hash>
111+
&expression_identifiers)
112+
{
113+
const smt_declare_function_commandt function{
114+
smt_identifier_termt(
115+
symbol_identifier, convert_type_to_smt_sort(expr.type())),
116+
{}};
117+
expression_identifiers.emplace(expr, function.identifier());
118+
solver_process->send(function);
119+
}
120+
103121
/// \brief Defines any functions which \p expr depends on, which have not yet
104122
/// been defined, along with their dependencies in turn.
105123
void smt2_incremental_decision_proceduret::define_dependent_functions(
@@ -134,12 +152,11 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
134152
const symbolt *symbol = nullptr;
135153
if(ns.lookup(identifier, symbol) || symbol->value.is_nil())
136154
{
137-
const smt_declare_function_commandt function{
138-
smt_identifier_termt(
139-
identifier, convert_type_to_smt_sort(symbol_expr->type())),
140-
{}};
141-
expression_identifiers.emplace(*symbol_expr, function.identifier());
142-
solver_process->send(function);
155+
send_function_definition(
156+
*symbol_expr,
157+
symbol_expr->get_identifier(),
158+
solver_process,
159+
expression_identifiers);
143160
}
144161
else
145162
{
@@ -153,6 +170,16 @@ void smt2_incremental_decision_proceduret::define_dependent_functions(
153170
}
154171
if(const auto array_expr = expr_try_dynamic_cast<array_exprt>(current))
155172
define_array_function(*array_expr);
173+
if(
174+
const auto nondet_symbol =
175+
expr_try_dynamic_cast<nondet_symbol_exprt>(current))
176+
{
177+
send_function_definition(
178+
*nondet_symbol,
179+
nondet_symbol->get_identifier(),
180+
solver_process,
181+
expression_identifiers);
182+
}
156183
to_be_defined.pop();
157184
}
158185
}

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,20 @@ TEST_CASE("\"symbol_exprt\" to smt term conversion", "[core][smt2_incremental]")
119119
smt_identifier_termt("foo", smt_bool_sortt{}));
120120
}
121121

122+
TEST_CASE(
123+
"\"nondet_symbol_exprt\" to smt term conversion",
124+
"[core][smt2_incremental]")
125+
{
126+
auto test = expr_to_smt_conversion_test_environmentt::make(test_archt::i386);
127+
CHECK(
128+
test.convert(nondet_symbol_exprt{"nondet_symbol1", bool_typet{}}) ==
129+
smt_identifier_termt("nondet_symbol1", smt_bool_sortt{}));
130+
CHECK(
131+
test.convert(
132+
nondet_symbol_exprt{"nondet_symbol2", bitvector_typet{ID_bv, 42}}) ==
133+
smt_identifier_termt{"nondet_symbol2", smt_bit_vector_sortt{42}});
134+
}
135+
122136
TEST_CASE(
123137
"\"exprt\" to smt term conversion for constants/literals",
124138
"[core][smt2_incremental]")
@@ -1350,7 +1364,7 @@ TEST_CASE("expr to smt conversion for type casts", "[core][smt2_incremental]")
13501364
exprt{false_exprt{}});
13511365
const smt_termt from_term = test.convert(from_expr);
13521366
const std::size_t width = GENERATE(1, 8, 16, 32, 64);
1353-
const typecast_exprt cast{from_expr, bitvector_typet{ID_bv, width}};
1367+
const typecast_exprt cast{from_expr, bv_typet(width)};
13541368
CHECK(
13551369
test.convert(cast) == smt_core_theoryt::if_then_else(
13561370
from_term,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
goto-symex
12
solvers/smt2_incremental
23
testing-utils
34
util

unit/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
// means that we get error messages showing the smt formula expressed as SMT2
2424
// strings instead of `{?}` being printed. It works because catch uses the
2525
// appropriate overload of `operator<<` where it exists.
26+
#include <goto-symex/path_storage.h>
2627
#include <solvers/smt2_incremental/smt_to_smt2_string.h>
2728

2829
#include <deque>
@@ -306,6 +307,49 @@ TEST_CASE(
306307
"B0", {}, smt_identifier_termt{"bar", smt_bit_vector_sortt{8}}}});
307308
}
308309
}
310+
SECTION("Handle single nondet_symbol")
311+
{
312+
// Using the standard way to create nondet_symbol_exprt.
313+
::symex_nondet_generatort generator;
314+
const nondet_symbol_exprt nondet_symbol0 =
315+
generator(bool_typet{}, source_locationt{});
316+
const smt_identifier_termt nondet_symbol_term0{
317+
nondet_symbol0.get_identifier(), smt_bool_sortt{}};
318+
test.sent_commands.clear();
319+
test.procedure.handle(nondet_symbol0);
320+
REQUIRE(
321+
test.sent_commands ==
322+
std::vector<smt_commandt>{
323+
smt_declare_function_commandt{nondet_symbol_term0, {}},
324+
smt_define_function_commandt{"B0", {}, nondet_symbol_term0}});
325+
}
326+
SECTION("Handle multiple nested nondet_symbol")
327+
{
328+
::symex_nondet_generatort generator;
329+
const nondet_symbol_exprt nondet_symbol1 =
330+
generator(bv_typet(42), source_locationt{});
331+
const smt_identifier_termt nondet_symbol_term1{
332+
nondet_symbol1.get_identifier(), smt_bit_vector_sortt{42}};
333+
const nondet_symbol_exprt nondet_symbol2 =
334+
generator(bv_typet(42), source_locationt{});
335+
const smt_identifier_termt nondet_symbol_term2{
336+
nondet_symbol2.get_identifier(), smt_bit_vector_sortt{42}};
337+
// Check that the 2 calls to the generator returns unique nondet_symbols.
338+
REQUIRE(
339+
nondet_symbol1.get_identifier() != nondet_symbol_term2.identifier());
340+
test.sent_commands.clear();
341+
test.procedure.handle(equal_exprt{nondet_symbol1, nondet_symbol2});
342+
// Checking that we defined 2 symbols and that they are correctly compared.
343+
REQUIRE(
344+
test.sent_commands ==
345+
std::vector<smt_commandt>{
346+
smt_declare_function_commandt{nondet_symbol_term1, {}},
347+
smt_declare_function_commandt{nondet_symbol_term2, {}},
348+
smt_define_function_commandt{
349+
"B0",
350+
{},
351+
smt_core_theoryt::equal(nondet_symbol_term1, nondet_symbol_term2)}});
352+
}
309353
}
310354

311355
TEST_CASE(

0 commit comments

Comments
 (0)