Skip to content

Commit 3cf746e

Browse files
committed
SPLIT
1 parent a303858 commit 3cf746e

File tree

13 files changed

+338
-45
lines changed

13 files changed

+338
-45
lines changed

regression/cbmc/Pointer_Arithmetic19/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
CORE new-smt-backend
22
main.c
33
--program-only
4-
ASSERT\(\{ 42, 43 \}\[POINTER_OFFSET\(p!0@1#2\) / \d+l*\] == 43\)$
54
^EXIT=0$
65
^SIGNAL=0$
76
--

regression/cbmc/array-cell-sensitivity15/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ access.c
33
--program-only
44
^EXIT=0$
55
^SIGNAL=0$
6-
s!0@1#1\.\.n == \{ s!0@1#1\.\.n\[\[0\]\], s!0@1#1\.\.n\[\[1\]\], s!0@1#1\.\.n\[\[2\]\], s!0@1#1\.\.n\[\[3\]\] } WITH \[\(.*\)i!0@1#2:=k!0@1#1\]
6+
s!0@1#2\.\.n == \{ s!0@1#1\.\.n\[\[0\]\], s!0@1#1\.\.n\[\[1\]\], s!0@1#1\.\.n\[\[2\]\], s!0@1#1\.\.n\[\[3\]\] } WITH \[\(.*\)i!0@1#2:=k!0@1#1\]
77
--
88
byte_update
99
--

regression/cbmc/array-cell-sensitivity8/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ main::1::array!0@1#2\[\[6\]\] =
1010
main::1::array!0@1#2\[\[7\]\] =
1111
main::1::array!0@1#2\[\[8\]\] =
1212
main::1::array!0@1#2\[\[9\]\] =
13-
main::1::array!0@1#2 =.*byte_extract_little_endian
13+
main::1::array!0@1#3 =.*byte_extract_little_endian
1414
main::1::array!0@1#3\[\[0\]\] =
1515
main::1::array!0@1#3\[\[1\]\] =
1616
main::1::array!0@1#3\[\[2\]\] =

regression/cbmc/field-sensitivity9/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CORE
22
test.c
33
--show-vcc
4-
main::1::a1!0@1#1 =
5-
main::1::a2!0@1#1 =
4+
main::1::a1!0@1#2 =
5+
main::1::a2!0@1#2 =
66
main::1::a1!0@1#2\.\.x =
77
main::1::a1!0@1#2\.\.y =
88
main::1::a1!0@1#2\.\.z =

regression/cbmc/vla1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-cprover-smt-backend
1+
CORE broken-cprover-smt-backend paths-lifo-expected-failure
22
main.c
33

44
^EXIT=0$

src/goto-symex/field_sensitivity.cpp

Lines changed: 183 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ Author: Michael Tautschnig
99
#include "field_sensitivity.h"
1010

1111
#include <util/arith_tools.h>
12+
#include <util/byte_operators.h>
13+
#include <util/c_types.h>
14+
#include <util/pointer_offset_size.h>
1215
#include <util/simplify_expr.h>
13-
#include <util/std_expr.h>
1416

1517
#include "goto_symex_state.h"
1618
#include "symex_target.h"
@@ -26,7 +28,7 @@ exprt field_sensitivityt::apply(
2628
if(!run_apply || write)
2729
return std::move(ssa_expr);
2830
else
29-
return get_fields(ns, state, ssa_expr);
31+
return get_fields(ns, state, ssa_expr, true);
3032
}
3133

3234
exprt field_sensitivityt::apply(
@@ -72,7 +74,9 @@ exprt field_sensitivityt::apply(
7274
if(
7375
is_ssa_expr(member.struct_op()) &&
7476
(member.struct_op().type().id() == ID_struct ||
75-
member.struct_op().type().id() == ID_struct_tag))
77+
member.struct_op().type().id() == ID_struct_tag ||
78+
member.struct_op().type().id() == ID_union ||
79+
member.struct_op().type().id() == ID_union_tag))
7680
{
7781
// place the entire member expression, not just the struct operand, in an
7882
// SSA expression
@@ -88,6 +92,58 @@ exprt field_sensitivityt::apply(
8892
return std::move(tmp);
8993
}
9094
}
95+
else if(
96+
!write && (expr.id() == ID_byte_extract_little_endian ||
97+
expr.id() == ID_byte_extract_big_endian))
98+
{
99+
const byte_extract_exprt &be = to_byte_extract_expr(expr);
100+
if(
101+
(be.op().type().id() == ID_union ||
102+
be.op().type().id() == ID_union_tag) &&
103+
is_ssa_expr(be.op()) && be.offset().is_constant())
104+
{
105+
const union_typet &type = to_union_type(ns.follow(be.op().type()));
106+
for(const auto &comp : type.components())
107+
{
108+
if(be.offset().is_zero() && comp.type() == be.type())
109+
{
110+
ssa_exprt tmp = to_ssa_expr(be.op());
111+
bool was_l2 = !tmp.get_level_2().empty();
112+
tmp.remove_level_2();
113+
member_exprt member{tmp.get_original_expr(), comp};
114+
tmp.type() = be.type();
115+
tmp.set_expression(member);
116+
if(was_l2)
117+
return state.rename(std::move(tmp), ns).get();
118+
else
119+
return std::move(tmp);
120+
}
121+
else if(
122+
comp.type().id() == ID_struct || comp.type().id() == ID_struct_tag ||
123+
comp.type().id() == ID_array)
124+
{
125+
ssa_exprt tmp = to_ssa_expr(be.op());
126+
bool was_l2 = !tmp.get_level_2().empty();
127+
tmp.remove_level_2();
128+
const member_exprt member{tmp.get_original_expr(), comp};
129+
auto recursive_member =
130+
get_subexpression_at_offset(member, be.offset(), be.type(), ns);
131+
if(
132+
recursive_member.has_value() &&
133+
(recursive_member->id() == ID_member ||
134+
recursive_member->id() == ID_index))
135+
{
136+
tmp.type() = be.type();
137+
tmp.set_expression(*recursive_member);
138+
if(was_l2)
139+
return state.rename(std::move(tmp), ns).get();
140+
else
141+
return std::move(tmp);
142+
}
143+
}
144+
}
145+
}
146+
}
91147
#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
92148
else if(expr.id() == ID_index)
93149
{
@@ -144,7 +200,7 @@ exprt field_sensitivityt::apply(
144200
{
145201
// Expand the array and return `{array[0]; array[1]; ...}[index]`
146202
exprt expanded_array =
147-
get_fields(ns, state, to_ssa_expr(index.array()));
203+
get_fields(ns, state, to_ssa_expr(index.array()), true);
148204
return index_exprt{std::move(expanded_array), index.index()};
149205
}
150206
}
@@ -157,33 +213,48 @@ exprt field_sensitivityt::apply(
157213
exprt field_sensitivityt::get_fields(
158214
const namespacet &ns,
159215
goto_symex_statet &state,
160-
const ssa_exprt &ssa_expr) const
216+
const ssa_exprt &ssa_expr,
217+
bool disjoined_fields_only) const
161218
{
162-
if(ssa_expr.type().id() == ID_struct || ssa_expr.type().id() == ID_struct_tag)
219+
if(
220+
ssa_expr.type().id() == ID_struct ||
221+
ssa_expr.type().id() == ID_struct_tag ||
222+
(!disjoined_fields_only && (ssa_expr.type().id() == ID_union ||
223+
ssa_expr.type().id() == ID_union_tag)))
163224
{
164-
const struct_typet &type = to_struct_type(ns.follow(ssa_expr.type()));
225+
const struct_union_typet &type =
226+
to_struct_union_type(ns.follow(ssa_expr.type()));
165227
const struct_union_typet::componentst &components = type.components();
166228

167-
struct_exprt::operandst fields;
229+
exprt::operandst fields;
168230
fields.reserve(components.size());
169231

170-
const exprt &struct_op = ssa_expr.get_original_expr();
232+
const exprt &compound_op = ssa_expr.get_original_expr();
171233

172234
for(const auto &comp : components)
173235
{
174236
ssa_exprt tmp = ssa_expr;
175237
bool was_l2 = !tmp.get_level_2().empty();
176238
tmp.remove_level_2();
177-
tmp.set_expression(member_exprt{struct_op, comp.get_name(), comp.type()});
239+
tmp.set_expression(
240+
member_exprt{compound_op, comp.get_name(), comp.type()});
241+
exprt field = get_fields(ns, state, tmp, disjoined_fields_only);
178242
if(was_l2)
179243
{
180-
fields.push_back(state.rename(get_fields(ns, state, tmp), ns).get());
244+
fields.emplace_back(state.rename(std::move(field), ns).get());
181245
}
182246
else
183-
fields.push_back(get_fields(ns, state, tmp));
247+
fields.emplace_back(std::move(field));
184248
}
185249

186-
return struct_exprt(std::move(fields), ssa_expr.type());
250+
if(
251+
disjoined_fields_only && (ssa_expr.type().id() == ID_struct ||
252+
ssa_expr.type().id() == ID_struct_tag))
253+
{
254+
return struct_exprt{std::move(fields), ssa_expr.type()};
255+
}
256+
else
257+
return field_sensitive_ssa_exprt{ssa_expr, std::move(fields)};
187258
}
188259
#ifdef ENABLE_ARRAY_FIELD_SENSITIVITY
189260
else if(
@@ -210,15 +281,19 @@ exprt field_sensitivityt::get_fields(
210281
bool was_l2 = !tmp.get_level_2().empty();
211282
tmp.remove_level_2();
212283
tmp.set_expression(index);
284+
exprt element = get_fields(ns, state, tmp, disjoined_fields_only);
213285
if(was_l2)
214286
{
215-
elements.push_back(state.rename(get_fields(ns, state, tmp), ns).get());
287+
elements.emplace_back(state.rename(std::move(element), ns).get());
216288
}
217289
else
218-
elements.push_back(get_fields(ns, state, tmp));
290+
elements.emplace_back(std::move(element));
219291
}
220292

221-
return array_exprt(std::move(elements), type);
293+
if(disjoined_fields_only)
294+
return array_exprt(std::move(elements), type);
295+
else
296+
return field_sensitive_ssa_exprt{ssa_expr, std::move(elements)};
222297
}
223298
#endif // ENABLE_ARRAY_FIELD_SENSITIVITY
224299
else
@@ -233,15 +308,15 @@ void field_sensitivityt::field_assignments(
233308
symex_targett &target,
234309
bool allow_pointer_unsoundness)
235310
{
236-
const exprt lhs_fs = apply(ns, state, lhs, false);
311+
PRECONDITION(run_apply);
312+
const exprt lhs_fs = get_fields(ns, state, lhs, false);
237313

238314
if(lhs != lhs_fs)
239315
{
240-
bool run_apply_bak = run_apply;
241-
run_apply = false;
316+
// run_apply = false; // not even clear we need this anymore
242317
field_assignments_rec(
243318
ns, state, lhs_fs, rhs, target, allow_pointer_unsoundness);
244-
run_apply = run_apply_bak;
319+
// run_apply = true;
245320
}
246321
}
247322

@@ -302,6 +377,60 @@ void field_sensitivityt::field_assignments_rec(
302377
simplify_opt(member_exprt{ssa_rhs, comp.get_name(), comp.type()}, ns);
303378
const exprt &member_lhs = *fs_it;
304379

380+
if(
381+
auto fs_ssa =
382+
expr_try_dynamic_cast<field_sensitive_ssa_exprt>(member_lhs))
383+
{
384+
field_assignments_rec(
385+
ns,
386+
state,
387+
fs_ssa->get_object_ssa(),
388+
member_rhs,
389+
target,
390+
allow_pointer_unsoundness);
391+
}
392+
393+
field_assignments_rec(
394+
ns, state, member_lhs, member_rhs, target, allow_pointer_unsoundness);
395+
++fs_it;
396+
}
397+
}
398+
else if(
399+
ssa_rhs.type().id() == ID_union || ssa_rhs.type().id() == ID_union_tag)
400+
{
401+
const union_typet &type = to_union_type(ns.follow(ssa_rhs.type()));
402+
const struct_union_typet::componentst &components = type.components();
403+
404+
PRECONDITION(
405+
components.empty() ||
406+
(lhs_fs.has_operands() && lhs_fs.operands().size() == components.size()));
407+
408+
exprt::operandst::const_iterator fs_it = lhs_fs.operands().begin();
409+
for(const auto &comp : components)
410+
{
411+
const exprt member_rhs = apply(
412+
ns,
413+
state,
414+
simplify_opt(
415+
make_byte_extract(
416+
ssa_rhs, from_integer(0, c_index_type()), comp.type()),
417+
ns),
418+
false);
419+
const exprt &member_lhs = *fs_it;
420+
421+
if(
422+
auto fs_ssa =
423+
expr_try_dynamic_cast<field_sensitive_ssa_exprt>(member_lhs))
424+
{
425+
field_assignments_rec(
426+
ns,
427+
state,
428+
fs_ssa->get_object_ssa(),
429+
member_rhs,
430+
target,
431+
allow_pointer_unsoundness);
432+
}
433+
305434
field_assignments_rec(
306435
ns, state, member_lhs, member_rhs, target, allow_pointer_unsoundness);
307436
++fs_it;
@@ -324,6 +453,19 @@ void field_sensitivityt::field_assignments_rec(
324453
index_exprt{ssa_rhs, from_integer(i, type->index_type())}, ns);
325454
const exprt &index_lhs = *fs_it;
326455

456+
if(
457+
auto fs_ssa =
458+
expr_try_dynamic_cast<field_sensitive_ssa_exprt>(index_lhs))
459+
{
460+
field_assignments_rec(
461+
ns,
462+
state,
463+
fs_ssa->get_object_ssa(),
464+
index_rhs,
465+
target,
466+
allow_pointer_unsoundness);
467+
}
468+
327469
field_assignments_rec(
328470
ns, state, index_lhs, index_rhs, target, allow_pointer_unsoundness);
329471
++fs_it;
@@ -339,6 +481,17 @@ void field_sensitivityt::field_assignments_rec(
339481
exprt::operandst::const_iterator fs_it = lhs_fs.operands().begin();
340482
for(const exprt &op : ssa_rhs.operands())
341483
{
484+
if(auto fs_ssa = expr_try_dynamic_cast<field_sensitive_ssa_exprt>(*fs_it))
485+
{
486+
field_assignments_rec(
487+
ns,
488+
state,
489+
fs_ssa->get_object_ssa(),
490+
op,
491+
target,
492+
allow_pointer_unsoundness);
493+
}
494+
342495
field_assignments_rec(
343496
ns, state, *fs_it, op, target, allow_pointer_unsoundness);
344497
++fs_it;
@@ -350,7 +503,9 @@ void field_sensitivityt::field_assignments_rec(
350503
}
351504
}
352505

353-
bool field_sensitivityt::is_divisible(const ssa_exprt &expr) const
506+
bool field_sensitivityt::is_divisible(
507+
const ssa_exprt &expr,
508+
bool disjoined_fields_only) const
354509
{
355510
if(expr.type().id() == ID_struct || expr.type().id() == ID_struct_tag)
356511
return true;
@@ -366,6 +521,13 @@ bool field_sensitivityt::is_divisible(const ssa_exprt &expr) const
366521
}
367522
#endif
368523

524+
if(
525+
!disjoined_fields_only &&
526+
(expr.type().id() == ID_union || expr.type().id() == ID_union_tag))
527+
{
528+
return true;
529+
}
530+
369531
return false;
370532
}
371533

0 commit comments

Comments
 (0)