@@ -114,9 +114,21 @@ void code_contractst::check_apply_invariants(
114114 // build the havocking code
115115 goto_programt havoc_code;
116116
117- // assert the invariant
118- {
119- code_assertt assertion{invariant};
117+ // process quantified variables correctly (introduce a fresh temporary)
118+ // and return a copy of the invariant
119+ const auto &invariant_expr = [&]() {
120+ auto invariant_copy = invariant;
121+ replace_symbolt replace;
122+ code_contractst::add_quantified_variable (invariant_copy, replace, mode);
123+ replace (invariant_copy);
124+ return invariant_copy;
125+ };
126+
127+ // Generate: assert(invariant) just before the loop
128+ // We use a block scope to create a temporary assertion,
129+ // and immediately convert it to goto instructions.
130+ {
131+ code_assertt assertion{invariant_expr ()};
120132 assertion.add_source_location () = loop_head->source_location ;
121133 converter.goto_convert (assertion, havoc_code, mode);
122134 havoc_code.instructions .back ().source_location .set_comment (
@@ -126,10 +138,14 @@ void code_contractst::check_apply_invariants(
126138 // havoc variables being written to
127139 build_havoc_code (loop_head, modifies, havoc_code);
128140
129- // assume the invariant
130- code_assumet assumption{invariant};
131- assumption.add_source_location () = loop_head->source_location ;
132- converter.goto_convert (assumption, havoc_code, mode);
141+ // Generate: assume(invariant) just after havocing
142+ // We use a block scope to create a temporary assumption,
143+ // and immediately convert it to goto instructions.
144+ {
145+ code_assumet assumption{invariant_expr ()};
146+ assumption.add_source_location () = loop_head->source_location ;
147+ converter.goto_convert (assumption, havoc_code, mode);
148+ }
133149
134150 // non-deterministically skip the loop if it is a do-while loop
135151 if (!loop_head->is_goto ())
@@ -143,9 +159,11 @@ void code_contractst::check_apply_invariants(
143159 // Use insert_before_swap to preserve jumps to loop head.
144160 goto_function.body .insert_before_swap (loop_head, havoc_code);
145161
146- // assert the invariant at the end of the loop body
162+ // Generate: assert(invariant) just after the loop exits
163+ // We use a block scope to create a temporary assertion,
164+ // and immediately convert it to goto instructions.
147165 {
148- code_assertt assertion{invariant };
166+ code_assertt assertion{invariant_expr () };
149167 assertion.add_source_location () = loop_end->source_location ;
150168 converter.goto_convert (assertion, havoc_code, mode);
151169 havoc_code.instructions .back ().source_location .set_comment (
0 commit comments