Skip to content

Commit 24c825a

Browse files
authored
Merge pull request #7020 from tautschnig/bugfixes/typed-bv_get_rec
bv_get_rec: ensure all expressions are properly typed
2 parents b4a2ab0 + e90aeb3 commit 24c825a

File tree

6 files changed

+65
-49
lines changed

6 files changed

+65
-49
lines changed
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
struct S
2+
{
3+
int x;
4+
};
5+
6+
int main()
7+
{
8+
unsigned size;
9+
__CPROVER_assume(size > 0);
10+
struct S array[size];
11+
__CPROVER_assert(array[0].x == 0, "not always zero");
12+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--trace
4+
^VERIFICATION FAILED$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
--
8+
^Invariant check failed
9+
--
10+
This test requires that bv_get_rec always uses properly typed expressions.

src/solvers/flattening/boolbv.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,8 @@ class boolbvt:public arrayst
243243

244244
virtual exprt bv_get_unbounded_array(const exprt &) const;
245245

246-
virtual exprt bv_get_rec(
247-
const exprt &expr,
248-
const bvt &bv,
249-
std::size_t offset,
250-
const typet &type) const;
246+
virtual exprt
247+
bv_get_rec(const exprt &expr, const bvt &bv, std::size_t offset) const;
251248

252249
exprt bv_get(const bvt &bv, const typet &type) const;
253250
exprt bv_get_cache(const exprt &expr) const;

src/solvers/flattening/boolbv_get.cpp

+36-39
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ Author: Daniel Kroening, [email protected]
66
77
\*******************************************************************/
88

9-
#include "boolbv.h"
10-
119
#include <util/arith_tools.h>
1210
#include <util/c_types.h>
1311
#include <util/namespace.h>
1412
#include <util/simplify_expr.h>
1513
#include <util/std_expr.h>
1614
#include <util/threeval.h>
1715

16+
#include "boolbv.h"
1817
#include "boolbv_type.h"
1918

19+
#include <iostream>
20+
2021
exprt boolbvt::get(const exprt &expr) const
2122
{
2223
if(expr.id()==ID_symbol ||
@@ -33,21 +34,26 @@ exprt boolbvt::get(const exprt &expr) const
3334
// the value of clock symbols, which do not have a fixed type as the clock
3435
// type is computed during symbolic execution) or match the type stored in
3536
// the mapping
36-
PRECONDITION(expr.type() == typet() || expr.type() == map_entry.type);
37-
38-
return bv_get_rec(expr, map_entry.literal_map, 0, map_entry.type);
37+
if(expr.type() == map_entry.type)
38+
return bv_get_rec(expr, map_entry.literal_map, 0);
39+
else
40+
{
41+
PRECONDITION(expr.type() == typet{});
42+
exprt skeleton = expr;
43+
skeleton.type() = map_entry.type;
44+
return bv_get_rec(skeleton, map_entry.literal_map, 0);
45+
}
3946
}
4047
}
4148

4249
return SUB::get(expr);
4350
}
4451

