Skip to content

Commit ffe62af

Browse files
authored
Merge pull request #2934 from danpoe/refactor/error-handling-solvers-flattening-from-boolbv-quantifier
Error handling cleanup in solvers/flattening 4
2 parents 771b368 + 44503dd commit ffe62af

9 files changed

+120
-113
lines changed

src/solvers/flattening/boolbv.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,9 +462,9 @@ literalt boolbvt::convert_rest(const exprt &expr)
462462
else if(expr.id()==ID_extractbit)
463463
return convert_extractbit(to_extractbit_expr(expr));
464464
else if(expr.id()==ID_forall)
465-
return convert_quantifier(expr);
465+
return convert_quantifier(to_quantifier_expr(expr));
466466
else if(expr.id()==ID_exists)
467-
return convert_quantifier(expr);
467+
return convert_quantifier(to_quantifier_expr(expr));
468468
else if(expr.id()==ID_let)
469469
{
470470
bvt bv=convert_let(to_let_expr(expr));

src/solvers/flattening/boolbv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class boolbvt:public arrayst
131131
virtual literalt convert_verilog_case_equality(
132132
const binary_relation_exprt &expr);
133133
virtual literalt convert_ieee_float_rel(const exprt &expr);
134-
virtual literalt convert_quantifier(const exprt &expr);
134+
virtual literalt convert_quantifier(const quantifier_exprt &expr);
135135

136136
virtual bvt convert_index(const exprt &array, const mp_integer &index);
137137
virtual bvt convert_index(const index_exprt &expr);

src/solvers/flattening/boolbv_quantifier.cpp

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ Author: Daniel Kroening, [email protected]
88

99
#include "boolbv.h"
1010

11-
#include <cassert>
12-
1311
#include <util/arith_tools.h>
12+
#include <util/invariant.h>
13+
#include <util/optional.h>
1414
#include <util/replace_expr.h>
1515
#include <util/simplify_expr.h>
1616

@@ -32,8 +32,8 @@ exprt get_quantifier_var_min(
3232
const exprt &var_expr,
3333
const exprt &quantifier_expr)
3434
{
35-
assert(quantifier_expr.id()==ID_or ||
36-
quantifier_expr.id()==ID_and);
35+
PRECONDITION(quantifier_expr.id() == ID_or || quantifier_expr.id() == ID_and);
36+
3737
exprt res;
3838
res.make_false();
3939
if(quantifier_expr.id()==ID_or)
@@ -80,8 +80,7 @@ exprt get_quantifier_var_max(
8080
const exprt &var_expr,
8181
const exprt &quantifier_expr)
8282
{
83-
assert(quantifier_expr.id()==ID_or ||
84-
quantifier_expr.id()==ID_and);
83+
PRECONDITION(quantifier_expr.id() == ID_or || quantifier_expr.id() == ID_and);
8584
exprt res;
8685
res.make_false();
8786
if(quantifier_expr.id()==ID_or)
@@ -137,78 +136,74 @@ exprt get_quantifier_var_max(
137136
return res;
138137
}
139138

140-
bool instantiate_quantifier(exprt &expr,
141-
const namespacet &ns)
139+
optionalt<exprt>
140+
instantiate_quantifier(const quantifier_exprt &expr, const namespacet &ns)
142141
{
143-
if(!(expr.id()==ID_forall || expr.id()==ID_exists))
144-
return true;
145-
146-
assert(expr.operands().size()==2);
147-
assert(expr.op0().id()==ID_symbol);
142+
PRECONDITION(expr.id() == ID_forall || expr.id() == ID_exists);
148143

149-
exprt var_expr=expr.op0();
144+
const symbol_exprt &var_expr = expr.symbol();
150145

151146
/**
152147
* We need to rewrite the forall/exists quantifier into
153148
* an OR/AND expr.
154149
**/
155-
exprt re(expr);
156-
exprt tmp(re.op1());
157-
re.swap(tmp);
158-
re=simplify_expr(re, ns);
150+
151+
const exprt &re = simplify_expr(expr.where(), ns);
159152

160153
if(re.is_true() || re.is_false())
161154
{
162-
expr=re;
163-
return true;
155+
return re;
164156
}
165157

166-
exprt min_i=get_quantifier_var_min(var_expr, re);
167-
exprt max_i=get_quantifier_var_max(var_expr, re);
168-
exprt body_expr=re;
169-
if(var_expr.is_false() ||
170-
min_i.is_false() ||
171-
max_i.is_false() ||
172-
body_expr.is_false())
173-
return false;
158+
const exprt &min_i = get_quantifier_var_min(var_expr, re);
159+
const exprt &max_i = get_quantifier_var_max(var_expr, re);
160+
161+
if(min_i.is_false() || max_i.is_false())
162+
return nullopt;
174163

175-
mp_integer lb, ub;
176-
to_integer(min_i, lb);
177-
to_integer(max_i, ub);
164+
mp_integer lb = numeric_cast_v<mp_integer>(min_i);
165+
mp_integer ub = numeric_cast_v<mp_integer>(max_i);
178166

179167
if(lb>ub)
180-
return false;
168+
return nullopt;
181169

182-
bool res=true;
183170
std::vector<exprt> expr_insts;
184171
for(mp_integer i=lb; i<=ub; ++i)
185172
{
186-
exprt constraint_expr=body_expr;
173+
exprt constraint_expr = re;
187174
replace_expr(var_expr,
188175
from_integer(i, var_expr.type()),
189176
constraint_expr);
190177
expr_insts.push_back(constraint_expr);
191178
}
179+
192180
if(expr.id()==ID_forall)
193181
{
194-
expr=conjunction(expr_insts);
182+
return conjunction(expr_insts);
195183
}
196-
if(expr.id()==ID_exists)
184+
else if(expr.id() == ID_exists)
197185
{
198-
expr=disjunction(expr_insts);
186+
return disjunction(expr_insts);
199187
}
200188

201-
return res;
189+
UNREACHABLE;
190+
return nullopt;
202191
}
203192

204-
literalt boolbvt::convert_quantifier(const exprt &src)
193+
literalt boolbvt::convert_quantifier(const quantifier_exprt &src)
205194
{
206-
exprt expr(src);
207-
if(!instantiate_quantifier(expr, ns))
195+
PRECONDITION(src.id() == ID_forall || src.id() == ID_exists);
196+
197+
quantifier_exprt expr(src);
198+
const auto res = instantiate_quantifier(expr, ns);
199+
200+
if(!res)
201+
{
208202
return SUB::convert_rest(src);
203+
}
209204

210205
quantifiert quantifier;
211-
quantifier.expr=expr;
206+
quantifier.expr = *res;
212207
quantifier_list.push_back(quantifier);
213208

214209
literalt l=prop.new_variable();

src/solvers/flattening/boolbv_reduction.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ literalt boolbvt::convert_reduction(const unary_exprt &expr)
1313
{
1414
const bvt &op_bv=convert_bv(expr.op());
1515

16-
if(op_bv.empty())
17-
throw "reduction operators take one non-empty operand";
16+
INVARIANT(
17+
!op_bv.empty(),
18+
"reduction operand bitvector shall have width at least one");
1819

1920
enum { O_OR, O_AND, O_XOR } op;
2021

@@ -27,7 +28,7 @@ literalt boolbvt::convert_reduction(const unary_exprt &expr)
2728
else if(id==ID_reduction_xor || id==ID_reduction_xnor)
2829
op=O_XOR;
2930
else
30-
throw "unexpected reduction operator";
31+
UNREACHABLE;
3132

3233
literalt l=op_bv[0];
3334

@@ -53,8 +54,9 @@ bvt boolbvt::convert_bv_reduction(const unary_exprt &expr)
5354
{
5455
const bvt &op_bv=convert_bv(expr.op());
5556

56-
if(op_bv.empty())
57-
throw "reduction operators take one non-empty operand";
57+
INVARIANT(
58+
!op_bv.empty(),
59+
"reduction operand bitvector shall have width at least one");
5860

5961
enum { O_OR, O_AND, O_XOR } op;
6062

@@ -67,7 +69,7 @@ bvt boolbvt::convert_bv_reduction(const unary_exprt &expr)
6769
else if(id==ID_reduction_xor || id==ID_reduction_xnor)
6870
op=O_XOR;
6971
else
70-
throw "unexpected reduction operator";
72+
UNREACHABLE;
7173

7274
const typet &op_type=expr.op().type();
7375

src/solvers/flattening/boolbv_replication.cpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,29 @@ bvt boolbvt::convert_replication(const replication_exprt &expr)
1717
if(width==0)
1818
return conversion_failed(expr);
1919

20-
mp_integer times;
21-
if(to_integer(expr.op0(), times))
22-
throw "replication takes constant as first parameter";
20+
mp_integer times = numeric_cast_v<mp_integer>(expr.times());
2321

2422
bvt bv;
2523
bv.resize(width);
2624

2725
const std::size_t u_times=integer2unsigned(times);
28-
const bvt &op=convert_bv(expr.op1());
29-
std::size_t offset=0;
26+
const bvt &op = convert_bv(expr.op());
3027

31-
for(std::size_t i=0; i<u_times; i++)
32-
{
33-
if(op.size()+offset>width)
34-
throw "replication operand width too big";
28+
INVARIANT(
29+
op.size() * u_times == bv.size(),
30+
"result bitvector width shall be equal to the operand bitvector width times"
31+
"the number of replications");
3532

36-
for(std::size_t i=0; i<op.size(); i++)
37-
bv[i+offset]=op[i];
33+
std::size_t bit_idx = 0;
3834

39-
offset+=op.size();
35+
for(std::size_t i = 0; i < u_times; i++)
36+
{
37+
for(const auto &bit : op)
38+
{
39+
bv[bit_idx] = bit;
40+
bit_idx++;
41+
}
4042
}
4143

42-
if(offset!=bv.size())
43-
throw "replication operand width too small";
44-
4544
return bv;
4645
}

src/solvers/flattening/boolbv_shift.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,7 @@ bvt boolbvt::convert_shift(const binary_exprt &expr)
3030
if(width==0)
3131
return conversion_failed(expr);
3232

33-
const bvt &op=convert_bv(expr.op0());
34-
35-
if(op.size()!=width)
36-
throw "convert_shift: unexpected operand 0 width";
33+
const bvt &op = convert_bv(expr.op0(), width);
3734

3835
bv_utilst::shiftt shift;
3936

@@ -48,15 +45,13 @@ bvt boolbvt::convert_shift(const binary_exprt &expr)
4845
else if(expr.id()==ID_ror)
4946
shift=bv_utilst::shiftt::ROTATE_RIGHT;
5047
else
51-
throw "unexpected shift operator";
48+
UNREACHABLE;
5249

5350
// we allow a constant as shift distance
5451

5552
if(expr.op1().is_constant())
5653
{
57-
mp_integer i;
58-
if(to_integer(expr.op1(), i))
59-
throw "convert_shift: failed to convert constant";
54+
mp_integer i = numeric_cast_v<mp_integer>(expr.op1());
6055

6156
std::size_t distance;
6257

src/solvers/flattening/boolbv_struct.cpp

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,53 +19,52 @@ bvt boolbvt::convert_struct(const struct_exprt &expr)
1919

2020
const struct_typet::componentst &components=struct_type.components();
2121

22-
if(expr.operands().size()!=components.size())
23-
{
24-
error().source_location=expr.find_source_location();
25-
error() << "struct: wrong number of arguments" << eom;
26-
throw 0;
27-
}
22+
DATA_INVARIANT_WITH_DIAGNOSTICS(
23+
expr.operands().size() == components.size(),
24+
"number of operands of a struct expression shall equal the number of"
25+
"components as indicated by its type",
26+
expr.find_source_location());
2827

2928
bvt bv;
3029
bv.resize(width);
3130

32-
std::size_t offset=0;
31+
std::size_t bit_idx = 0;
3332

3433
exprt::operandst::const_iterator op_it=expr.operands().begin();
3534
for(const auto &comp : components)
3635
{
3736
const typet &subtype=comp.type();
3837
const exprt &op=*op_it;
3938

40-
if(!base_type_eq(subtype, op.type(), ns))
41-
{
42-
error().source_location=expr.find_source_location();
43-
error() << "struct: component type does not match: "
44-
<< subtype.pretty() << " vs. "
45-
<< op.type().pretty() << eom;
46-
throw 0;
47-
}
39+
DATA_INVARIANT_WITH_DIAGNOSTICS(
40+
base_type_eq(subtype, op.type(), ns),
41+
"type of a struct expression operand shall equal the type of the "
42+
"corresponding struct component",
43+
expr.find_source_location(),
44+
subtype.pretty(),
45+
op.type().pretty());
4846

4947
std::size_t subtype_width=boolbv_width(subtype);
5048

5149
if(subtype_width!=0)
5250
{
53-
const bvt &op_bv=convert_bv(op);
54-
55-
assert(offset<width);
56-
assert(op_bv.size()==subtype_width);
57-
assert(offset+op_bv.size()<=width);
51+
const bvt &op_bv = convert_bv(op, subtype_width);
5852

59-
for(std::size_t j=0; j<op_bv.size(); j++)
60-
bv[offset+j]=op_bv[j];
53+
INVARIANT(
54+
bit_idx + op_bv.size() <= width, "bit index shall be within bounds");
6155

62-
offset+=op_bv.size();
56+
for(const auto &bit : op_bv)
57+
{
58+
bv[bit_idx] = bit;
59+
bit_idx++;
60+
}
6361
}
6462

6563
++op_it;
6664
}
6765

68-
assert(offset==width);
66+
INVARIANT(
67+
bit_idx == width, "all bits in the bitvector shall have been assigned");
6968

7069
return bv;
7170
}

0 commit comments

Comments
 (0)