@@ -140,9 +140,6 @@ void code_contractst::check_apply_loop_contracts(
140
140
generated_code,
141
141
ID_loop_entry);
142
142
143
- // Create 'loop_entry' history variables
144
- insert_before_swap_and_advance (goto_function.body , loop_head, generated_code);
145
-
146
143
// Generate: assert(invariant) just before the loop
147
144
// We use a block scope to create a temporary assertion,
148
145
// and immediately convert it to goto instructions.
@@ -154,6 +151,14 @@ void code_contractst::check_apply_loop_contracts(
154
151
" Check loop invariant before entry" );
155
152
}
156
153
154
+ // Add 'loop_entry' history variables and base case assertion.
155
+ // These variables are local and thus
156
+ // need not be checked against the enclosing scope's write set.
157
+ insert_before_swap_and_advance (
158
+ goto_function.body ,
159
+ loop_head,
160
+ add_pragma_disable_assigns_check (generated_code));
161
+
157
162
// havoc the variables that may be modified
158
163
modifiest modifies;
159
164
if (assigns.is_nil ())
@@ -176,7 +181,8 @@ void code_contractst::check_apply_loop_contracts(
176
181
for (const auto &target : assigns.operands ())
177
182
modifies.insert (target);
178
183
179
- // create snapshots of the CARs -- must be done before havocing
184
+ // Create snapshots of write set CARs.
185
+ // This must be done before havocing the write set.
180
186
for (const auto &car : loop_assigns.get_write_set ())
181
187
{
182
188
auto snapshot_instructions = car.generate_snapshot_instructions ();
@@ -188,7 +194,17 @@ void code_contractst::check_apply_loop_contracts(
188
194
havoc_assigns_targetst havoc_gen (modifies, ns);
189
195
havoc_gen.append_full_havoc_code (
190
196
loop_head->source_location (), generated_code);
191
- insert_before_swap_and_advance (goto_function.body , loop_head, generated_code);
197
+
198
+ // Add the havocing code, but only check against the enclosing scope's
199
+ // write set if it was manually specified.
200
+ if (assigns.is_nil ())
201
+ insert_before_swap_and_advance (
202
+ goto_function.body ,
203
+ loop_head,
204
+ add_pragma_disable_assigns_check (generated_code));
205
+ else
206
+ insert_before_swap_and_advance (
207
+ goto_function.body , loop_head, generated_code);
192
208
193
209
// Generate: assume(invariant) just after havocing
194
210
// We use a block scope to create a temporary assumption,
@@ -726,7 +742,6 @@ void code_contractst::instrument_assign_statement(
726
742
instruction_it->is_assign (),
727
743
" The first instruction of instrument_assign_statement should always be"
728
744
" an assignment" );
729
-
730
745
add_inclusion_check (
731
746
program, assigns_clause, instruction_it, instruction_it->assign_lhs ());
732
747
}
@@ -816,7 +831,9 @@ void code_contractst::instrument_call_statement(
816
831
817
832
alias_checking_instructions.destructive_append (skip_program);
818
833
insert_before_swap_and_advance (
819
- body, instruction_it, alias_checking_instructions);
834
+ body,
835
+ instruction_it,
836
+ add_pragma_disable_assigns_check (alias_checking_instructions));
820
837
821
838
// move past the call and then insert the invalidation instructions
822
839
instruction_it++;
@@ -848,7 +865,9 @@ void code_contractst::instrument_call_statement(
848
865
849
866
invalidation_instructions.destructive_append (skip_program);
850
867
insert_before_swap_and_advance (
851
- body, instruction_it, invalidation_instructions);
868
+ body,
869
+ instruction_it,
870
+ add_pragma_disable_assigns_check (invalidation_instructions));
852
871
853
872
instruction_it--;
854
873
}
@@ -985,6 +1004,14 @@ void code_contractst::check_frame_conditions(
985
1004
986
1005
for (; instruction_it != instruction_end; ++instruction_it)
987
1006
{
1007
+ const auto &pragmas = instruction_it->source_location ().get_pragmas ();
1008
+ if (pragmas.find (CONTRACT_PRAGMA_DISABLE_ASSIGNS_CHECK) != pragmas.end ())
1009
+ continue ;
1010
+
1011
+ // do not instrument this instruction again in the future,
1012
+ // since we are going to instrument it now below.
1013
+ add_pragma_disable_assigns_check (*instruction_it);
1014
+
988
1015
if (instruction_it->is_decl ())
989
1016
{
990
1017
// grab the declared symbol
0 commit comments