Skip to content

Commit c83c1d2

Browse files
committed
SMT back-end: Extend trace value evaluation
We record the values of expressions by adding `expr == expr` as constraints in order to be able to fetch and display them in the GOTO trace (for declaration; we presently also introduce new symbols in other cases). Constructing a trace then requires the ability to evaluate all kinds of expressions to obtain the value for those expressions. Fixes: #7308
1 parent 70b7cf7 commit c83c1d2

File tree

8 files changed

+50
-30
lines changed

8 files changed

+50
-30
lines changed

regression/cbmc/Empty_struct3/main.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <assert.h>
2+
3+
struct Unit
4+
{
5+
};
6+
7+
int main()
8+
{
9+
struct Unit var_0;
10+
int x;
11+
int y = x;
12+
assert(0);
13+
assert(y == x);
14+
return 0;
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--json-ui
4+
VERIFICATION FAILED
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring

regression/cbmc/trace-values/trace-values.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
trace-values.c
33
--trace
44
^EXIT=10$

regression/cbmc/trace_options_json_extended/extended.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
test.c
33
--trace --json-ui --trace-json-extended
44
^EXIT=10$

regression/cbmc/trace_options_json_extended/non-extended.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
test.c
33
--trace --json-ui
44
^EXIT=10$

regression/validate-trace-xml-schema/check.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
# this uses json-ui (fails for a different reason actually, but should also
5757
# fail because of command line incompatibility)
5858
['json1', 'test.desc'],
59+
['Empty_struct3', 'test.desc'],
5960
# uses show-goto-functions
6061
['reachability-slice', 'test.desc'],
6162
['reachability-slice', 'test2.desc'],

src/goto-symex/build_goto_trace.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -353,10 +353,12 @@ void build_goto_trace(
353353
goto_trace_step.io_id = SSA_step.io_id;
354354
goto_trace_step.formatted = SSA_step.formatted;
355355
goto_trace_step.called_function = SSA_step.called_function;
356-
goto_trace_step.function_arguments = SSA_step.converted_function_arguments;
357356

358-
for(auto &arg : goto_trace_step.function_arguments)
359-
arg = decision_procedure.get(arg);
357+
for(const auto &arg : SSA_step.converted_function_arguments)
358+
{
359+
goto_trace_step.function_arguments.push_back(
360+
simplify_expr(decision_procedure.get(arg), ns));
361+
}
360362

361363
// update internal field for specific variables in the counterexample
362364
update_internal_field(SSA_step, goto_trace_step, ns);
@@ -394,15 +396,8 @@ void build_goto_trace(
394396

395397
for(const auto &j : SSA_step.converted_io_args)
396398
{
397-
if(j.is_constant() || j.id() == ID_string_constant)
398-
{
399-
goto_trace_step.io_args.push_back(j);
400-
}
401-
else
402-
{
403-
exprt tmp = decision_procedure.get(j);
404-
goto_trace_step.io_args.push_back(tmp);
405-
}
399+
goto_trace_step.io_args.push_back(
400+
simplify_expr(decision_procedure.get(j), ns));
406401
}
407402

408403
if(SSA_step.is_assert() || SSA_step.is_assume() || SSA_step.is_goto())

src/solvers/smt2/smt2_conv.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -297,14 +297,6 @@ exprt smt2_convt::get(const exprt &expr) const
297297
if(it!=identifier_map.end())
298298
return it->second.value;
299299
}
300-
else if(expr.id()==ID_member)
301-
{
302-
const member_exprt &member_expr=to_member_expr(expr);
303-
exprt tmp=get(member_expr.struct_op());
304-
if(tmp.is_nil())
305-
return nil_exprt();
306-
return member_exprt(tmp, member_expr.get_component_name(), expr.type());
307-
}
308300
else if(expr.id() == ID_literal)
309301
{
310302
auto l = to_literal_expr(expr).get_literal();
@@ -321,16 +313,23 @@ exprt smt2_convt::get(const exprt &expr) const
321313
else if(op.is_false())
322314
return true_exprt();
323315
}
324-
else if(expr.is_constant())
316+
else if(
317+
expr.is_constant() || expr.id() == ID_empty_union ||
318+
(!expr.has_operands() && (expr.id() == ID_struct || expr.id() == ID_array)))
319+
{
325320
return expr;
326-
else if(const auto &array = expr_try_dynamic_cast<array_exprt>(expr))
321+
}
322+
else if(expr.has_operands())
327323
{
328-
exprt array_copy = *array;
329-
for(auto &element : array_copy.operands())
324+
exprt copy = expr;
325+
for(auto &op : copy.operands())
330326
{
331-
element = get(element);
327+
exprt eval_op = get(op);
328+
if(eval_op.is_nil())
329+
return nil_exprt{};
330+
op = std::move(eval_op);
332331
}
333-
return array_copy;
332+
return copy;
334333
}
335334

336335
return nil_exprt();
@@ -4780,7 +4779,9 @@ void smt2_convt::set_to(const exprt &expr, bool value)
47804779
const irep_idt &identifier=
47814780
to_symbol_expr(equal_expr.lhs()).get_identifier();
47824781

4783-
if(identifier_map.find(identifier)==identifier_map.end())
4782+
if(
4783+
identifier_map.find(identifier) == identifier_map.end() &&
4784+
equal_expr.lhs() != equal_expr.rhs())
47844785
{
47854786
identifiert &id=identifier_map[identifier];
47864787
CHECK_RETURN(id.type.is_nil());

0 commit comments

Comments
 (0)