@@ -154,9 +154,9 @@ void code_contractst::check_apply_loop_contracts(
154
154
// at the start of and end of a loop body
155
155
std::vector<symbol_exprt> old_decreases_vars, new_decreases_vars;
156
156
157
- replace_symbolt replace;
158
- code_contractst::add_quantified_variable ( invariant, replace, mode);
159
- replace (invariant);
157
+ // replace bound variables by fresh instances
158
+ if ( has_subexpr ( invariant, ID_exists) || has_subexpr (invariant, ID_forall))
159
+ add_quantified_variable (invariant, mode );
160
160
161
161
// instrument
162
162
//
@@ -567,68 +567,73 @@ void code_contractst::check_apply_loop_contracts(
567
567
}
568
568
569
569
void code_contractst::add_quantified_variable (
570
- const exprt &expression,
571
- replace_symbolt &replace,
570
+ exprt &expression,
572
571
const irep_idt &mode)
573
572
{
574
573
if (expression.id () == ID_not || expression.id () == ID_typecast)
575
574
{
576
575
// For unary connectives, recursively check for
577
576
// nested quantified formulae in the term
578
- const auto &unary_expression = to_unary_expr (expression);
579
- add_quantified_variable (unary_expression.op (), replace, mode);
577
+ auto &unary_expression = to_unary_expr (expression);
578
+ add_quantified_variable (unary_expression.op (), mode);
580
579
}
581
580
if (expression.id () == ID_notequal || expression.id () == ID_implies)
582
581
{
583
582
// For binary connectives, recursively check for
584
583
// nested quantified formulae in the left and right terms
585
- const auto &binary_expression = to_binary_expr (expression);
586
- add_quantified_variable (binary_expression.lhs (), replace, mode);
587
- add_quantified_variable (binary_expression.rhs (), replace, mode);
584
+ auto &binary_expression = to_binary_expr (expression);
585
+ add_quantified_variable (binary_expression.lhs (), mode);
586
+ add_quantified_variable (binary_expression.rhs (), mode);
588
587
}
589
588
if (expression.id () == ID_if)
590
589
{
591
590
// For ternary connectives, recursively check for
592
591
// nested quantified formulae in all three terms
593
- const auto &if_expression = to_if_expr (expression);
594
- add_quantified_variable (if_expression.cond (), replace, mode);
595
- add_quantified_variable (if_expression.true_case (), replace, mode);
596
- add_quantified_variable (if_expression.false_case (), replace, mode);
592
+ auto &if_expression = to_if_expr (expression);
593
+ add_quantified_variable (if_expression.cond (), mode);
594
+ add_quantified_variable (if_expression.true_case (), mode);
595
+ add_quantified_variable (if_expression.false_case (), mode);
597
596
}
598
597
if (expression.id () == ID_and || expression.id () == ID_or)
599
598
{
600
599
// For multi-ary connectives, recursively check for
601
600
// nested quantified formulae in all terms
602
- const auto &multi_ary_expression = to_multi_ary_expr (expression);
603
- for (const auto &operand : multi_ary_expression.operands ())
601
+ auto &multi_ary_expression = to_multi_ary_expr (expression);
602
+ for (auto &operand : multi_ary_expression.operands ())
604
603
{
605
- add_quantified_variable (operand, replace, mode);
604
+ add_quantified_variable (operand, mode);
606
605
}
607
606
}
608
607
else if (expression.id () == ID_exists || expression.id () == ID_forall)
609
608
{
610
- // When a quantifier expression is found,
611
- // for each quantified variable ...
612
- const auto &quantifier_expression = to_quantifier_expr (expression);
609
+ // When a quantifier expression is found, create a fresh symbol for each
610
+ // quantified variable and rewrite the expression to use those fresh
611
+ // symbols.
612
+ auto &quantifier_expression = to_quantifier_expr (expression);
613
+ std::vector<symbol_exprt> fresh_variables;
614
+ fresh_variables.reserve (quantifier_expression.variables ().size ());
613
615
for (const auto &quantified_variable : quantifier_expression.variables ())
614
616
{
615
- const auto &quantified_symbol = to_symbol_expr (quantified_variable);
616
-
617
617
// 1. create fresh symbol
618
618
symbolt new_symbol = new_tmp_symbol (
619
- quantified_symbol .type (),
620
- quantified_symbol .source_location (),
619
+ quantified_variable .type (),
620
+ quantified_variable .source_location (),
621
621
mode,
622
622
symbol_table);
623
623
624
624
// 2. add created fresh symbol to expression map
625
- symbol_exprt q (
626
- quantified_symbol.get_identifier (), quantified_symbol.type ());
627
- replace.insert (q, new_symbol.symbol_expr ());
628
-
629
- // 3. recursively check for nested quantified formulae
630
- add_quantified_variable (quantifier_expression.where (), replace, mode);
625
+ fresh_variables.push_back (new_symbol.symbol_expr ());
631
626
}
627
+
628
+ // use fresh symbols
629
+ exprt where = quantifier_expression.instantiate (fresh_variables);
630
+
631
+ // recursively check for nested quantified formulae
632
+ add_quantified_variable (where, mode);
633
+
634
+ // replace previous variables and body
635
+ quantifier_expression.variables () = fresh_variables;
636
+ quantifier_expression.where () = std::move (where);
632
637
}
633
638
}
634
639
@@ -831,9 +836,9 @@ void code_contractst::apply_function_contract(
831
836
// Insert assertion of the precondition immediately before the call site.
832
837
if (!requires.is_true ())
833
838
{
834
- replace_symbolt replace (common_replace);
835
- code_contractst:: add_quantified_variable (requires, replace , mode);
836
- replace (requires);
839
+ if ( has_subexpr (requires, ID_exists) || has_subexpr (requires, ID_forall))
840
+ add_quantified_variable (requires, mode);
841
+ common_replace (requires);
837
842
838
843
goto_programt assertion;
839
844
converter.goto_convert (code_assertt (requires), assertion, mode);
@@ -852,9 +857,9 @@ void code_contractst::apply_function_contract(
852
857
std::pair<goto_programt, goto_programt> ensures_pair;
853
858
if (!ensures.is_false ())
854
859
{
855
- replace_symbolt replace (common_replace);
856
- code_contractst:: add_quantified_variable (ensures, replace , mode);
857
- replace (ensures);
860
+ if ( has_subexpr (ensures, ID_exists) || has_subexpr (ensures, ID_forall))
861
+ add_quantified_variable (ensures, mode);
862
+ common_replace (ensures);
858
863
859
864
auto assumption = code_assumet (ensures);
860
865
ensures_pair =
@@ -1430,12 +1435,9 @@ void code_contractst::add_contract_check(
1430
1435
// Generate: assume(requires)
1431
1436
if (!requires.is_false ())
1432
1437
{
1433
- // extend common_replace with quantified variables in REQUIRES,
1434
- // and then do the replacement
1435
- replace_symbolt replace (common_replace);
1436
- code_contractst::add_quantified_variable (
1437
- requires, replace, function_symbol.mode );
1438
- replace (requires);
1438
+ if (has_subexpr (requires, ID_exists) || has_subexpr (requires, ID_forall))
1439
+ add_quantified_variable (requires, function_symbol.mode );
1440
+ common_replace (requires);
1439
1441
1440
1442
goto_programt assumption;
1441
1443
converter.goto_convert (
@@ -1450,12 +1452,9 @@ void code_contractst::add_contract_check(
1450
1452
// Generate: copies for history variables
1451
1453
if (!ensures.is_true ())
1452
1454
{
1453
- // extend common_replace with quantified variables in ENSURES,
1454
- // and then do the replacement
1455
- replace_symbolt replace (common_replace);
1456
- code_contractst::add_quantified_variable (
1457
- ensures, replace, function_symbol.mode );
1458
- replace (ensures);
1455
+ if (has_subexpr (ensures, ID_exists) || has_subexpr (ensures, ID_forall))
1456
+ add_quantified_variable (ensures, function_symbol.mode );
1457
+ common_replace (ensures);
1459
1458
1460
1459
// get all the relevant instructions related to history variables
1461
1460
auto assertion = code_assertt (ensures);
0 commit comments