Skip to content

Commit b9a0781

Browse files
committed
Error handling cleanup in solvers/flattening
1 parent 3f5847c commit b9a0781

12 files changed

+124
-80
lines changed

src/solvers/flattening/boolbv.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ bool boolbvt::literal(
113113
throw "found no literal for expression";
114114
}
115115

116-
const bvt &boolbvt::convert_bv(const exprt &expr)
116+
const bvt &boolbvt::convert_bv(
117+
const exprt &expr,
118+
optionalt<std::size_t> expected_width)
117119
{
118120
// check cache first
119121
std::pair<bv_cachet::iterator, bool> cache_result=
@@ -126,18 +128,21 @@ const bvt &boolbvt::convert_bv(const exprt &expr)
126128
// Iterators into hash_maps supposedly stay stable
127129
// even though we are inserting more elements recursively.
128130

129-
cache_result.first->second=convert_bitvector(expr);
131+
const bvt &bv = convert_bitvector(expr);
132+
CHECK_RETURN(!expected_width || bv.size() == *expected_width);
133+
134+
cache_result.first->second = bv;
130135

131136
// check
132137
forall_literals(it, cache_result.first->second)
133138
{
134139
if(freeze_all && !it->is_constant())
135140
prop.set_frozen(*it);
136-
if(it->var_no()==literalt::unused_var_no())
137-
{
138-
error() << "unused_var_no: " << expr.pretty() << eom;
139-
assert(false);
140-
}
141+
142+
INVARIANT(
143+
it->var_no() != literalt::unused_var_no(),
144+
"variable number must be different from the unused variable number",
145+
expr.pretty());
141146
}
142147

143148
return cache_result.first->second;

src/solvers/flattening/boolbv.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Author: Daniel Kroening, [email protected]
1717
#include <util/mp_arith.h>
1818
#include <util/expr.h>
1919
#include <util/byte_operators.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

src/solvers/flattening/boolbv_add_sub.cpp

Lines changed: 28 additions & 22 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,18 @@ 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());
76+
//const typet &subtype=ns.follow(type.subtype());
7877

79-
std::size_t sub_width=boolbv_width(subtype);
78+
std::size_t sub_width=boolbv_width(type.subtype());
8079

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

8485
std::size_t size=width/sub_width;
8586
bv.resize(width);
@@ -91,34 +92,39 @@ bvt boolbvt::convert_add_sub(const exprt &expr)
9192

9293
for(std::size_t j=0; j<tmp_op.size(); j++)
9394
{
94-
assert(i*sub_width+j<op.size());
95-
tmp_op[j]=op[i*sub_width+j];
95+
const std::size_t index = i * sub_width + j;
96+
INVARIANT(index < op.size(), "bit index shall be within bounds");
97+
tmp_op[j] = op[index];
9698
}
9799

98100
bvt tmp_result;
99101
tmp_result.resize(sub_width);
100102

101103
for(std::size_t j=0; j<tmp_result.size(); j++)
102104
{
103-
assert(i*sub_width+j<bv.size());
104-
tmp_result[j]=bv[i*sub_width+j];
105+
const std::size_t index = i * sub_width + j;
106+
INVARIANT(index < bv.size(), "bit index shall be within bounds");
107+
tmp_result[j] = bv[index];
105108
}
106109

107110
if(type.subtype().id()==ID_floatbv)
108111
{
109112
// needs to change due to rounding mode
110-
float_utilst float_utils(prop, to_floatbv_type(subtype));
113+
float_utilst float_utils(prop, to_floatbv_type(type.subtype()));
111114
tmp_result=float_utils.add_sub(tmp_result, tmp_op, subtract);
112115
}
113116
else
114117
tmp_result=bv_utils.add_sub(tmp_result, tmp_op, subtract);
115118

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

118123
for(std::size_t j=0; j<tmp_result.size(); j++)
119124
{
120-
assert(i*sub_width+j<bv.size());
121-
bv[i*sub_width+j]=tmp_result[j];
125+
const std::size_t index = i * sub_width + j;
126+
INVARIANT(index < bv.size(), "bit index shall be within bounds");
127+
bv[index] = tmp_result[j];
122128
}
123129
}
124130
}

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_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
}

src/solvers/flattening/boolbv_case.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Author: Daniel Kroening, [email protected]
1212

1313
bvt boolbvt::convert_case(const exprt &expr)
1414
{
15+
PRECONDITION(expr.id() == ID_case);
16+
1517
const std::vector<exprt> &operands=expr.operands();
1618

1719
std::size_t width=boolbv_width(expr.type());
@@ -26,11 +28,11 @@ bvt boolbvt::convert_case(const exprt &expr)
2628
Forall_literals(it, bv)
2729
*it=prop.new_variable();
2830

29-
if(operands.size()<3)
30-
throw "case takes at least three operands";
31+
DATA_INVARIANT(
32+
operands.size() >= 3, "case should have at least three operands");
3133

32-
if((operands.size()%2)!=1)
33-
throw "number of case operands must be odd";
34+
DATA_INVARIANT(
35+
operands.size() % 2 == 1, "number of case operands should be odd");
3436

3537
enum { FIRST, COMPARE, VALUE } what=FIRST;
3638
bvt compare_bv;
@@ -81,7 +83,7 @@ bvt boolbvt::convert_case(const exprt &expr)
8183
break;
8284

8385
default:
84-
assert(false);
86+
UNREACHABLE;
8587
}
8688
}
8789

src/solvers/flattening/boolbv_complex.cpp

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

9-
109
#include "boolbv.h"
1110

11+
#include <util/invariant.h>
12+
1213
bvt boolbvt::convert_complex(const exprt &expr)
1314
{
15+
PRECONDITION(expr.id() == ID_complex);
16+
1417
std::size_t width=boolbv_width(expr.type());
1518

1619
if(width==0)
@@ -29,10 +32,7 @@ bvt boolbvt::convert_complex(const exprt &expr)
2932

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

3737
forall_literals(it2, tmp)
3838
bv.push_back(*it2);
@@ -47,6 +47,8 @@ bvt boolbvt::convert_complex(const exprt &expr)
4747

4848
bvt boolbvt::convert_complex_real(const exprt &expr)
4949
{
50+
PRECONDITION(expr.id() == ID_complex_real);
51+
5052
std::size_t width=boolbv_width(expr.type());
5153

5254
if(width==0)
@@ -57,14 +59,16 @@ bvt boolbvt::convert_complex_real(const exprt &expr)
5759

5860
bvt bv=convert_bv(expr.op0());
5961

60-
assert(bv.size()==width*2);
62+
INVARIANT(bv.size() == width * 2, "");
6163
bv.resize(width); // chop
6264

6365
return bv;
6466
}
6567

6668
bvt boolbvt::convert_complex_imag(const exprt &expr)
6769
{
70+
PRECONDITION(expr.id() == ID_complex_imag);
71+
6872
std::size_t width=boolbv_width(expr.type());
6973

7074
if(width==0)
@@ -75,7 +79,7 @@ bvt boolbvt::convert_complex_imag(const exprt &expr)
7579

7680
bvt bv=convert_bv(expr.op0());
7781

78-
assert(bv.size()==width*2);
82+
INVARIANT(bv.size() == width * 2, "");
7983
bv.erase(bv.begin(), bv.begin()+width);
8084

8185
return bv;

0 commit comments

Comments
 (0)