Skip to content

Commit 21ff086

Browse files
authored
Merge pull request #6988 from esteffin/tas/array_index_of
Add array read and update function to SMT2 backend
2 parents 365871d + 462ab19 commit 21ff086

File tree

12 files changed

+140
-9
lines changed

12 files changed

+140
-9
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
int main()
2+
{
3+
int example_array[10000];
4+
unsigned int index;
5+
__CPROVER_assume(index < 10000);
6+
__CPROVER_assert(example_array[index] != 42, "Array condition");
7+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
array_read.c
3+
4+
Passing problem to incremental SMT2 solving
5+
\[main\.assertion\.1\] line \d+ Array condition: FAILURE
6+
^EXIT=10$
7+
^SIGNAL=0$
8+
--
9+
--
10+
Test of reading an index of an array.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
int main()
2+
{
3+
int example_array[10000];
4+
unsigned int index;
5+
__CPROVER_assume(index < 10000);
6+
example_array[index] = 42;
7+
__CPROVER_assert(example_array[index] == 42, "Array condition");
8+
__CPROVER_assert(example_array[index] != 42, "Array condition");
9+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
array_write.c
3+
4+
Passing problem to incremental SMT2 solving
5+
\[main\.assertion\.1\] line \d+ Array condition: SUCCESS
6+
\[main\.assertion\.2\] line \d+ Array condition: FAILURE
7+
^EXIT=10$
8+
^SIGNAL=0$
9+
--
10+
--
11+
Test of updating the value at an index of an array.

regression/cbmc-incr-smt2/nondeterministic-int-assert/control_flow.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ control_flow.c
33
--verbosity 10
44
Passing problem to incremental SMT2 solving via
55
Sending command to SMT2 solver - \(set-option :produce-models true\)
6-
Sending command to SMT2 solver - \(set-logic QF_UFBV\)
6+
Sending command to SMT2 solver - \(set-logic QF_AUFBV\)
77
Sending command to SMT2 solver - \(declare-fun |goto_symex::&92;guard#1| \(\) Bool\)
88
Sending command to SMT2 solver - \(define-fun |B1| \(\) Bool |goto_symex::&92;guard#1|\)
99
Sending command to SMT2 solver - \(declare-fun |main::1::x!0@1#1| \(\) \(_ BitVec 32\)\)

regression/cbmc-incr-smt2/nondeterministic-int-assert/incremental_solver_called.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ test.c
33
--verbosity 10
44
Passing problem to incremental SMT2 solving via
55
Sending command to SMT2 solver - \(set-option :produce-models true\)
6-
Sending command to SMT2 solver - \(set-logic QF_UFBV\)
6+
Sending command to SMT2 solver - \(set-logic QF_AUFBV\)
77
Sending command to SMT2 solver - \(define-fun |B0| \(\) Bool true\)
88
Sending command to SMT2 solver - \(declare-fun |main::1::x!0@1#1| \(\) \(_ BitVec 32\)\)
99
Sending command to SMT2 solver - \(define-fun |B1| \(\) Bool \(|=| |main::1::x!0@1#1| |main::1::x!0@1#1|\)\)

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <solvers/prop/literal_expr.h>
2020
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
21+
#include <solvers/smt2_incremental/smt_array_theory.h>
2122
#include <solvers/smt2_incremental/smt_bit_vector_theory.h>
2223
#include <solvers/smt2_incremental/smt_core_theory.h>
2324

@@ -89,6 +90,13 @@ static smt_sortt convert_type_to_smt_sort(const bitvector_typet &type)
8990
return smt_bit_vector_sortt{type.get_width()};
9091
}
9192

93+
static smt_sortt convert_type_to_smt_sort(const array_typet &type)
94+
{
95+
return smt_array_sortt{
96+
convert_type_to_smt_sort(type.index_type()),
97+
convert_type_to_smt_sort(type.element_type())};
98+
}
99+
92100
smt_sortt convert_type_to_smt_sort(const typet &type)
93101
{
94102
if(const auto bool_type = type_try_dynamic_cast<bool_typet>(type))
@@ -99,6 +107,10 @@ smt_sortt convert_type_to_smt_sort(const typet &type)
99107
{
100108
return convert_type_to_smt_sort(*bitvector_type);
101109
}
110+
if(const auto array_type = type_try_dynamic_cast<array_typet>(type))
111+
{
112+
return convert_type_to_smt_sort(*array_type);
113+
}
102114
UNIMPLEMENTED_FEATURE("Generation of SMT formula for type: " + type.pretty());
103115
}
104116

@@ -906,11 +918,12 @@ static smt_termt convert_expr_to_smt(
906918
}
907919

908920
static smt_termt convert_expr_to_smt(
909-
const index_exprt &index,
921+
const index_exprt &index_of,
910922
const sub_expression_mapt &converted)
911923
{
912-
UNIMPLEMENTED_FEATURE(
913-
"Generation of SMT formula for index expression: " + index.pretty());
924+
const smt_termt &array = converted.at(index_of.array());
925+
const smt_termt &index = converted.at(index_of.index());
926+
return smt_array_theoryt::select(array, index);
914927
}
915928

916929
template <typename factoryt, typename shiftt>
@@ -978,10 +991,29 @@ static smt_termt convert_expr_to_smt(
978991
"Generation of SMT formula for shift expression: " + shift.pretty());
979992
}
980993

994+
static smt_termt convert_array_update_to_smt(
995+
const exprt &old,
996+
const exprt &index,
997+
const exprt &new_value,
998+
const sub_expression_mapt &converted)
999+
{
1000+
const smt_termt &old_array_term = converted.at(old);
1001+
const smt_termt &index_term = converted.at(index);
1002+
const smt_termt &value_term = converted.at(new_value);
1003+
return smt_array_theoryt::store(old_array_term, index_term, value_term);
1004+
}
1005+
9811006
static smt_termt convert_expr_to_smt(
9821007
const with_exprt &with,
9831008
const sub_expression_mapt &converted)
9841009
{
1010+
if(const auto array_type = type_try_dynamic_cast<array_typet>(with.type()))
1011+
{
1012+
return convert_array_update_to_smt(
1013+
with.old(), with.where(), with.new_value(), converted);
1014+
}
1015+
// 'with' expression is also used to update struct fields, but for now we do
1016+
// not support them, so we fail.
9851017
UNIMPLEMENTED_FEATURE(
9861018
"Generation of SMT formula for with expression: " + with.pretty());
9871019
}

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret(
140140
solver_process->send(
141141
smt_set_option_commandt{smt_option_produce_modelst{true}});
142142
solver_process->send(smt_set_logic_commandt{
143-
smt_logic_quantifier_free_uninterpreted_functions_bit_vectorst{}});
143+
smt_logic_quantifier_free_arrays_uninterpreted_functions_bit_vectorst{}});
144144
solver_process->send(object_size_function.declaration);
145145
}
146146

src/solvers/smt2_incremental/smt_logics.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ LOGIC_ID(quantifier_free_uninterpreted_functions, QF_UF)
1010
LOGIC_ID(quantifier_free_bit_vectors, QF_BV)
1111
LOGIC_ID(quantifier_free_uninterpreted_functions_bit_vectors, QF_UFBV)
1212
LOGIC_ID(quantifier_free_bit_vectors_arrays, QF_ABV)
13-
LOGIC_ID(quantifier_free_uninterpreted_functions_bit_vectors_arrays, QF_AUFBV)
13+
LOGIC_ID(quantifier_free_arrays_uninterpreted_functions_bit_vectors, QF_AUFBV)
1414
LOGIC_ID(all, ALL)

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
1616
#include <solvers/smt2_incremental/object_tracking.h>
17+
#include <solvers/smt2_incremental/smt_array_theory.h>
1718
#include <solvers/smt2_incremental/smt_bit_vector_theory.h>
1819
#include <solvers/smt2_incremental/smt_core_theory.h>
1920
#include <solvers/smt2_incremental/smt_terms.h>
@@ -96,6 +97,20 @@ expr_to_smt_conversion_test_environmentt::convert(const exprt &expression) const
9697
object_size_function.make_application);
9798
}
9899

100+
TEST_CASE("\"array_typet\" to smt sort conversion", "[core][smt2_incremental]")
101+
{
102+
auto test =
103+
expr_to_smt_conversion_test_environmentt::make(test_archt::x86_64);
104+
105+
const auto array_type =
106+
array_typet{signedbv_typet{8}, from_integer(8, c_index_type())};
107+
INFO("Type being converted: " + array_type.pretty(2, 0));
108+
const auto conversion_result = convert_type_to_smt_sort(array_type);
109+
CHECK(
110+
conversion_result ==
111+
smt_array_sortt{smt_bit_vector_sortt{64}, smt_bit_vector_sortt{8}});
112+
}
113+
99114
TEST_CASE("\"symbol_exprt\" to smt term conversion", "[core][smt2_incremental]")
100115
{
101116
auto test = expr_to_smt_conversion_test_environmentt::make(test_archt::i386);
@@ -1126,6 +1141,52 @@ TEST_CASE(
11261141
}
11271142
}
11281143

1144+
TEST_CASE(
1145+
"expr to smt conversion for index_exprt expressions",
1146+
"[core][smt2_incremental]")
1147+
{
1148+
auto test =
1149+
expr_to_smt_conversion_test_environmentt::make(test_archt::x86_64);
1150+
const typet value_type = signedbv_typet{8};
1151+
const exprt array = symbol_exprt{
1152+
"my_array", array_typet{value_type, from_integer(10, signed_size_type())}};
1153+
const exprt index = from_integer(42, unsignedbv_typet{64});
1154+
const index_exprt index_expr{array, index};
1155+
INFO("Expression being converted: " + index_expr.pretty(2, 0));
1156+
const smt_termt expected = smt_array_theoryt::select(
1157+
smt_identifier_termt{
1158+
"my_array",
1159+
smt_array_sortt{smt_bit_vector_sortt{64}, smt_bit_vector_sortt{8}}},
1160+
smt_bit_vector_constant_termt{42, 64});
1161+
CHECK(test.convert(index_expr) == expected);
1162+
}
1163+
1164+
TEST_CASE(
1165+
"expr to smt conversion for with_exprt expressions",
1166+
"[core][smt2_incremental]")
1167+
{
1168+
auto test =
1169+
expr_to_smt_conversion_test_environmentt::make(test_archt::x86_64);
1170+
SECTION("Array types")
1171+
{
1172+
const typet value_type = signedbv_typet{8};
1173+
const exprt array = symbol_exprt{
1174+
"my_array",
1175+
array_typet{value_type, from_integer(10, signed_size_type())}};
1176+
const exprt index = from_integer(42, unsignedbv_typet{64});
1177+
const exprt value = from_integer(12, value_type);
1178+
const with_exprt with{array, index, value};
1179+
INFO("Expression being converted: " + with.pretty(2, 0));
1180+
const smt_termt expected = smt_array_theoryt::store(
1181+
smt_identifier_termt{
1182+
"my_array",
1183+
smt_array_sortt{smt_bit_vector_sortt{64}, smt_bit_vector_sortt{8}}},
1184+
smt_bit_vector_constant_termt{42, 64},
1185+
smt_bit_vector_constant_termt{12, 8});
1186+
CHECK(test.convert(with) == expected);
1187+
}
1188+
}
1189+
11291190
TEST_CASE(
11301191
"expr to smt conversion for extract bits expressions",
11311192
"[core][smt2_incremental]")

0 commit comments

Comments
 (0)