@@ -820,8 +820,12 @@ void code_contractst::apply_function_contract(
820820
821821 const auto &mode = function_symbol.mode ;
822822
823+ // new program where all contract-derived instructions are added
824+ goto_programt new_program;
825+
823826 is_fresh_replacet is_fresh (*this , log, target_function);
824827 is_fresh.create_declarations ();
828+ is_fresh.add_memory_map_decl (new_program);
825829
826830 // Insert assertion of the precondition immediately before the call site.
827831 if (!requires .is_true ())
@@ -839,7 +843,7 @@ void code_contractst::apply_function_contract(
839843 assertion.instructions .back ().source_location_nonconst ().set_property_class (
840844 ID_precondition);
841845 is_fresh.update_requires (assertion);
842- insert_before_swap_and_advance (function_body, target, assertion);
846+ new_program. destructive_append ( assertion);
843847 }
844848
845849 // Gather all the instructions required to handle history variables
@@ -856,8 +860,7 @@ void code_contractst::apply_function_contract(
856860 create_ensures_instruction (assumption, ensures.source_location (), mode);
857861
858862 // 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 );
861864 }
862865
863866 // ASSIGNS clause should not refer to any quantified variables,
@@ -901,14 +904,14 @@ void code_contractst::apply_function_contract(
901904 }
902905
903906 // 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);
905908
906909 // To remove the function call, insert statements related to the assumption.
907910 // Then, replace the function call with a SKIP statement.
908911 if (!ensures.is_false ())
909912 {
910913 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 );
912915 }
913916
914917 // Kill return value variable if fresh
@@ -921,11 +924,19 @@ void code_contractst::apply_function_contract(
921924 ++target;
922925 }
923926
927+ is_fresh.add_memory_map_dead (new_program);
928+
924929 // Erase original function call
925930 *target = goto_programt::make_skip ();
926931
932+ // insert contract replacement instructions
933+ insert_before_swap_and_advance (function_body, target, new_program);
934+
927935 // Add this function to the set of replaced functions.
928936 summarized.insert (target_function);
937+
938+ // restore global goto_program consistency
939+ goto_functions.update ();
929940}
930941
931942void code_contractst::apply_loop_contract (
@@ -1450,7 +1461,7 @@ void code_contractst::add_contract_check(
14501461
14511462 is_fresh_enforcet visitor (*this , log, wrapper_function);
14521463 visitor.create_declarations ();
1453-
1464+ visitor. add_memory_map_decl (check);
14541465 // Generate: assume(requires)
14551466 if (!requires .is_false ())
14561467 {
@@ -1513,9 +1524,17 @@ void code_contractst::add_contract_check(
15131524 return_stmt.value ().return_value (), skip->source_location ()));
15141525 }
15151526
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
15171531 check.destructive_append (tmp_skip);
1532+
1533+ // prepend the new code to dest
15181534 dest.destructive_insert (dest.instructions .begin (), check);
1535+
1536+ // restore global goto_program consistency
1537+ goto_functions.update ();
15191538}
15201539
15211540void code_contractst::check_all_functions_found (
0 commit comments