Skip to content

Commit 0c8ef66

Browse files
Daniel Kroeningtautschnig
Daniel Kroening
authored andcommitted
Improve precision of value_set on unions by extending and using the simplifier
1 parent 84170df commit 0c8ef66

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

regression/cbmc/union11/union_list.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <assert.h>
2+
3+
struct list_item
4+
{
5+
struct list_item *previous;
6+
};
7+
8+
struct List
9+
{
10+
unsigned something;
11+
struct list_item *index;
12+
struct list_item end;
13+
};
14+
15+
union U
16+
{
17+
struct List my_list;
18+
};
19+
20+
int main()
21+
{
22+
union U u;
23+
24+
u.my_list.index = &(u.my_list.end);
25+
u.my_list.end.previous = u.my_list.index;
26+
struct list_item *p1 = u.my_list.index;
27+
struct list_item *p2 = p1->previous;
28+
struct list_item *p3 = p2->previous;
29+
assert(p3 != 0); // should pass
30+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
union_list.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/pointer-analysis/value_set.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616

1717
#include <util/arith_tools.h>
1818
#include <util/base_type.h>
19+
#include <util/byte_operators.h>
1920
#include <util/c_types.h>
2021
#include <util/pointer_offset_size.h>
2122
#include <util/simplify_expr.h>
@@ -1203,9 +1204,9 @@ void value_sett::assign(
12031204
"type:\n"+type.pretty();
12041205

12051206
rhs_member=make_member(rhs, name, ns);
1206-
1207-
assign(lhs_member, rhs_member, ns, is_simplified, add_to_sets);
12081207
}
1208+
1209+
assign(lhs_member, rhs_member, ns, false, add_to_sets);
12091210
}
12101211
}
12111212
else if(type.id()==ID_array)
@@ -1756,7 +1757,7 @@ exprt value_sett::make_member(
17561757
}
17571758

17581759
// give up
1759-
typet subtype=struct_union_type.component_type(component_name);
1760+
const typet subtype = struct_union_type.component_type(component_name);
17601761
member_exprt member_expr(src, component_name, subtype);
17611762

17621763
return member_expr;

src/util/simplify_expr_struct.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,25 @@ bool simplify_exprt::simplify_member(exprt &expr)
172172

173173
return false;
174174
}
175+
else if(op_type.id() == ID_union)
176+
{
177+
// rewrite byte_extract(X, 0).member to X
178+
// if the type of X is that of the member
179+
const auto &byte_extract_expr = to_byte_extract_expr(op);
180+
if(byte_extract_expr.offset().is_zero())
181+
{
182+
const union_typet &union_type = to_union_type(op_type);
183+
const typet subtype = union_type.component_type(component_name);
184+
185+
if(subtype == byte_extract_expr.op().type())
186+
{
187+
exprt tmp = byte_extract_expr.op();
188+
expr.swap(tmp);
189+
190+
return false;
191+
}
192+
}
193+
}
175194
}
176195
else if(op.id()==ID_union && op_type.id()==ID_union)
177196
{

0 commit comments

Comments
 (0)