Skip to content

Commit af46479

Browse files
committed
SMT2 back-end: fix inconsistent array flattening
Whether we flatten or don't (when datatype support is not available) depends on the expression, but we may need to unflatten when the context expects an array. Fixes: #8399
1 parent 12a0fdc commit af46479

File tree

1 file changed

+56
-53
lines changed

1 file changed

+56
-53
lines changed

src/solvers/smt2/smt2_conv.cpp

Lines changed: 56 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4445,15 +4445,22 @@ void smt2_convt::convert_member(const member_exprt &expr)
44454445
CHECK_RETURN_WITH_DIAGNOSTICS(
44464446
width != 0, "failed to get union member width");
44474447

4448-
unflatten(wheret::BEGIN, expr.type());
4448+
if(use_datatypes)
4449+
{
4450+
unflatten(wheret::BEGIN, expr.type());
44494451

4450-
out << "((_ extract "
4451-
<< (width-1)
4452-
<< " 0) ";
4453-
convert_expr(struct_op);
4454-
out << ")";
4452+
out << "((_ extract " << (width - 1) << " 0) ";
4453+
convert_expr(struct_op);
4454+
out << ")";
44554455

4456-
unflatten(wheret::END, expr.type());
4456+
unflatten(wheret::END, expr.type());
4457+
}
4458+
else
4459+
{
4460+
out << "((_ extract " << (width - 1) << " 0) ";
4461+
convert_expr(struct_op);
4462+
out << ")";
4463+
}
44574464
}
44584465
else
44594466
UNEXPECTEDCASE(
@@ -4565,57 +4572,50 @@ void smt2_convt::unflatten(
45654572
}
45664573
else if(type.id() == ID_array)
45674574
{
4568-
if(use_datatypes)
4575+
PRECONDITION(use_as_const);
4576+
4577+
if(where == wheret::BEGIN)
4578+
out << "(let ((?ufop" << nesting << " ";
4579+
else
45694580
{
4570-
PRECONDITION(use_as_const);
4581+
out << ")) ";
45714582

4572-
if(where == wheret::BEGIN)
4573-
out << "(let ((?ufop" << nesting << " ";
4574-
else
4575-
{
4576-
out << ")) ";
4583+
const array_typet &array_type = to_array_type(type);
45774584

4578-
const array_typet &array_type = to_array_type(type);
4585+
std::size_t subtype_width = boolbv_width(array_type.element_type());
45794586

4580-
std::size_t subtype_width = boolbv_width(array_type.element_type());
4587+
DATA_INVARIANT(
4588+
array_type.size().is_constant(),
4589+
"cannot unflatten arrays of non-constant size");
4590+
mp_integer size =
4591+
numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));
45814592

4582-
DATA_INVARIANT(
4583-
array_type.size().is_constant(),
4584-
"cannot unflatten arrays of non-constant size");
4585-
mp_integer size =
4586-
numeric_cast_v<mp_integer>(to_constant_expr(array_type.size()));
4593+
for(mp_integer i = 1; i < size; ++i)
4594+
out << "(store ";
45874595

4588-
for(mp_integer i = 1; i < size; ++i)
4589-
out << "(store ";
4596+
out << "((as const ";
4597+
convert_type(array_type);
4598+
out << ") ";
4599+
// use element at index 0 as default value
4600+
unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
4601+
out << "((_ extract " << subtype_width - 1 << " "
4602+
<< "0) ?ufop" << nesting << ")";
4603+
unflatten(wheret::END, array_type.element_type(), nesting + 1);
4604+
out << ") ";
45904605

4591-
out << "((as const ";
4592-
convert_type(array_type);
4593-
out << ") ";
4594-
// use element at index 0 as default value
4606+
std::size_t offset = subtype_width;
4607+
for(mp_integer i = 1; i < size; ++i, offset += subtype_width)
4608+
{
4609+
convert_expr(from_integer(i, array_type.index_type()));
4610+
out << ' ';
45954611
unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
4596-
out << "((_ extract " << subtype_width - 1 << " "
4597-
<< "0) ?ufop" << nesting << ")";
4612+
out << "((_ extract " << offset + subtype_width - 1 << " " << offset
4613+
<< ") ?ufop" << nesting << ")";
45984614
unflatten(wheret::END, array_type.element_type(), nesting + 1);
4599-
out << ") ";
4600-
4601-
std::size_t offset = subtype_width;
4602-
for(mp_integer i = 1; i < size; ++i, offset += subtype_width)
4603-
{
4604-
convert_expr(from_integer(i, array_type.index_type()));
4605-
out << ' ';
4606-
unflatten(wheret::BEGIN, array_type.element_type(), nesting + 1);
4607-
out << "((_ extract " << offset + subtype_width - 1 << " " << offset
4608-
<< ") ?ufop" << nesting << ")";
4609-
unflatten(wheret::END, array_type.element_type(), nesting + 1);
4610-
out << ")"; // store
4611-
}
4612-
4613-
out << ")"; // let
4615+
out << ")"; // store
46144616
}
4615-
}
4616-
else
4617-
{
4618-
// nop, already a bv
4617+
4618+
out << ")"; // let
46194619
}
46204620
}
46214621
else if(type.id() == ID_struct || type.id() == ID_struct_tag)
@@ -4767,19 +4767,22 @@ void smt2_convt::set_to(const exprt &expr, bool value)
47674767
{
47684768
out << "(define-fun " << smt2_identifier;
47694769
out << " () ";
4770+
convert_type(equal_expr.lhs().type());
4771+
out << ' ';
47704772
if(
47714773
equal_expr.lhs().type().id() != ID_array ||
47724774
use_array_theory(prepared_rhs))
47734775
{
4774-
convert_type(equal_expr.lhs().type());
4776+
convert_expr(prepared_rhs);
47754777
}
47764778
else
47774779
{
4778-
std::size_t width = boolbv_width(equal_expr.lhs().type());
4779-
out << "(_ BitVec " << width << ")";
4780+
unflatten(wheret::BEGIN, equal_expr.lhs().type());
4781+
4782+
convert_expr(prepared_rhs);
4783+
4784+
unflatten(wheret::END, equal_expr.lhs().type());
47804785
}
4781-
out << ' ';
4782-
convert_expr(prepared_rhs);
47834786
out << ')' << '\n';
47844787
}
47854788

0 commit comments

Comments
 (0)