@@ -820,8 +820,12 @@ void code_contractst::apply_function_contract(
820
820
821
821
const auto &mode = function_symbol.mode ;
822
822
823
+ // new program where all contract-derived instructions are added
824
+ goto_programt new_program;
825
+
823
826
is_fresh_replacet is_fresh (*this , log, target_function);
824
827
is_fresh.create_declarations ();
828
+ is_fresh.add_memory_map_decl (new_program);
825
829
826
830
// Insert assertion of the precondition immediately before the call site.
827
831
if (!requires .is_true ())
@@ -839,7 +843,7 @@ void code_contractst::apply_function_contract(
839
843
assertion.instructions .back ().source_location_nonconst ().set_property_class (
840
844
ID_precondition);
841
845
is_fresh.update_requires (assertion);
842
- insert_before_swap_and_advance (function_body, target, assertion);
846
+ new_program. destructive_append ( assertion);
843
847
}
844
848
845
849
// Gather all the instructions required to handle history variables
@@ -856,8 +860,7 @@ void code_contractst::apply_function_contract(
856
860
create_ensures_instruction (assumption, ensures.source_location (), mode);
857
861
858
862
// add all the history variable initialization instructions
859
- // to the goto program
860
- insert_before_swap_and_advance (function_body, target, ensures_pair.second );
863
+ new_program.destructive_append (ensures_pair.second );
861
864
}
862
865
863
866
// ASSIGNS clause should not refer to any quantified variables,
@@ -901,14 +904,15 @@ void code_contractst::apply_function_contract(
901
904
}
902
905
903
906
// Insert havoc instructions immediately before the call site.
904
- insert_before_swap_and_advance (function_body, target, havoc_instructions);
907
+ new_program. destructive_append ( havoc_instructions);
905
908
906
909
// To remove the function call, insert statements related to the assumption.
907
910
// Then, replace the function call with a SKIP statement.
908
911
if (!ensures.is_false ())
909
912
{
910
913
is_fresh.update_ensures (ensures_pair.first );
911
- insert_before_swap_and_advance (function_body, target, ensures_pair.first );
914
+ // insert_before_swap_and_advance(function_body, target, ensures_pair.first);
915
+ new_program.destructive_append (ensures_pair.first );
912
916
}
913
917
914
918
// Kill return value variable if fresh
@@ -921,11 +925,19 @@ void code_contractst::apply_function_contract(
921
925
++target;
922
926
}
923
927
928
+ is_fresh.add_memory_map_dead (new_program);
929
+
924
930
// Erase original function call
925
931
*target = goto_programt::make_skip ();
926
932
933
+ // insert contract replacement instructions
934
+ insert_before_swap_and_advance (function_body, target, new_program);
935
+
927
936
// Add this function to the set of replaced functions.
928
937
summarized.insert (target_function);
938
+
939
+ // restore global goto_program consistency
940
+ goto_functions.update ();
929
941
}
930
942
931
943
void code_contractst::apply_loop_contract (
@@ -1450,7 +1462,7 @@ void code_contractst::add_contract_check(
1450
1462
1451
1463
is_fresh_enforcet visitor (*this , log, wrapper_function);
1452
1464
visitor.create_declarations ();
1453
-
1465
+ visitor. add_memory_map_decl (check);
1454
1466
// Generate: assume(requires)
1455
1467
if (!requires .is_false ())
1456
1468
{
@@ -1513,9 +1525,17 @@ void code_contractst::add_contract_check(
1513
1525
return_stmt.value ().return_value (), skip->source_location ()));
1514
1526
}
1515
1527
1516
- // prepend the new code to dest
1528
+ // kill the is_fresh memory map
1529
+ visitor.add_memory_map_dead (check);
1530
+
1531
+ // add final instruction
1517
1532
check.destructive_append (tmp_skip);
1533
+
1534
+ // prepend the new code to dest
1518
1535
dest.destructive_insert (dest.instructions .begin (), check);
1536
+
1537
+ // restore global goto_program consistency
1538
+ goto_functions.update ();
1519
1539
}
1520
1540
1521
1541
void code_contractst::check_all_functions_found (
0 commit comments