Skip to content

Commit 31e4ddf

Browse files
authored
Merge pull request #6862 from tautschnig/cleanup/optional-size
boolbv_width: distinguish zero from unknown size
2 parents 3b340ad + 6685497 commit 31e4ddf

33 files changed

+177
-248
lines changed

Diff for: regression/cbmc/dynamic_sizeof1/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE broken-z3-smt-backend
22
main.c
33

44
^EXIT=0$

Diff for: regression/cbmc/vla1/test.desc

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
CORE
1+
CORE broken-cprover-smt-backend
22
main.c
33

44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$
77
--
88
^warning: ignoring
9+
--
10+
The SMT back-end does not correctly support structs with non-constant size,
11+
unless named data types are used (as is the case with Z3).

Diff for: src/solvers/flattening/boolbv.cpp

+6-12
Original file line numberDiff line numberDiff line change
@@ -242,22 +242,16 @@ bvt boolbvt::convert_array_comprehension(const array_comprehension_exprt &expr)
242242
{
243243
std::size_t width=boolbv_width(expr.type());
244244

245-
if(width==0)
246-
return conversion_failed(expr);
247-
248245
const exprt &array_size = expr.type().size();
249246

250-
const auto size = numeric_cast<mp_integer>(array_size);
251-
252-
if(!size.has_value())
253-
return conversion_failed(expr);
247+
const auto size = numeric_cast_v<mp_integer>(to_constant_expr(array_size));
254248

255249
typet counter_type = expr.arg().type();
256250

257251
bvt bv;
258252
bv.resize(width);
259253

260-
for(mp_integer i = 0; i < *size; ++i)
254+
for(mp_integer i = 0; i < size; ++i)
261255
{
262256
exprt counter=from_integer(i, counter_type);
263257

@@ -266,7 +260,7 @@ bvt boolbvt::convert_array_comprehension(const array_comprehension_exprt &expr)
266260
const bvt &tmp = convert_bv(body);
267261

268262
INVARIANT(
269-
*size * tmp.size() == width,
263+
size * tmp.size() == width,
270264
"total bitvector width shall equal the number of operands times the size "
271265
"per operand");
272266

@@ -521,12 +515,12 @@ bool boolbvt::is_unbounded_array(const typet &type) const
521515
if(unbounded_array==unbounded_arrayt::U_ALL)
522516
return true;
523517

524-
const std::size_t size = boolbv_width(type);
525-
if(size == 0)
518+
const auto &size_opt = bv_width.get_width_opt(type);
519+
if(!size_opt.has_value())
526520
return true;
527521

528522
if(unbounded_array==unbounded_arrayt::U_AUTO)
529-
if(size > MAX_FLATTENED_ARRAY_SIZE)
523+
if(*size_opt > MAX_FLATTENED_ARRAY_SIZE)
530524
return true;
531525

532526
return false;

Diff for: src/solvers/flattening/boolbv_abs.cpp

-5
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ Author: Daniel Kroening, [email protected]
1616

1717
bvt boolbvt::convert_abs(const abs_exprt &expr)
1818
{
19-
const std::size_t width = boolbv_width(expr.type());
20-
21-
if(width==0)
22-
return conversion_failed(expr);
23-
2419
const bvt &op_bv=convert_bv(expr.op());
2520

2621
if(expr.op().type()!=expr.type())

Diff for: src/solvers/flattening/boolbv_add_sub.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ bvt boolbvt::convert_add_sub(const exprt &expr)
3232

3333
std::size_t width=boolbv_width(type);
3434

35-
if(width==0)
36-
return conversion_failed(expr);
37-
3835
const exprt::operandst &operands=expr.operands();
3936

4037
DATA_INVARIANT(
@@ -160,9 +157,6 @@ bvt boolbvt::convert_saturating_add_sub(const binary_exprt &expr)
160157

161158
std::size_t width = boolbv_width(type);
162159

163-
if(width == 0)
164-
return conversion_failed(expr);
165-
166160
DATA_INVARIANT(
167161
expr.lhs().type() == type && expr.rhs().type() == type,
168162
"saturating add/sub with mixed types:\n" + expr.pretty());

Diff for: src/solvers/flattening/boolbv_array_of.cpp

+4-15
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,17 @@ bvt boolbvt::convert_array_of(const array_of_exprt &expr)
2424
return conversion_failed(expr);
2525

2626
std::size_t width=boolbv_width(array_type);
27-
28-
if(width==0)
29-
{
30-
// A zero-length array is acceptable;
31-
// an element with unknown size is not.
32-
if(boolbv_width(array_type.element_type()) == 0)
33-
return conversion_failed(expr);
34-
else
35-
return bvt();
36-
}
27+
if(width == 0)
28+
return bvt{};
3729

3830
const exprt &array_size=array_type.size();
3931

40-
const auto size = numeric_cast<mp_integer>(array_size);
41-
42-
if(!size.has_value())
43-
return conversion_failed(expr);
32+
const auto size = numeric_cast_v<mp_integer>(to_constant_expr(array_size));
4433

4534
const bvt &tmp = convert_bv(expr.what());
4635

4736
INVARIANT(
48-
*size * tmp.size() == width,
37+
size * tmp.size() == width,
4938
"total array bit width shall equal the number of elements times the "
5039
"element bit with");
5140

Diff for: src/solvers/flattening/boolbv_bitreverse.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ Author: Michael Tautschnig
1313
bvt boolbvt::convert_bitreverse(const bitreverse_exprt &expr)
1414
{
1515
const std::size_t width = boolbv_width(expr.type());
16-
if(width == 0)
17-
return conversion_failed(expr);
1816

1917
bvt bv = convert_bv(expr.op(), width);
2018

Diff for: src/solvers/flattening/boolbv_bitwise.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ Author: Daniel Kroening, [email protected]
1313
bvt boolbvt::convert_bitwise(const exprt &expr)
1414
{
1515
const std::size_t width = boolbv_width(expr.type());
16-
if(width==0)
17-
return conversion_failed(expr);
1816

1917
if(expr.id()==ID_bitnot)
2018
{

Diff for: src/solvers/flattening/boolbv_case.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ bvt boolbvt::convert_case(const exprt &expr)
1818

1919
std::size_t width=boolbv_width(expr.type());
2020

21-
if(width==0)
22-
return conversion_failed(expr);
23-
2421
// make it free variables
2522
bvt bv = prop.new_variables(width);
2623

Diff for: src/solvers/flattening/boolbv_complex.cpp

-9
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ bvt boolbvt::convert_complex(const complex_exprt &expr)
1414
{
1515
std::size_t width=boolbv_width(expr.type());
1616

17-
if(width==0)
18-
return conversion_failed(expr);
19-
2017
DATA_INVARIANT(
2118
expr.type().id() == ID_complex,
2219
"complex expression shall have complex type");
@@ -41,9 +38,6 @@ bvt boolbvt::convert_complex_real(const complex_real_exprt &expr)
4138
{
4239
std::size_t width=boolbv_width(expr.type());
4340

44-
if(width==0)
45-
return conversion_failed(expr);
46-
4741
bvt bv = convert_bv(expr.op(), width * 2);
4842

4943
bv.resize(width); // chop
@@ -55,9 +49,6 @@ bvt boolbvt::convert_complex_imag(const complex_imag_exprt &expr)
5549
{
5650
std::size_t width=boolbv_width(expr.type());
5751

58-
if(width==0)
59-
return conversion_failed(expr);
60-
6152
bvt bv = convert_bv(expr.op(), width * 2);
6253

6354
bv.erase(bv.begin(), bv.begin()+width);

Diff for: src/solvers/flattening/boolbv_concatenation.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ bvt boolbvt::convert_concatenation(const concatenation_exprt &expr)
1515
{
1616
std::size_t width=boolbv_width(expr.type());
1717

18-
if(width==0)
19-
return conversion_failed(expr);
20-
2118
const exprt::operandst &operands=expr.operands();
2219

2320
DATA_INVARIANT(

Diff for: src/solvers/flattening/boolbv_cond.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ bvt boolbvt::convert_cond(const cond_exprt &expr)
1616

1717
std::size_t width=boolbv_width(expr.type());
1818

19-
if(width==0)
20-
return conversion_failed(expr);
21-
2219
bvt bv;
2320

2421
DATA_INVARIANT(operands.size() >= 2, "cond must have at least two operands");

Diff for: src/solvers/flattening/boolbv_constant.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ bvt boolbvt::convert_constant(const constant_exprt &expr)
1414
{
1515
std::size_t width=boolbv_width(expr.type());
1616

17-
if(width==0)
18-
return conversion_failed(expr);
19-
2017
bvt bv;
2118
bv.resize(width);
2219

Diff for: src/solvers/flattening/boolbv_div.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ bvt boolbvt::convert_div(const div_exprt &expr)
1919

2020
std::size_t width=boolbv_width(expr.type());
2121

22-
if(width==0)
23-
return conversion_failed(expr);
24-
2522
if(expr.op0().type().id()!=expr.type().id() ||
2623
expr.op1().type().id()!=expr.type().id())
2724
return conversion_failed(expr);

Diff for: src/solvers/flattening/boolbv_extractbits.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ bvt boolbvt::convert_extractbits(const extractbits_exprt &expr)
1515
{
1616
const std::size_t bv_width = boolbv_width(expr.type());
1717

18-
if(bv_width == 0)
19-
return conversion_failed(expr);
20-
2118
auto const &src_bv = convert_bv(expr.src());
2219

2320
auto const maybe_upper_as_int = numeric_cast<mp_integer>(expr.upper());

Diff for: src/solvers/flattening/boolbv_get.cpp

+26-20
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,9 @@ exprt boolbvt::bv_get_rec(
4848
std::size_t offset,
4949
const typet &type) const
5050
{
51-
std::size_t width=boolbv_width(type);
52-
53-
assert(bv.size()>=offset+width);
54-
5551
if(type.id()==ID_bool)
5652
{
53+
PRECONDITION(bv.size() > offset);
5754
// clang-format off
5855
switch(prop.l_get(bv[offset]).get_value())
5956
{
@@ -76,10 +73,14 @@ exprt boolbvt::bv_get_rec(
7673
return bv_get_unbounded_array(expr);
7774

7875
const typet &subtype = array_type.element_type();
79-
std::size_t sub_width=boolbv_width(subtype);
76+
const auto &sub_width_opt = bv_width.get_width_opt(subtype);
8077

81-
if(sub_width!=0)
78+
if(sub_width_opt.has_value() && *sub_width_opt > 0)
8279
{
80+
const std::size_t width = boolbv_width(type);
81+
82+
std::size_t sub_width = *sub_width_opt;
83+
8384
exprt::operandst op;
8485
op.reserve(width/sub_width);
8586

@@ -131,9 +132,7 @@ exprt boolbvt::bv_get_rec(
131132
const member_exprt member{expr, c.get_name(), subtype};
132133
op.push_back(bv_get_rec(member, bv, offset + new_offset, subtype));
133134

134-
std::size_t sub_width = boolbv_width(subtype);
135-
if(sub_width!=0)
136-
new_offset+=sub_width;
135+
new_offset += boolbv_width(subtype);
137136
}
138137

139138
return struct_exprt(std::move(op), type);
@@ -160,9 +159,12 @@ exprt boolbvt::bv_get_rec(
160159
}
161160
else if(type.id()==ID_vector)
162161
{
162+
const std::size_t width = boolbv_width(type);
163+
163164
const auto &vector_type = to_vector_type(type);
164165
const typet &element_type = vector_type.element_type();
165166
std::size_t element_width = boolbv_width(element_type);
167+
CHECK_RETURN(element_width > 0);
166168

167169
if(element_width != 0 && width % element_width == 0)
168170
{
@@ -183,21 +185,25 @@ exprt boolbvt::bv_get_rec(
183185
}
184186
else if(type.id()==ID_complex)
185187
{
186-
const typet &subtype = to_complex_type(type).subtype();
187-
std::size_t sub_width=boolbv_width(subtype);
188+
const std::size_t width = boolbv_width(type);
188189

189-
if(sub_width!=0 && width==sub_width*2)
190-
{
191-
const complex_exprt value(
192-
bv_get_rec(complex_real_exprt{expr}, bv, 0 * sub_width, subtype),
193-
bv_get_rec(complex_imag_exprt{expr}, bv, 1 * sub_width, subtype),
194-
to_complex_type(type));
195-
196-
return value;
197-
}
190+
const typet &subtype = to_complex_type(type).subtype();
191+
const std::size_t sub_width = boolbv_width(subtype);
192+
CHECK_RETURN(sub_width > 0);
193+
DATA_INVARIANT(
194+
width == sub_width * 2,
195+
"complex type has two elements of equal bit width");
196+
197+
return complex_exprt{
198+
bv_get_rec(complex_real_exprt{expr}, bv, 0 * sub_width, subtype),
199+
bv_get_rec(complex_imag_exprt{expr}, bv, 1 * sub_width, subtype),
200+
to_complex_type(type)};
198201
}
199202
}
200203

204+
const std::size_t width = boolbv_width(type);
205+
PRECONDITION(bv.size() >= offset + width);
206+
201207
// most significant bit first
202208
std::string value;
203209

Diff for: src/solvers/flattening/boolbv_index.cpp

+9-13
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,6 @@ bvt boolbvt::convert_index(const index_exprt &expr)
3434
const array_typet &array_type=
3535
to_array_type(array_op_type);
3636

37-
std::size_t width=boolbv_width(expr.type());
38-
39-
if(width==0)
40-
return conversion_failed(expr);
41-
4237
// see if the array size is constant
4338

4439
if(is_unbounded_array(array_type))
@@ -57,9 +52,11 @@ bvt boolbvt::convert_index(const index_exprt &expr)
5752
if(
5853
final_array.id() == ID_symbol || final_array.id() == ID_nondet_symbol)
5954
{
60-
std::size_t width = boolbv_width(array_type);
55+
const auto &array_width_opt = bv_width.get_width_opt(array_type);
6156
(void)map.get_literals(
62-
final_array.get(ID_identifier), array_type, width);
57+
final_array.get(ID_identifier),
58+
array_type,
59+
array_width_opt.value_or(0));
6360
}
6461

6562
// make sure we have the index in the cache
@@ -68,15 +65,16 @@ bvt boolbvt::convert_index(const index_exprt &expr)
6865
else
6966
{
7067
// free variables
71-
bv = prop.new_variables(width);
68+
bv = prop.new_variables(boolbv_width(expr.type()));
7269

7370
record_array_index(expr);
7471

7572
// record type if array is a symbol
7673
if(array.id() == ID_symbol || array.id() == ID_nondet_symbol)
7774
{
78-
std::size_t width = boolbv_width(array_type);
79-
(void)map.get_literals(array.get(ID_identifier), array_type, width);
75+
const auto &array_width_opt = bv_width.get_width_opt(array_type);
76+
(void)map.get_literals(
77+
array.get(ID_identifier), array_type, array_width_opt.value_or(0));
8078
}
8179

8280
// make sure we have the index in the cache
@@ -208,6 +206,7 @@ bvt boolbvt::convert_index(const index_exprt &expr)
208206
// one or more of the above encoding strategies.
209207

210208
// get literals for the whole array
209+
const std::size_t width = boolbv_width(expr.type());
211210

212211
const bvt &array_bv =
213212
convert_bv(array, numeric_cast_v<std::size_t>(array_size * width));
@@ -290,9 +289,6 @@ bvt boolbvt::convert_index(
290289

291290
std::size_t width = boolbv_width(array_type.element_type());
292291

293-
if(width==0)
294-
return conversion_failed(array);
295-
296292
// TODO: If the underlying array can use one of the
297293
// improvements given above then it may be better to use
298294
// the array theory for short chains of updates and then

0 commit comments

Comments
 (0)