@@ -89,10 +89,9 @@ void code_contractst::check_apply_loop_contracts(
89
89
//
90
90
// ... preamble ...
91
91
// ,- initialize loop_entry history vars;
92
- // | entered_loop = false
93
- // loop assigns check | initial_invariant_val = invariant_expr;
94
- // - unchecked, temps | in_base_case = true;
95
- // func assigns check | snapshot (write_set);
92
+ // loop assigns check | entered_loop = false
93
+ // - unchecked, temps | initial_invariant_val = invariant_expr;
94
+ // func assigns check | in_base_case = true;
96
95
// - disabled via pragma | goto HEAD;
97
96
// | STEP:
98
97
// --. | assert (initial_invariant_val);
@@ -104,10 +103,12 @@ void code_contractst::check_apply_loop_contracts(
104
103
// loop assigns check ,- ... eval guard ...
105
104
// + assertions added | if (!guard)
106
105
// func assigns check | goto EXIT;
107
- // - disabled via pragma `- ... loop body ...
106
+ // - disabled via pragma | snapshot (write_set);
107
+ // `- ... loop body ...
108
108
// ,- entered_loop = true
109
109
// | if (in_base_case)
110
110
// | goto STEP;
111
+ // | assert CAR_begin in CAR_end
111
112
// loop assigns check | assert (invariant_expr);
112
113
// - unchecked, temps | new_variant_val = decreases_clause_expr;
113
114
// func assigns check | assert (new_variant_val < old_variant_val);
@@ -256,9 +257,8 @@ void code_contractst::check_apply_loop_contracts(
256
257
257
258
// Insert instrumentation
258
259
// This must be done before havocing the write set.
259
- // FIXME: this is not true for write set targets that
260
- // might depend on other write set targets.
261
- pre_loop_head_instrs.destructive_append (snapshot_instructions);
260
+ goto_function.body .destructive_insert (
261
+ std::next (loop_head), snapshot_instructions);
262
262
263
263
// Insert a jump to the loop head
264
264
// (skipping over the step case initialization code below)
@@ -387,6 +387,17 @@ void code_contractst::check_apply_loop_contracts(
387
387
pre_loop_end_instrs.add (goto_programt::make_goto (
388
388
step_case_target, in_base_case, loop_head_location));
389
389
390
+ // Adding checks that demonstrating that the loop assigns clause is an
391
+ // inductive invariant.
392
+ // CAR_begin should be included in CAR_end
393
+ goto_programt assigns_inductive_check_instrs;
394
+ for (const auto &target : to_havoc)
395
+ {
396
+ instrument_spec_assigns.check_inclusion_induction (
397
+ target, assigns_inductive_check_instrs);
398
+ pre_loop_end_instrs.destructive_append (assigns_inductive_check_instrs);
399
+ }
400
+
390
401
// The following code is only reachable in the step case,
391
402
// i.e., when in_base_case == false,
392
403
// because of the unconditional jump above.
0 commit comments