@@ -141,9 +141,6 @@ void code_contractst::check_apply_loop_contracts(
141141 generated_code,
142142 ID_loop_entry);
143143
144- // Create 'loop_entry' history variables
145- insert_before_swap_and_advance (goto_function.body , loop_head, generated_code);
146-
147144 // Generate: assert(invariant) just before the loop
148145 // We use a block scope to create a temporary assertion,
149146 // and immediately convert it to goto instructions.
@@ -155,6 +152,14 @@ void code_contractst::check_apply_loop_contracts(
155152 " Check loop invariant before entry" );
156153 }
157154
155+ // Add 'loop_entry' history variables and base case assertion.
156+ // These variables are local and thus
157+ // need not be checked against the enclosing scope's write set.
158+ insert_before_swap_and_advance (
159+ goto_function.body ,
160+ loop_head,
161+ add_pragma_disable_assigns_check (generated_code));
162+
158163 // havoc the variables that may be modified
159164 modifiest modifies;
160165 if (assigns.is_nil ())
@@ -177,7 +182,8 @@ void code_contractst::check_apply_loop_contracts(
177182 for (const auto &target : assigns.operands ())
178183 modifies.insert (target);
179184
180- // create snapshots of the CARs -- must be done before havocing
185+ // Create snapshots of write set CARs.
186+ // This must be done before havocing the write set.
181187 for (const auto &car : loop_assigns.get_write_set ())
182188 {
183189 auto snapshot_instructions = car.generate_snapshot_instructions ();
@@ -189,7 +195,17 @@ void code_contractst::check_apply_loop_contracts(
189195 havoc_assigns_targetst havoc_gen (modifies, ns);
190196 havoc_gen.append_full_havoc_code (
191197 loop_head->source_location (), generated_code);
192- insert_before_swap_and_advance (goto_function.body , loop_head, generated_code);
198+
199+ // Add the havocing code, but only check against the enclosing scope's
200+ // write set if it was manually specified.
201+ if (assigns.is_nil ())
202+ insert_before_swap_and_advance (
203+ goto_function.body ,
204+ loop_head,
205+ add_pragma_disable_assigns_check (generated_code));
206+ else
207+ insert_before_swap_and_advance (
208+ goto_function.body , loop_head, generated_code);
193209
194210 // Generate: assume(invariant) just after havocing
195211 // We use a block scope to create a temporary assumption,
@@ -744,7 +760,6 @@ void code_contractst::instrument_assign_statement(
744760 instruction_it->is_assign (),
745761 " The first instruction of instrument_assign_statement should always be"
746762 " an assignment" );
747-
748763 add_inclusion_check (
749764 program, assigns_clause, instruction_it, instruction_it->assign_lhs ());
750765}
@@ -834,7 +849,9 @@ void code_contractst::instrument_call_statement(
834849
835850 alias_checking_instructions.destructive_append (skip_program);
836851 insert_before_swap_and_advance (
837- body, instruction_it, alias_checking_instructions);
852+ body,
853+ instruction_it,
854+ add_pragma_disable_assigns_check (alias_checking_instructions));
838855
839856 // move past the call and then insert the invalidation instructions
840857 instruction_it++;
@@ -866,7 +883,9 @@ void code_contractst::instrument_call_statement(
866883
867884 invalidation_instructions.destructive_append (skip_program);
868885 insert_before_swap_and_advance (
869- body, instruction_it, invalidation_instructions);
886+ body,
887+ instruction_it,
888+ add_pragma_disable_assigns_check (invalidation_instructions));
870889
871890 instruction_it--;
872891 }
@@ -1003,6 +1022,14 @@ void code_contractst::check_frame_conditions(
10031022
10041023 for (; instruction_it != instruction_end; ++instruction_it)
10051024 {
1025+ const auto &pragmas = instruction_it->source_location ().get_pragmas ();
1026+ if (pragmas.find (CONTRACT_PRAGMA_DISABLE_ASSIGNS_CHECK) != pragmas.end ())
1027+ continue ;
1028+
1029+ // Do not instrument this instruction again in the future,
1030+ // since we are going to instrument it now below.
1031+ add_pragma_disable_assigns_check (*instruction_it);
1032+
10061033 if (instruction_it->is_decl ())
10071034 {
10081035 // grab the declared symbol
0 commit comments