27
27
#include < util/expr_iterator.h>
28
28
#include < util/expr_util.h>
29
29
#include < util/magic.h>
30
+ #include < util/range.h>
30
31
#include < util/simplify_expr.h>
31
32
32
33
#include " equation_symbol_mapping.h"
@@ -239,23 +240,24 @@ static std::vector<exprt> generate_instantiations(
239
240
return lemmas;
240
241
}
241
242
242
- // / Fill the array_pointer correspondence and replace the right hand sides of
243
- // / the corresponding equations
243
+ // / If \p expr is an equation whose right-hand-side is a
244
+ // / associate_array_to_pointer call, add the correspondence and replace the call
245
+ // / by an expression representing its result.
244
246
static void make_char_array_pointer_associations (
245
247
string_constraint_generatort &generator,
246
- std::vector<equal_exprt> &equations )
248
+ exprt &expr )
247
249
{
248
- for (equal_exprt &eq : equations )
250
+ if ( const auto equal_expr = expr_try_dynamic_cast<equal_exprt>(expr) )
249
251
{
250
252
if (
251
- const auto fun_app =
252
- expr_try_dynamic_cast<function_application_exprt>(eq. rhs ()))
253
+ const auto fun_app = expr_try_dynamic_cast<function_application_exprt>(
254
+ as_const (equal_expr-> rhs () )))
253
255
{
254
256
const auto new_equation =
255
- generator.make_array_pointer_association (eq. lhs (), *fun_app);
257
+ generator.make_array_pointer_association (equal_expr-> lhs (), *fun_app);
256
258
if (new_equation)
257
259
{
258
- eq =
260
+ expr =
259
261
equal_exprt{from_integer (true , new_equation->type ()), *new_equation};
260
262
}
261
263
}
@@ -281,18 +283,10 @@ void string_refinementt::set_to(const exprt &expr, bool value)
281
283
{
282
284
PRECONDITION (expr.type ().id () == ID_bool);
283
285
PRECONDITION (equality_propagation);
284
-
285
- if (expr.id () == ID_equal && value)
286
- {
287
- const equal_exprt &eq_expr = to_equal_expr (expr);
288
- equations.push_back (eq_expr);
289
- }
286
+ if (!value)
287
+ equations.push_back (not_exprt{expr});
290
288
else
291
- {
292
- INVARIANT (
293
- !has_char_array_subexpr (expr, ns), " char array only appear in equations" );
294
- supert::set_to (expr, value);
295
- }
289
+ equations.push_back (expr);
296
290
}
297
291
298
292
// / Add association for each char pointer in the equation
@@ -305,16 +299,19 @@ void string_refinementt::set_to(const exprt &expr, bool value)
305
299
// / by an equation are associated to the same element
306
300
static void add_equations_for_symbol_resolution (
307
301
union_find_replacet &symbol_solver,
308
- const std::vector<equal_exprt > &equations,
302
+ const std::vector<exprt > &equations,
309
303
const namespacet &ns,
310
304
messaget::mstreamt &stream)
311
305
{
312
306
const std::string log_message =
313
307
" WARNING string_refinement.cpp generate_symbol_resolution_from_equations:" ;
314
- for (const equal_exprt &eq : equations)
308
+ auto equalities = make_range (equations).filter (
309
+ [&](const exprt &e) { return can_cast_expr<equal_exprt>(e); });
310
+ for (const exprt &e : equalities)
315
311
{
316
- const exprt &lhs = eq.lhs ();
317
- const exprt &rhs = eq.rhs ();
312
+ const equal_exprt &eq = to_equal_expr (e);
313
+ const exprt &lhs = to_equal_expr (eq).lhs ();
314
+ const exprt &rhs = to_equal_expr (eq).rhs ();
318
315
if (lhs.id () != ID_symbol)
319
316
{
320
317
stream << log_message << " non symbol lhs: " << format (lhs)
@@ -463,7 +460,7 @@ static void add_string_equation_to_symbol_resolution(
463
460
// / \param stream: output stream
464
461
// / \return union_find_replacet structure containing the correspondences.
465
462
union_find_replacet string_identifiers_resolution_from_equations (
466
- std::vector<equal_exprt> &equations,
463
+ const std::vector<equal_exprt> &equations,
467
464
const namespacet &ns,
468
465
messaget::mstreamt &stream)
469
466
{
@@ -534,13 +531,11 @@ union_find_replacet string_identifiers_resolution_from_equations(
534
531
535
532
#ifdef DEBUG
536
533
// / Output a vector of equations to the given stream, used for debugging.
537
- static void output_equations (
538
- std::ostream &output,
539
- const std::vector<equal_exprt> &equations)
534
+ static void
535
+ output_equations (std::ostream &output, const std::vector<exprt> &equations)
540
536
{
541
537
for (std::size_t i = 0 ; i < equations.size (); ++i)
542
- output << " [" << i << " ] " << format (equations[i].lhs ())
543
- << " == " << format (equations[i].rhs ()) << std::endl;
538
+ output << " [" << i << " ] " << format (equations[i]) << std::endl;
544
539
}
545
540
#endif
546
541
@@ -629,7 +624,18 @@ decision_proceduret::resultt string_refinementt::dec_solve()
629
624
#endif
630
625
631
626
const union_find_replacet string_id_symbol_resolve =
632
- string_identifiers_resolution_from_equations (equations, ns, log .debug ());
627
+ string_identifiers_resolution_from_equations (
628
+ [&] {
629
+ std::vector<equal_exprt> equalities;
630
+ for (const auto &eq : equations)
631
+ {
632
+ if (auto equal_expr = expr_try_dynamic_cast<equal_exprt>(eq))
633
+ equalities.push_back (*equal_expr);
634
+ }
635
+ return equalities;
636
+ }(),
637
+ ns,
638
+ log .debug ());
633
639
#ifdef DEBUG
634
640
log .debug () << " symbol resolve string:" << messaget::eom;
635
641
for (const auto &pair : string_id_symbol_resolve.to_vector ())
@@ -639,39 +645,55 @@ decision_proceduret::resultt string_refinementt::dec_solve()
639
645
}
640
646
#endif
641
647
642
- log .debug () << " dec_solve: Replacing string ids in function applications"
648
+ log .debug () << " dec_solve: Replacing string ids and simplifying arguments"
649
+ " in function applications"
643
650
<< messaget::eom;
644
- for (equal_exprt &eq : equations)
651
+ for (exprt &expr : equations)
645
652
{
646
- if (can_cast_expr<function_application_exprt>(eq.rhs ()))
653
+ auto it = expr.depth_begin ();
654
+ while (it != expr.depth_end ())
647
655
{
648
- simplify (eq.rhs (), ns);
649
- string_id_symbol_resolve.replace_expr (eq.rhs ());
656
+ if (can_cast_expr<function_application_exprt>(*it))
657
+ {
658
+ // Simplification is required because the array pool may not realize
659
+ // that an expression like
660
+ // `(unsignedbv[16]*)((signedbv[8]*)&constarray[0] + 0)` is the
661
+ // same pointer as `&constarray[0]
662
+ simplify (it.mutate (), ns);
663
+ string_id_symbol_resolve.replace_expr (it.mutate ());
664
+ it.next_sibling_or_parent ();
665
+ }
666
+ else
667
+ ++it;
650
668
}
651
669
}
652
670
653
671
// Constraints start clear at each `dec_solve` call.
654
672
string_constraintst constraints;
655
- make_char_array_pointer_associations (generator, equations);
673
+ for (auto &expr : equations)
674
+ make_char_array_pointer_associations (generator, expr);
656
675
657
676
#ifdef DEBUG
658
677
output_equations (log .debug (), equations);
659
678
#endif
660
679
661
680
log .debug () << " dec_solve: compute dependency graph and remove function "
662
681
<< " applications captured by the dependencies:" << messaget::eom;
663
- std::vector<equal_exprt > local_equations;
664
- for (const equal_exprt &eq : equations)
682
+ std::vector<exprt > local_equations;
683
+ for (const exprt &eq : equations)
665
684
{
666
685
// Ensures that arrays that are equal, are associated to the same nodes
667
686
// in the graph.
668
- const equal_exprt eq_with_char_array_replaced_with_representative_elements =
669
- to_equal_expr ( replace_expr_copy (symbol_resolve, eq) );
670
- const bool node_added = add_node (
687
+ const exprt eq_with_char_array_replaced_with_representative_elements =
688
+ replace_expr_copy (symbol_resolve, eq);
689
+ const optionalt<exprt> new_equation = add_node (
671
690
dependencies,
672
691
eq_with_char_array_replaced_with_representative_elements,
673
- generator.array_pool );
674
- if (!node_added)
692
+ generator.array_pool ,
693
+ generator.fresh_symbol );
694
+ if (new_equation)
695
+ local_equations.push_back (*new_equation);
696
+ else
675
697
local_equations.push_back (eq);
676
698
}
677
699
equations.clear ();
0 commit comments