45-
exprt boolbvt::bv_get_rec(
46-
const exprt &expr,
47-
const bvt &bv,
48-
std::size_t offset,
49-
const typet &type) const
52+
exprt boolbvt::bv_get_rec(const exprt &expr, const bvt &bv, std::size_t offset)
53+
const
5054
{
55+
const typet &type = expr.type();
56+
5157
if(type.id()==ID_bool)
5258
{
5359
PRECONDITION(bv.size() > offset);
@@ -91,7 +97,7 @@ exprt boolbvt::bv_get_rec(
9197
const index_exprt index{
9298
expr,
9399
from_integer(new_offset / sub_width, array_type.index_type())};
94-
op.push_back(bv_get_rec(index, bv, offset + new_offset, subtype));
100+
op.push_back(bv_get_rec(index, bv, offset + new_offset));
95101
}
96102

97103
exprt dest=exprt(ID_array, type);
@@ -103,24 +109,12 @@ exprt boolbvt::bv_get_rec(
103109
return array_exprt{{}, array_type};
104110
}
105111
}
106-
else if(type.id()==ID_struct_tag)
107-
{
108-
exprt result =
109-
bv_get_rec(expr, bv, offset, ns.follow_tag(to_struct_tag_type(type)));
110-
result.type() = type;
111-
return result;
112-
}
113-
else if(type.id()==ID_union_tag)
114-
{
115-
exprt result =
116-
bv_get_rec(expr, bv, offset, ns.follow_tag(to_union_tag_type(type)));
117-
result.type() = type;
118-
return result;
119-
}
120-
else if(type.id()==ID_struct)
112+
else if(type.id() == ID_struct || type.id() == ID_struct_tag)
121113
{
122-
const struct_typet &struct_type=to_struct_type(type);
123-
const struct_typet::componentst &components=struct_type.components();
114+
const struct_typet::componentst &components =
115+
type.id() == ID_struct
116+
? to_struct_type(type).components()
117+
: ns.follow_tag(to_struct_tag_type(type)).components();
124118
std::size_t new_offset=0;
125119
exprt::operandst op;
126120
op.reserve(components.size());
@@ -130,17 +124,19 @@ exprt boolbvt::bv_get_rec(
130124
const typet &subtype = c.type();
131125

132126
const member_exprt member{expr, c.get_name(), subtype};
133-
op.push_back(bv_get_rec(member, bv, offset + new_offset, subtype));
127+
op.push_back(bv_get_rec(member, bv, offset + new_offset));
134128

135129
new_offset += boolbv_width(subtype);
136130
}
137131

138132
return struct_exprt(std::move(op), type);
139133
}
140-
else if(type.id()==ID_union)
134+
else if(type.id() == ID_union || type.id() == ID_union_tag)
141135
{
142-
const union_typet &union_type=to_union_type(type);
143-
const union_typet::componentst &components=union_type.components();
136+
const union_typet::componentst &components =
137+
type.id() == ID_union
138+
? to_union_type(type).components()
139+
: ns.follow_tag(to_union_tag_type(type)).components();
144140

145141
if(components.empty())
146142
return empty_union_exprt(type);
@@ -154,8 +150,8 @@ exprt boolbvt::bv_get_rec(
154150
expr, components[component_nr].get_name(), subtype};
155151
return union_exprt(
156152
components[component_nr].get_name(),
157-
bv_get_rec(member, bv, offset, subtype),
158-
union_type);
153+
bv_get_rec(member, bv, offset),
154+
type);
159155
}
160156
else if(type.id()==ID_vector)
161157
{
@@ -176,8 +172,7 @@ exprt boolbvt::bv_get_rec(
176172
{
177173
const index_exprt index{expr,
178174
from_integer(i, vector_type.index_type())};
179-
value.operands().push_back(
180-
bv_get_rec(index, bv, i * element_width, element_type));
175+
value.operands().push_back(bv_get_rec(index, bv, i * element_width));
181176
}
182177

183178
return std::move(value);
@@ -195,8 +190,8 @@ exprt boolbvt::bv_get_rec(
195190
"complex type has two elements of equal bit width");
196191

197192
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),
193+
bv_get_rec(complex_real_exprt{expr}, bv, 0 * sub_width),
194+
bv_get_rec(complex_imag_exprt{expr}, bv, 1 * sub_width),
200195
to_complex_type(type)};
201196
}
202197
}
@@ -274,7 +269,9 @@ exprt boolbvt::bv_get_rec(
274269

275270
exprt boolbvt::bv_get(const bvt &bv, const typet &type) const
276271
{
277-
return bv_get_rec(nil_exprt{}, bv, 0, type);
272+
nil_exprt skeleton;
273+
skeleton.type() = type;
274+
return bv_get_rec(skeleton, bv, 0);
278275
}
279276

280277
exprt boolbvt::bv_get_cache(const exprt &expr) const

src/solvers/flattening/bv_pointers.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -769,11 +769,12 @@ static std::string bits_to_string(const propt &prop, const bvt &bv)
769769
exprt bv_pointerst::bv_get_rec(
770770
const exprt &expr,
771771
const bvt &bv,
772-
std::size_t offset,
773-
const typet &type) const
772+
std::size_t offset) const
774773
{
774+
const typet &type = expr.type();
775+
775776
if(type.id() != ID_pointer)
776-
return SUB::bv_get_rec(expr, bv, offset, type);
777+
return SUB::bv_get_rec(expr, bv, offset);
777778

778779
const pointer_typet &pt = to_pointer_type(type);
779780
const std::size_t bits = boolbv_width(pt);

src/solvers/flattening/bv_pointers.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ class bv_pointerst:public boolbvt
5252
bvt convert_bitvector(const exprt &) override; // no cache
5353

5454
exprt
55-
bv_get_rec(const exprt &, const bvt &, std::size_t offset, const typet &)
56-
const override;
55+
bv_get_rec(const exprt &, const bvt &, std::size_t offset) const override;
5756

5857
NODISCARD
5958
optionalt<bvt> convert_address_of_rec(const exprt &);

0 commit comments

Comments
 (0)