@@ -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,14 @@ 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
+ new_program. destructive_append ( ensures_pair.first );
912
915
}
913
916
914
917
// Kill return value variable if fresh
@@ -921,11 +924,19 @@ void code_contractst::apply_function_contract(
921
924
++target;
922
925
}
923
926
927
+ is_fresh.add_memory_map_dead (new_program);
928
+
924
929
// Erase original function call
925
930
*target = goto_programt::make_skip ();
926
931
932
+ // insert contract replacement instructions
933
+ insert_before_swap_and_advance (function_body, target, new_program);
934
+
927
935
// Add this function to the set of replaced functions.
928
936
summarized.insert (target_function);
937
+
938
+ // restore global goto_program consistency
939
+ goto_functions.update ();
929
940
}
930
941
931
942
void code_contractst::apply_loop_contract (
@@ -1450,7 +1461,7 @@ void code_contractst::add_contract_check(
1450
1461
1451
1462
is_fresh_enforcet visitor (*this , log , wrapper_function);
1452
1463
visitor.create_declarations ();
1453
-
1464
+ visitor. add_memory_map_decl (check);
1454
1465
// Generate: assume(requires)
1455
1466
if (!requires.is_false ())
1456
1467
{
@@ -1513,9 +1524,17 @@ void code_contractst::add_contract_check(
1513
1524
return_stmt.value ().return_value (), skip->source_location ()));
1514
1525
}
1515
1526
1516
- // prepend the new code to dest
1527
+ // kill the is_fresh memory map
1528
+ visitor.add_memory_map_dead (check);
1529
+
1530
+ // add final instruction
1517
1531
check.destructive_append (tmp_skip);
1532
+
1533
+ // prepend the new code to dest
1518
1534
dest.destructive_insert (dest.instructions .begin (), check);
1535
+
1536
+ // restore global goto_program consistency
1537
+ goto_functions.update ();
1519
1538
}
1520
1539
1521
1540
void code_contractst::check_all_functions_found (
0 commit comments