Skip to content

Commit f7e224b

Browse files
authored
Merge pull request #2897 from danpoe/refactor/error-handling-cleanup-solvers-flattening
Error handling cleanup in solvers/flattening
2 parents bc4503d + 77e1b6c commit f7e224b

14 files changed

+139
-125
lines changed

src/solvers/flattening/boolbv.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ bool boolbvt::literal(
110110
throw "found no literal for expression";
111111
}
112112

113-
const bvt &boolbvt::convert_bv(const exprt &expr)
113+
const bvt &
114+
boolbvt::convert_bv(const exprt &expr, optionalt<std::size_t> expected_width)
114115
{
115116
// check cache first
116117
std::pair<bv_cachet::iterator, bool> cache_result=
@@ -123,18 +124,27 @@ const bvt &boolbvt::convert_bv(const exprt &expr)
123124
// Iterators into hash_maps supposedly stay stable
124125
// even though we are inserting more elements recursively.
125126

126-
cache_result.first->second=convert_bitvector(expr);
127+
const bvt &bv = convert_bitvector(expr);
128+
129+
INVARIANT_WITH_DIAGNOSTICS(
130+
!expected_width || bv.size() == *expected_width,
131+
"bitvector width shall match the indicated expected width",
132+
expr.find_source_location(),
133+
irep_pretty_diagnosticst(expr));
134+
135+
cache_result.first->second = bv;
127136

128137
// check
129138
forall_literals(it, cache_result.first->second)
130139
{
131140
if(freeze_all && !it->is_constant())
132141
prop.set_frozen(*it);
133-
if(it->var_no()==literalt::unused_var_no())
134-
{
135-
error() << "unused_var_no: " << expr.pretty() << eom;
136-
assert(false);
137-
}
142+
143+
INVARIANT_WITH_DIAGNOSTICS(
144+
it->var_no() != literalt::unused_var_no(),
145+
"variable number must be different from the unused variable number",
146+
expr.find_source_location(),
147+
irep_pretty_diagnosticst(expr));
138148
}
139149

140150
return cache_result.first->second;
@@ -231,7 +241,7 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
231241
else if(expr.id()==ID_floatbv_typecast)
232242
return convert_floatbv_typecast(to_floatbv_typecast_expr(expr));
233243
else if(expr.id()==ID_concatenation)
234-
return convert_concatenation(expr);
244+
return convert_concatenation(to_concatenation_expr(expr));
235245
else if(expr.id()==ID_replication)
236246
return convert_replication(to_replication_expr(expr));
237247
else if(expr.id()==ID_extractbits)
@@ -273,7 +283,7 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
273283
else if(expr.id()==ID_vector)
274284
return convert_vector(expr);
275285
else if(expr.id()==ID_complex)
276-
return convert_complex(expr);
286+
return convert_complex(to_complex_expr(expr));
277287
else if(expr.id()==ID_complex_real)
278288
return convert_complex_real(to_complex_real_expr(expr));
279289
else if(expr.id()==ID_complex_imag)

src/solvers/flattening/boolbv.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ Author: Daniel Kroening, [email protected]
1414
// convert expression to boolean formula
1515
//
1616

17-
#include <util/mp_arith.h>
18-
#include <util/expr.h>
1917
#include <util/byte_operators.h>
18+
#include <util/expr.h>
19+
#include <util/mp_arith.h>
20+
#include <util/optional.h>
2021

2122
#include "bv_utils.h"
2223
#include "boolbv_width.h"
@@ -43,7 +44,10 @@ class boolbvt:public arrayst
4344
{
4445
}
4546

46-
virtual const bvt &convert_bv(const exprt &expr); // check cache
47+
virtual const bvt &convert_bv( // check cache
48+
const exprt &expr,
49+
const optionalt<std::size_t> expected_width = nullopt);
50+
4751
virtual bvt convert_bitvector(const exprt &expr); // no cache
4852

4953
// overloading
@@ -139,7 +143,7 @@ class boolbvt:public arrayst
139143
virtual bvt convert_struct(const struct_exprt &expr);
140144
virtual bvt convert_array(const exprt &expr);
141145
virtual bvt convert_vector(const exprt &expr);
142-
virtual bvt convert_complex(const exprt &expr);
146+
virtual bvt convert_complex(const complex_exprt &expr);
143147
virtual bvt convert_complex_real(const complex_real_exprt &expr);
144148
virtual bvt convert_complex_imag(const complex_imag_exprt &expr);
145149
virtual bvt convert_lambda(const exprt &expr);
@@ -162,7 +166,7 @@ class boolbvt:public arrayst
162166
virtual bvt convert_bitwise(const exprt &expr);
163167
virtual bvt convert_unary_minus(const unary_exprt &expr);
164168
virtual bvt convert_abs(const abs_exprt &expr);
165-
virtual bvt convert_concatenation(const exprt &expr);
169+
virtual bvt convert_concatenation(const concatenation_exprt &expr);
166170
virtual bvt convert_replication(const replication_exprt &expr);
167171
virtual bvt convert_bv_literals(const exprt &expr);
168172
virtual bvt convert_constant(const constant_exprt &expr);

src/solvers/flattening/boolbv_add_sub.cpp

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ Author: Daniel Kroening, [email protected]
1515

1616
bvt boolbvt::convert_add_sub(const exprt &expr)
1717
{
18+
PRECONDITION(
19+
expr.id() == ID_plus || expr.id() == ID_minus ||
20+
expr.id() == "no-overflow-plus" || expr.id() == "no-overflow-minus");
21+
1822
const typet &type=ns.follow(expr.type());
1923

2024
if(type.id()!=ID_unsignedbv &&
@@ -33,17 +37,15 @@ bvt boolbvt::convert_add_sub(const exprt &expr)
3337

3438
const exprt::operandst &operands=expr.operands();
3539

36-
if(operands.empty())
37-
throw "operator "+expr.id_string()+" takes at least one operand";
40+
DATA_INVARIANT(
41+
!operands.empty(),
42+
"operator " + expr.id_string() + " takes at least one operand");
3843

3944
const exprt &op0=expr.op0();
4045
DATA_INVARIANT(
4146
op0.type() == type, "add/sub with mixed types:\n" + expr.pretty());
4247

43-
bvt bv=convert_bv(op0);
44-
45-
if(bv.size()!=width)
46-
throw "convert_add_sub: unexpected operand 0 width";
48+
bvt bv = convert_bv(op0, width);
4749

4850
bool subtract=(expr.id()==ID_minus ||
4951
expr.id()=="no-overflow-minus");
@@ -67,19 +69,16 @@ bvt boolbvt::convert_add_sub(const exprt &expr)
6769
DATA_INVARIANT(
6870
it->type() == type, "add/sub with mixed types:\n" + expr.pretty());
6971

70-
const bvt &op=convert_bv(*it);
71-
72-
if(op.size()!=width)
73-
throw "convert_add_sub: unexpected operand width";
72+
const bvt &op = convert_bv(*it, width);
7473

7574
if(type.id()==ID_vector || type.id()==ID_complex)
7675
{
77-
const typet &subtype=ns.follow(type.subtype());
78-
79-
std::size_t sub_width=boolbv_width(subtype);
76+
std::size_t sub_width = boolbv_width(type.subtype());
8077

81-
if(sub_width==0 || width%sub_width!=0)
82-
throw "convert_add_sub: unexpected vector operand width";
78+
INVARIANT(sub_width != 0, "vector elements shall have nonzero bit width");
79+
INVARIANT(
80+
width % sub_width == 0,
81+
"total vector bit width shall be a multiple of the element bit width");
8382

8483
std::size_t size=width/sub_width;
8584
bv.resize(width);
@@ -91,34 +90,39 @@ bvt boolbvt::convert_add_sub(const exprt &expr)
9190

9291
for(std::size_t j=0; j<tmp_op.size(); j++)
9392
{
94-
assert(i*sub_width+j<op.size());
95-
tmp_op[j]=op[i*sub_width+j];
93+
const std::size_t index = i * sub_width + j;
94+
INVARIANT(index < op.size(), "bit index shall be within bounds");
95+
tmp_op[j] = op[index];
9696
}
9797

9898
bvt tmp_result;
9999
tmp_result.resize(sub_width);
100100

101101
for(std::size_t j=0; j<tmp_result.size(); j++)
102102
{
103-
assert(i*sub_width+j<bv.size());
104-
tmp_result[j]=bv[i*sub_width+j];
103+
const std::size_t index = i * sub_width + j;
104+
INVARIANT(index < bv.size(), "bit index shall be within bounds");
105+
tmp_result[j] = bv[index];
105106
}
106107

107108
if(type.subtype().id()==ID_floatbv)
108109
{
109110
// needs to change due to rounding mode
110-
float_utilst float_utils(prop, to_floatbv_type(subtype));
111+
float_utilst float_utils(prop, to_floatbv_type(type.subtype()));
111112
tmp_result=float_utils.add_sub(tmp_result, tmp_op, subtract);
112113
}
113114
else
114115
tmp_result=bv_utils.add_sub(tmp_result, tmp_op, subtract);
115116

116-
assert(tmp_result.size()==sub_width);
117+
INVARIANT(
118+
tmp_result.size() == sub_width,
119+
"applying the add/sub operation shall not change the bitwidth");
117120

118121
for(std::size_t j=0; j<tmp_result.size(); j++)
119122
{
120-
assert(i*sub_width+j<bv.size());
121-
bv[i*sub_width+j]=tmp_result[j];
123+
const std::size_t index = i * sub_width + j;
124+
INVARIANT(index < bv.size(), "bit index shall be within bounds");
125+
bv[index] = tmp_result[j];
122126
}
123127
}
124128
}

src/solvers/flattening/boolbv_array.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ Author: Daniel Kroening, [email protected]
66
77
\*******************************************************************/
88

9-
109
#include "boolbv.h"
1110

11+
#include <util/invariant.h>
12+
1213
bvt boolbvt::convert_array(const exprt &expr)
1314
{
1415
std::size_t width=boolbv_width(expr.type());
@@ -18,20 +19,19 @@ bvt boolbvt::convert_array(const exprt &expr)
1819

1920
if(expr.type().id()==ID_array)
2021
{
21-
assert(expr.has_operands());
22+
DATA_INVARIANT(
23+
expr.has_operands(),
24+
"the bit width being nonzero implies that the array has a nonzero size "
25+
"in which case the array shall have operands");
2226
const exprt::operandst &operands=expr.operands();
23-
assert(!operands.empty());
2427
std::size_t op_width=width/operands.size();
2528

2629
bvt bv;
2730
bv.reserve(width);
2831

2932
forall_expr(it, operands)
3033
{
31-
const bvt &tmp=convert_bv(*it);
32-
33-
if(tmp.size()!=op_width)
34-
throw "convert_array: unexpected operand width";
34+
const bvt &tmp = convert_bv(*it, op_width);
3535

3636
forall_literals(it2, tmp)
3737
bv.push_back(*it2);

src/solvers/flattening/boolbv_array_of.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ Author: Daniel Kroening, [email protected]
99
#include "boolbv.h"
1010

1111
#include <util/arith_tools.h>
12+
#include <util/invariant.h>
1213
#include <util/std_types.h>
1314

1415
bvt boolbvt::convert_array_of(const array_of_exprt &expr)
1516
{
16-
if(expr.type().id()!=ID_array)
17-
throw "array_of must be array-typed";
17+
DATA_INVARIANT(
18+
expr.type().id() == ID_array, "array_of expression shall have array type");
1819

1920
const array_typet &array_type=to_array_type(expr.type());
2021

@@ -42,21 +43,25 @@ bvt boolbvt::convert_array_of(const array_of_exprt &expr)
4243

4344
const bvt &tmp=convert_bv(expr.op0());
4445

46+
INVARIANT(
47+
size * tmp.size() == width,
48+
"total array bit width shall equal the number of elements times the "
49+
"element bit with");
50+
4551
bvt bv;
4652
bv.resize(width);
4753

48-
if(size*tmp.size()!=width)
49-
throw "convert_array_of: unexpected operand width";
50-
51-
std::size_t offset=0;
54+
auto b_it = tmp.begin();
5255

53-
for(mp_integer i=0; i<size; i=i+1)
56+
for(auto &b : bv)
5457
{
55-
for(std::size_t j=0; j<tmp.size(); j++, offset++)
56-
bv[offset]=tmp[j];
57-
}
58+
b = *b_it;
5859

59-
assert(offset==bv.size());
60+
b_it++;
61+
62+
if(b_it == tmp.end())
63+
b_it = tmp.begin();
64+
}
6065

6166
return bv;
6267
}

src/solvers/flattening/boolbv_bitwise.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ bvt boolbvt::convert_bitwise(const exprt &expr)
1919
{
2020
DATA_INVARIANT(expr.operands().size() == 1, "bitnot takes one operand");
2121
const exprt &op0=expr.op0();
22-
const bvt &op_bv=convert_bv(op0);
23-
CHECK_RETURN(op_bv.size() == width);
22+
const bvt &op_bv = convert_bv(op0, width);
2423
return bv_utils.inverted(op_bv);
2524
}
2625
else if(expr.id()==ID_bitand || expr.id()==ID_bitor ||
@@ -33,8 +32,7 @@ bvt boolbvt::convert_bitwise(const exprt &expr)
3332

3433
forall_operands(it, expr)
3534
{
36-
const bvt &op=convert_bv(*it);
37-
CHECK_RETURN(op.size() == width);
35+
const bvt &op = convert_bv(*it, width);
3836

3937
if(it==expr.operands().begin())
4038
bv=op;

src/solvers/flattening/boolbv_bswap.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ bvt boolbvt::convert_bswap(const bswap_exprt &expr)
1919
if(width % byte_bits != 0)
2020
return conversion_failed(expr);
2121

22-
bvt result = convert_bv(expr.op());
23-
CHECK_RETURN(result.size() == width);
22+
bvt result = convert_bv(expr.op(), width);
2423

2524
std::size_t dest_base = width;
2625

src/solvers/flattening/boolbv_byte_update.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,16 @@ Author: Daniel Kroening, [email protected]
99
#include "boolbv.h"
1010

1111
#include <iostream>
12-
#include <cassert>
1312

1413
#include <util/arith_tools.h>
1514
#include <util/byte_operators.h>
15+
#include <util/invariant.h>
1616

1717
#include "bv_endianness_map.h"
1818

1919
bvt boolbvt::convert_byte_update(const byte_update_exprt &expr)
2020
{
21-
if(expr.operands().size()!=3)
22-
throw "byte_update takes three operands";
23-
24-
const exprt &op=expr.op0();
21+
const exprt &op = expr.op();
2522
const exprt &offset_expr=expr.offset();
2623
const exprt &value=expr.value();
2724

@@ -70,8 +67,11 @@ bvt boolbvt::convert_byte_update(const byte_update_exprt &expr)
7067
size_t index_op=map_op.map_bit(offset_i+i);
7168
size_t index_value=map_value.map_bit(i);
7269

73-
assert(index_op<bv.size());
74-
assert(index_value<value_bv.size());
70+
INVARIANT(
71+
index_op < bv.size(), "bit vector index shall be within bounds");
72+
INVARIANT(
73+
index_value < value_bv.size(),
74+
"bit vector index shall be within bounds");
7575

7676
bv[index_op]=value_bv[index_value];
7777
}

0 commit comments

Comments
 (0)