Skip to content

Commit 5d4f090

Browse files
authored
Merge pull request #5633 from tautschnig/union-restore
Restore member-of-union expressions in trace output
2 parents 26f8498 + fafe838 commit 5d4f090

File tree

6 files changed

+82
-5
lines changed

6 files changed

+82
-5
lines changed

regression/cbmc/xml-trace/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ activate-multi-line-match
77
VERIFICATION FAILED
88
<assignment assignment_type="actual_parameter" base_name="u" display_name="test::u" hidden="false" identifier="test::u" mode="C" step_nr="\d+" thread="0">\n\s*<location file=".*" line="\d+" working-directory=".*"/>\n\s*<full_lhs_type>union myunion</full_lhs_type>\n\s*<full_lhs>u</full_lhs>
99
<value>\{ \.i=\d+ll? \}</value>\n\s*<value_expression>\n\s*<union>\n\s*<member member_name="i">\n\s*<integer binary="\d+" c_type=".*int.*" width="\d+">\d+</integer>\n\s*</member>\n\s*</union>\n\s*</value_expression>
10-
<assignment assignment_type="state" base_name="u" display_name="test::u" hidden="false" identifier="test::u" mode="C" step_nr="\d+" thread="0">\n\s*<location file=".*" function="test" line="\d+" working-directory=".*"/>\n\s*<full_lhs_type>signed long( long)? int</full_lhs_type>\n\s*<full_lhs>byte_extract_little_endian\(u, 0ll?, .*int.*\)</full_lhs>\n\s*<full_lhs_value binary="[01]+">\d+ll?</full_lhs_value>\n\s*</assignment>
10+
<assignment assignment_type="state" base_name="u" display_name="test::u" hidden="false" identifier="test::u" mode="C" step_nr="\d+" thread="0">\n\s*<location file=".*" function="test" line="\d+" working-directory=".*"/>\n\s*<full_lhs_type>signed long( long)? int</full_lhs_type>\n\s*<full_lhs>u\.i</full_lhs>\n\s*<full_lhs_value binary="[01]+">\d+ll?</full_lhs_value>\n\s*</assignment>
1111
--
1212
^warning: ignoring
1313
--

