Skip to content

Commit c9ea0b8

Browse files
author
Enrico Steffinlongo
committed
Support for enum in incremental SMT2 traces
This commit enables the generation of traces containing expression of type `c_enum_tag_typet`.
1 parent fc4308d commit c9ea0b8

File tree

4 files changed

+55
-16
lines changed

4 files changed

+55
-16
lines changed

src/solvers/smt2_incremental/construct_value_expr_from_smt.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Author: Diffblue Ltd.
22

33
#include <util/arith_tools.h>
4+
#include <util/c_types.h>
5+
#include <util/namespace.h>
46
#include <util/pointer_expr.h>
57
#include <util/std_expr.h>
68
#include <util/std_types.h>
@@ -13,10 +15,13 @@ class value_expr_from_smt_factoryt : public smt_term_const_downcast_visitort
1315
{
1416
private:
1517
const typet &type_to_construct;
18+
const namespacet &ns;
1619
optionalt<exprt> result;
1720

18-
explicit value_expr_from_smt_factoryt(const typet &type_to_construct)
19-
: type_to_construct{type_to_construct}, result{}
21+
explicit value_expr_from_smt_factoryt(
22+
const typet &type_to_construct,
23+
const namespacet &ns)
24+
: type_to_construct{type_to_construct}, ns{ns}, result{}
2025
{
2126
}
2227

@@ -70,6 +75,20 @@ class value_expr_from_smt_factoryt : public smt_term_const_downcast_visitort
7075
result = from_integer(bit_vector_constant.value(), type_to_construct);
7176
return;
7277
}
78+
if(
79+
const auto c_enum_tag_type =
80+
type_try_dynamic_cast<c_enum_tag_typet>(type_to_construct))
81+
{
82+
const c_enum_typet &real_type = ns.follow_tag(*c_enum_tag_type);
83+
INVARIANT(
84+
to_bitvector_type(real_type.underlying_type()).get_width() ==
85+
sort_width,
86+
"Width of smt bit vector term must match the width of bit vector "
87+
"underlying type of the original c_enum type.");
88+
result = from_integer(bit_vector_constant.value(), real_type);
89+
result->type() = type_to_construct;
90+
return;
91+
}
7392

7493
INVARIANT(
7594
false,
@@ -102,9 +121,12 @@ class value_expr_from_smt_factoryt : public smt_term_const_downcast_visitort
102121
/// \brief This function is complete the external interface to this class. All
103122
/// construction of this class and construction of expressions should be
104123
/// carried out via this function.
105-
static exprt make(const smt_termt &value_term, const typet &type_to_construct)
124+
static exprt make(
125+
const smt_termt &value_term,
126+
const typet &type_to_construct,
127+
const namespacet &ns)
106128
{
107-
value_expr_from_smt_factoryt factory{type_to_construct};
129+
value_expr_from_smt_factoryt factory{type_to_construct, ns};
108130
value_term.accept(factory);
109131
INVARIANT(factory.result.has_value(), "Factory must result in expr value.");
110132
return *factory.result;
@@ -113,7 +135,8 @@ class value_expr_from_smt_factoryt : public smt_term_const_downcast_visitort
113135

114136
exprt construct_value_expr_from_smt(
115137
const smt_termt &value_term,
116-
const typet &type_to_construct)
138+
const typet &type_to_construct,
139+
const namespacet &ns)
117140
{
118-
return value_expr_from_smt_factoryt::make(value_term, type_to_construct);
141+
return value_expr_from_smt_factoryt::make(value_term, type_to_construct, ns);
119142
}

src/solvers/smt2_incremental/construct_value_expr_from_smt.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class typet;
1818
/// \param type_to_construct
1919
/// The type which the constructed expr returned is expected to have. This
2020
/// type must be compatible with the sort of \p value_term.
21+
/// \param ns
22+
/// The namespace to resolve `c_enum_tag_type` to reconstruct the correct
23+
/// type of enum values in the trace.
2124
/// \note The type is required separately in order to carry out this conversion,
2225
/// because the smt value term does not contain all the required information.
2326
/// For example an 8 bit, bit vector with a value of 255 could be used to
@@ -26,6 +29,7 @@ class typet;
2629
/// using the type.
2730
exprt construct_value_expr_from_smt(
2831
const smt_termt &value_term,
29-
const typet &type_to_construct);
32+
const typet &type_to_construct,
33+
const namespacet &ns);
3034

