14
14
#include < util/arith_tools.h>
15
15
#include < util/c_types.h>
16
16
#include < util/config.h>
17
+ #include < util/expr_iterator.h>
17
18
#include < util/expr_util.h>
18
19
#include < util/fixedbv.h>
19
20
#include < util/format_expr.h>
@@ -612,24 +613,6 @@ void smt2_convt::convert_address_of_rec(
612
613
expr.id_string ());
613
614
}
614
615
615
- void smt2_convt::convert_byte_extract (const byte_extract_exprt &expr)
616
- {
617
- // we just run the flattener
618
- exprt flattened_expr = lower_byte_extract (expr, ns);
619
- unflatten (wheret::BEGIN, expr.type ());
620
- convert_expr (flattened_expr);
621
- unflatten (wheret::END, expr.type ());
622
- }
623
-
624
- void smt2_convt::convert_byte_update (const byte_update_exprt &expr)
625
- {
626
- // we just run the flattener
627
- exprt flattened_expr = lower_byte_update (expr, ns);
628
- unflatten (wheret::BEGIN, expr.type ());
629
- convert_expr (flattened_expr);
630
- unflatten (wheret::END, expr.type ());
631
- }
632
-
633
616
literalt smt2_convt::convert (const exprt &expr)
634
617
{
635
618
PRECONDITION (expr.type ().id () == ID_bool);
@@ -647,7 +630,7 @@ literalt smt2_convt::convert(const exprt &expr)
647
630
648
631
out << " \n " ;
649
632
650
- find_symbols (expr);
633
+ exprt prepared_expr = prepare_for_convert_expr (expr);
651
634
652
635
literalt l (no_boolean_variables, false );
653
636
no_boolean_variables++;
@@ -656,7 +639,7 @@ literalt smt2_convt::convert(const exprt &expr)
656
639
out << " (define-fun " ;
657
640
convert_literal (l);
658
641
out << " () Bool " ;
659
- convert_expr (expr );
642
+ convert_expr (prepared_expr );
660
643
out << " )" << " \n " ;
661
644
662
645
return l;
@@ -1431,12 +1414,14 @@ void smt2_convt::convert_expr(const exprt &expr)
1431
1414
else if (expr.id ()==ID_byte_extract_little_endian ||
1432
1415
expr.id ()==ID_byte_extract_big_endian)
1433
1416
{
1434
- convert_byte_extract (to_byte_extract_expr (expr));
1417
+ INVARIANT (
1418
+ false , " byte_extract ops should be lowered in prepare_for_convert_expr" );
1435
1419
}
1436
1420
else if (expr.id ()==ID_byte_update_little_endian ||
1437
1421
expr.id ()==ID_byte_update_big_endian)
1438
1422
{
1439
- convert_byte_update (to_byte_update_expr (expr));
1423
+ INVARIANT (
1424
+ false , " byte_update ops should be lowered in prepare_for_convert_expr" );
1440
1425
}
1441
1426
else if (expr.id ()==ID_width)
1442
1427
{
@@ -4058,7 +4043,7 @@ void smt2_convt::set_to(const exprt &expr, bool value)
4058
4043
4059
4044
id.type =equal_expr.lhs ().type ();
4060
4045
find_symbols (id.type );
4061
- find_symbols (equal_expr.rhs ());
4046
+ exprt prepared_rhs = prepare_for_convert_expr (equal_expr.rhs ());
4062
4047
4063
4048
std::string smt2_identifier=convert_identifier (identifier);
4064
4049
smt2_identifiers.insert (smt2_identifier);
@@ -4068,38 +4053,91 @@ void smt2_convt::set_to(const exprt &expr, bool value)
4068
4053
4069
4054
convert_type (equal_expr.lhs ().type ());
4070
4055
out << " " ;
4071
- convert_expr (equal_expr. rhs () );
4056
+ convert_expr (prepared_rhs );
4072
4057
4073
4058
out << " )" << " \n " ;
4074
4059
return ; // done
4075
4060
}
4076
4061
}
4077
4062
}
4078
4063
4079
- find_symbols (expr);
4064
+ exprt prepared_expr = prepare_for_convert_expr (expr);
4080
4065
4081
- #if 0
4066
+ #if 0
4082
4067
out << "; CONV: "
4083
4068
<< format(expr) << "\n";
4084
- #endif
4069
+ #endif
4085
4070
4086
4071
out << " ; set_to " << (value?" true" :" false" ) << " \n "
4087
4072
<< " (assert " ;
4088
4073
4089
4074
if (!value)
4090
4075
{
4091
4076
out << " (not " ;
4092
- convert_expr (expr );
4077
+ convert_expr (prepared_expr );
4093
4078
out << " )" ;
4094
4079
}
4095
4080
else
4096
- convert_expr (expr );
4081
+ convert_expr (prepared_expr );
4097
4082
4098
4083
out << " )" << " \n " ; // assert
4099
4084
4100
4085
return ;
4101
4086
}
4102
4087
4088
+ // / Lower byte_update and byte_extract operations within \p expr. Return an
4089
+ // / equivalent expression that doesn't use byte operators.
4090
+ // / Note this replaces operators post-order (compare \ref lower_byte_operators,
4091
+ // / which uses a pre-order walk, replacing in child expressions before the
4092
+ // / parent). Pre-order replacement currently fails regression tests: see
4093
+ // / https://github.com/diffblue/cbmc/issues/4380
4094
+ exprt smt2_convt::lower_byte_operators (const exprt &expr)
4095
+ {
4096
+ exprt lowered_expr = expr;
4097
+
4098
+ for (auto it = lowered_expr.depth_begin (), itend = lowered_expr.depth_end ();
4099
+ it != itend;
4100
+ ++it)
4101
+ {
4102
+ if (
4103
+ it->id () == ID_byte_extract_little_endian ||
4104
+ it->id () == ID_byte_extract_big_endian)
4105
+ {
4106
+ it.mutate () = lower_byte_extract (to_byte_extract_expr (*it), ns);
4107
+ }
4108
+ else if (
4109
+ it->id () == ID_byte_update_little_endian ||
4110
+ it->id () == ID_byte_update_big_endian)
4111
+ {
4112
+ it.mutate () = lower_byte_update (to_byte_update_expr (*it), ns);
4113
+ }
4114
+ }
4115
+
4116
+ return lowered_expr;
4117
+ }
4118
+
4119
+ // / Perform steps necessary before an expression is passed to \ref convert_expr
4120
+ // / 1. Replace byte operators (byte_extract, _update) with equivalent
4121
+ // / expressions
4122
+ // / 2. Call find_symbols to create auxiliary symbols, e.g. for array
4123
+ // / expressions.
4124
+ // / \param expr: expression to prepare
4125
+ // / \return equivalent expression suitable for convert_expr.
4126
+ exprt smt2_convt::prepare_for_convert_expr (const exprt &expr)
4127
+ {
4128
+ // First, replace byte operators, because they may introduce new array
4129
+ // expressions that must be seen by find_symbols:
4130
+ exprt lowered_expr = lower_byte_operators (expr);
4131
+ INVARIANT (
4132
+ !has_byte_operator (lowered_expr),
4133
+ " lower_byte_operators should remove all byte operators" );
4134
+
4135
+ // Now create symbols for all composite expressions present in lowered_expr:
4136
+ find_symbols (lowered_expr);
4137
+
4138
+ return lowered_expr;
4139
+ }
4140
+
4103
4141
void smt2_convt::find_symbols (const exprt &expr)
4104
4142
{
4105
4143
// recursive call on type
0 commit comments