src/goto-programs/goto_trace.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ void goto_trace_stept::output(
129129
if(!comment.empty())
130130
out << " " << comment << '\n';
131131

132-
out << " " << format(pc->condition()) << '\n';
132+
out << " " << format(original_condition) << '\n';
133133
out << '\n';
134134
}
135135
}
@@ -423,7 +423,8 @@ void show_compact_goto_trace(
423423

424424
if(step.pc->is_assert())
425425
{
426-
out << " " << from_expr(ns, step.function_id, step.pc->condition())
426+
out << " "
427+
<< from_expr(ns, step.function_id, step.original_condition)
427428
<< '\n';
428429
}
429430

@@ -550,7 +551,8 @@ void show_full_goto_trace(
550551

551552
if(step.pc->is_assert())
552553
{
553-
out << " " << from_expr(ns, step.function_id, step.pc->condition())
554+
out << " "
555+
<< from_expr(ns, step.function_id, step.original_condition)
554556
<< '\n';
555557
}
556558

@@ -567,7 +569,7 @@ void show_full_goto_trace(
567569
if(!step.pc->source_location().is_nil())
568570
out << " " << step.pc->source_location() << '\n';
569571

570-
out << " " << from_expr(ns, step.function_id, step.pc->condition())
572+
out << " " << from_expr(ns, step.function_id, step.original_condition)
571573
<< '\n';
572574
}
573575
break;

src/goto-programs/goto_trace.h

+2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class goto_trace_stept
117117
// for assume, assert, goto
118118
bool cond_value;
119119
exprt cond_expr;
120+
exprt original_condition;
120121

121122
// for assert
122123
irep_idt property_id;
@@ -161,6 +162,7 @@ class goto_trace_stept
161162
full_lhs.make_nil();
162163
full_lhs_value.make_nil();
163164
cond_expr.make_nil();
165+
original_condition.make_nil();
164166
}
165167

166168
/// Use \p dest to establish sharing among ireps.

src/goto-programs/rewrite_union.cpp

+63
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Author: Daniel Kroening, [email protected]
1515
#include <util/byte_operators.h>
1616
#include <util/c_types.h>
1717
#include <util/pointer_expr.h>
18+
#include <util/pointer_offset_size.h>
1819
#include <util/std_code.h>
1920

2021
#include <goto-programs/goto_model.h>
@@ -116,3 +117,65 @@ void rewrite_union(goto_modelt &goto_model)
116117
{
117118
rewrite_union(goto_model.goto_functions);
118119
}
120+
121+
/// Undo the union access -> byte_extract replacement that rewrite_union did for
122+
/// the purpose of displaying expressions to users.
123+
/// \param expr: expression to inspect and possibly transform
124+
/// \param ns: namespace
125+
/// \return True if, and only if, the expression is unmodified
126+
static bool restore_union_rec(exprt &expr, const namespacet &ns)
127+
{
128+
bool unmodified = true;
129+
130+
Forall_operands(it, expr)
131+
unmodified &= restore_union_rec(*it, ns);
132+
133+
if(
134+
expr.id() == ID_byte_extract_little_endian ||
135+
expr.id() == ID_byte_extract_big_endian)
136+
{
137+
byte_extract_exprt &be = to_byte_extract_expr(expr);
138+
if(be.op().type().id() == ID_union || be.op().type().id() == ID_union_tag)
139+
{
140+
const union_typet &union_type = to_union_type(ns.follow(be.op().type()));
141+
142+
for(const auto &comp : union_type.components())
143+
{
144+
if(be.offset().is_zero() && be.type() == comp.type())
145+
{
146+
expr = member_exprt{be.op(), comp.get_name(), be.type()};
147+
return false;
148+
}
149+
else if(
150+
comp.type().id() == ID_array || comp.type().id() == ID_struct ||
151+
comp.type().id() == ID_struct_tag)
152+
{
153+
optionalt<exprt> result = get_subexpression_at_offset(
154+
member_exprt{be.op(), comp.get_name(), comp.type()},
155+
be.offset(),
156+
be.type(),
157+
ns);
158+
if(result.has_value())
159+
{
160+
expr = *result;
161+
return false;
162+
}
163+
}
164+
}
165+
}
166+
}
167+
168+
return unmodified;
169+
}
170+
171+
/// Undo the union access -> byte_extract replacement that rewrite_union did for
172+
/// the purpose of displaying expressions to users.
173+
/// \param expr: expression to inspect and possibly transform
174+
/// \param ns: namespace
175+
void restore_union(exprt &expr, const namespacet &ns)
176+
{
177+
exprt tmp = expr;
178+
179+
if(!restore_union_rec(tmp, ns))
180+
expr.swap(tmp);
181+
}

src/goto-programs/rewrite_union.h

+2
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ void rewrite_union(goto_functionst::goto_functiont &);
2222
void rewrite_union(goto_functionst &);
2323
void rewrite_union(goto_modelt &);
2424

25+
void restore_union(exprt &, const namespacet &);
26+
2527
#endif // CPROVER_GOTO_PROGRAMS_REWRITE_UNION_H

src/goto-symex/build_goto_trace.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Daniel Kroening
1919
#include <util/symbol.h>
2020

2121
#include <goto-programs/goto_functions.h>
22+
#include <goto-programs/rewrite_union.h>
2223

2324
#include <solvers/decision_procedure.h>
2425

@@ -379,6 +380,7 @@ void build_goto_trace(
379380
SSA_step.ssa_full_lhs),
380381
ns);
381382
replace_nondet_in_type(goto_trace_step.full_lhs, decision_procedure);
383+
restore_union(goto_trace_step.full_lhs, ns);
382384
}
383385

384386
if(SSA_step.ssa_full_lhs.is_not_nil())
@@ -411,6 +413,12 @@ void build_goto_trace(
411413
decision_procedure.get(SSA_step.cond_handle).is_true();
412414
}
413415

416+
if(SSA_step.source.pc->is_assert() || SSA_step.source.pc->is_assume())
417+
{
418+
goto_trace_step.original_condition = SSA_step.source.pc->condition();
419+
restore_union(goto_trace_step.original_condition, ns);
420+
}
421+
414422
if(ssa_step_it == last_step_to_keep)
415423
return;
416424
}

0 commit comments

Comments
 (0)