@@ -145,6 +145,7 @@ void code_contractst::check_apply_loop_contracts(
145
145
// H: loop;
146
146
// E: ...
147
147
// to
148
+ // process history variables;
148
149
// H: assert(invariant);
149
150
// havoc;
150
151
// assume(invariant);
@@ -174,6 +175,16 @@ void code_contractst::check_apply_loop_contracts(
174
175
return invariant_copy;
175
176
};
176
177
178
+ // Process "loop_entry" history variables
179
+ std::map<exprt, exprt> parameter2history;
180
+ goto_programt history;
181
+
182
+ // Find and replace "loop_entry" expression in the "invariant" expression.
183
+ replace_old_parameter (invariant, parameter2history, loop_head->source_location , mode, history);
184
+
185
+ // Create 'loop_entry' history variables
186
+ insert_before_swap_and_advance (goto_function.body , loop_head, history);
187
+
177
188
// Generate: assert(invariant) just before the loop
178
189
// We use a block scope to create a temporary assertion,
179
190
// and immediately convert it to goto instructions.
@@ -387,10 +398,19 @@ void code_contractst::replace_old_parameter(
387
398
replace_old_parameter (op, parameter2history, location, mode, history);
388
399
}
389
400
390
- if (expr.id () == ID_old)
401
+ if (expr.id () == ID_old ||
402
+ expr.id () == ID_loop_entry)
391
403
{
392
- DATA_INVARIANT (
404
+ if (expr.id () == ID_old)
405
+ {
406
+ DATA_INVARIANT (
393
407
expr.operands ().size () == 1 , CPROVER_PREFIX " old must have one operand" );
408
+ }
409
+ if (expr.id () == ID_loop_entry)
410
+ {
411
+ DATA_INVARIANT (
412
+ expr.operands ().size () == 1 , CPROVER_PREFIX " loop_entry must have one operand" );
413
+ }
394
414
395
415
const auto ¶meter = to_old_expr (expr).expression ();
396
416
@@ -427,9 +447,18 @@ void code_contractst::replace_old_parameter(
427
447
}
428
448
else
429
449
{
430
- log .error () << CPROVER_PREFIX " old does not currently support "
450
+ if (expr.id () == ID_old)
451
+ {
452
+ log .error () << CPROVER_PREFIX " old does not currently support "
431
453
<< parameter.id () << " expressions." << messaget::eom;
432
454
throw 0 ;
455
+ }
456
+ if (expr.id () == ID_loop_entry)
457
+ {
458
+ log .error () << CPROVER_PREFIX " loop_entry does not currently support "
459
+ << parameter.id () << " expressions." << messaget::eom;
460
+ throw 0 ;
461
+ }
433
462
}
434
463
}
435
464
}
0 commit comments