3135
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_CONSTRUCT_VALUE_EXPR_FROM_SMT_H

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,15 @@ static optionalt<smt_termt> get_identifier(
348348
const std::unordered_map<exprt, smt_identifier_termt, irep_hash>
349349
&expression_handle_identifiers,
350350
const std::unordered_map<exprt, smt_identifier_termt, irep_hash>
351-
&expression_identifiers)
351+
&expression_identifiers,
352+
const namespacet &ns)
352353
{
353-
const auto handle_find_result = expression_handle_identifiers.find(expr);
354+
const exprt lowered_expr = lower_enum(expr, ns);
355+
const auto handle_find_result =
356+
expression_handle_identifiers.find(lowered_expr);
354357
if(handle_find_result != expression_handle_identifiers.cend())
355358
return handle_find_result->second;
356-
const auto expr_find_result = expression_identifiers.find(expr);
359+
const auto expr_find_result = expression_identifiers.find(lowered_expr);
357360
if(expr_find_result != expression_identifiers.cend())
358361
return expr_find_result->second;
359362
return {};
@@ -410,7 +413,7 @@ exprt smt2_incremental_decision_proceduret::get_expr(
410413
response.pretty()};
411414
}
412415
return construct_value_expr_from_smt(
413-
get_value_response->pairs()[0].get().value(), type);
416+
get_value_response->pairs()[0].get().value(), type, ns);
414417
}
415418

416419
// This is a fall back which builds resulting expression based on getting the
@@ -447,18 +450,20 @@ exprt smt2_incremental_decision_proceduret::get(const exprt &expr) const
447450
const auto array = get_identifier(
448451
index_expr->array(),
449452
expression_handle_identifiers,
450-
expression_identifiers);
453+
expression_identifiers,
454+
ns);
451455
const auto index = get_identifier(
452456
index_expr->index(),
453457
expression_handle_identifiers,
454-
expression_identifiers);
458+
expression_identifiers,
459+
ns);
455460
if(!array || !index)
456461
return {};
457462
return smt_array_theoryt::select(*array, *index);
458463
}
459464
if(
460465
auto identifier_descriptor = get_identifier(
461-
expr, expression_handle_identifiers, expression_identifiers))
466+
expr, expression_handle_identifiers, expression_identifiers, ns))
462467
{
463468
return identifier_descriptor;
464469
}

unit/solvers/smt2_incremental/construct_value_expr_from_smt.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
#include <util/arith_tools.h>
44
#include <util/bitvector_types.h>
55
#include <util/c_types.h>
6+
#include <util/namespace.h>
67
#include <util/std_expr.h>
78
#include <util/std_types.h>
9+
#include <util/symbol_table.h>
810

911
#include <solvers/smt2_incremental/ast/smt_terms.h>
1012
#include <solvers/smt2_incremental/construct_value_expr_from_smt.h>
@@ -31,6 +33,8 @@ static mp_integer max_int(const std::size_t bits)
3133

3234
TEST_CASE("Value expr construction from smt.", "[core][smt2_incremental]")
3335
{
36+
const symbol_tablet symbol_table;
37+
const namespacet ns{symbol_table};
3438
optionalt<smt_termt> input_term;
3539
optionalt<exprt> expected_result;
3640

@@ -90,7 +94,7 @@ TEST_CASE("Value expr construction from smt.", "[core][smt2_incremental]")
9094
"\" from \"" + smt_to_smt2_string(*input_term) + "\"")
9195
{
9296
REQUIRE(
93-
construct_value_expr_from_smt(*input_term, expected_result->type()) ==
97+
construct_value_expr_from_smt(*input_term, expected_result->type(), ns) ==
9498
*expected_result);
9599
}
96100
}
@@ -99,6 +103,8 @@ TEST_CASE(
99103
"Invariant violations in value expr construction from smt.",
100104
"[core][smt2_incremental]")
101105
{
106+
const symbol_tablet symbol_table;
107+
const namespacet ns{symbol_table};
102108
optionalt<smt_termt> input_term;
103109
optionalt<typet> input_type;
104110
std::string invariant_reason;
@@ -145,8 +151,9 @@ TEST_CASE(
145151
SECTION(invariant_reason)
146152
{
147153
const cbmc_invariants_should_throwt invariants_throw;
154+
148155
REQUIRE_THROWS_MATCHES(
149-
construct_value_expr_from_smt(*input_term, *input_type),
156+
construct_value_expr_from_smt(*input_term, *input_type, ns),
150157
invariant_failedt,
151158
invariant_failure_containing(invariant_reason));
152159
}

0 commit comments

Comments
 (0)