@@ -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,22 @@ 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_history_parameter (
184
+ invariant,
185
+ parameter2history,
186
+ loop_head->source_location ,
187
+ mode,
188
+ history,
189
+ ID_loop_entry);
190
+
191
+ // Create 'loop_entry' history variables
192
+ insert_before_swap_and_advance (goto_function.body , loop_head, history);
193
+
177
194
// Generate: assert(invariant) just before the loop
178
195
// We use a block scope to create a temporary assertion,
179
196
// and immediately convert it to goto instructions.
@@ -375,24 +392,26 @@ void code_contractst::add_quantified_variable(
375
392
}
376
393
}
377
394
378
- void code_contractst::replace_old_parameter (
395
+ void code_contractst::replace_history_parameter (
379
396
exprt &expr,
380
397
std::map<exprt, exprt> ¶meter2history,
381
398
source_locationt location,
382
399
const irep_idt &mode,
383
- goto_programt &history)
400
+ goto_programt &history,
401
+ const irep_idt &id)
384
402
{
385
403
for (auto &op : expr.operands ())
386
404
{
387
- replace_old_parameter (op, parameter2history, location, mode, history);
405
+ replace_history_parameter (
406
+ op, parameter2history, location, mode, history, id);
388
407
}
389
408
390
- if (expr.id () == ID_old)
409
+ if (expr.id () == ID_old || expr. id () == ID_loop_entry )
391
410
{
392
- DATA_INVARIANT (
393
- expr.operands ().size () == 1 , CPROVER_PREFIX " old must have one operand" );
411
+ const auto ¶meter = to_history_expr (expr, id).expression ();
394
412
395
- const auto ¶meter = to_old_expr (expr).expression ();
413
+ DATA_INVARIANT (
414
+ expr.operands ().size () == 1 , " A history variable must have one operand" );
396
415
397
416
if (
398
417
parameter.id () == ID_dereference || parameter.id () == ID_member ||
@@ -426,8 +445,8 @@ void code_contractst::replace_old_parameter(
426
445
}
427
446
else
428
447
{
429
- log .error () << CPROVER_PREFIX " old does not currently support "
430
- << parameter. id () << " expressions." << messaget::eom;
448
+ log .error () << " History variables do not support " << parameter. id ()
449
+ << " expressions." << messaget::eom;
431
450
throw 0 ;
432
451
}
433
452
}
@@ -443,7 +462,8 @@ code_contractst::create_ensures_instruction(
443
462
goto_programt history;
444
463
445
464
// Find and replace "old" expression in the "expression" variable
446
- replace_old_parameter (expression, parameter2history, location, mode, history);
465
+ replace_history_parameter (
466
+ expression, parameter2history, location, mode, history, ID_old);
447
467
448
468
// Create instructions corresponding to the ensures clause
449
469
goto_programt ensures_program;
0 commit comments