@@ -172,9 +172,9 @@ bool code_contractst::has_contract(const irep_idt fun_name)
172
172
}
173
173
174
174
void code_contractst::add_quantified_variable (
175
- exprt expression,
175
+ const exprt & expression,
176
176
replace_symbolt &replace,
177
- irep_idt mode)
177
+ const irep_idt & mode)
178
178
{
179
179
if (expression.id () == ID_not || expression.id () == ID_typecast)
180
180
{
@@ -213,12 +213,10 @@ void code_contractst::add_quantified_variable(
213
213
else if (expression.id () == ID_exists || expression.id () == ID_forall)
214
214
{
215
215
// When a quantifier expression is found,
216
- // 1. get quantified variables
216
+ // for each quantified variable ...
217
217
const auto &quantifier_expression = to_quantifier_expr (expression);
218
- const auto &quantified_variables = quantifier_expression.variables ();
219
- for (const auto &quantified_variable : quantified_variables)
218
+ for (const auto &quantified_variable : quantifier_expression.variables ())
220
219
{
221
- // for each quantified variable...
222
220
const auto &quantified_symbol = to_symbol_expr (quantified_variable);
223
221
224
222
// 1.1 create fresh symbol
@@ -356,7 +354,8 @@ bool code_contractst::apply_function_contract(
356
354
357
355
// Create a replace_symbolt object, for replacing expressions in the callee
358
356
// with expressions from the call site (e.g. the return value).
359
- replace_symbolt replace;
357
+ // This object tracks replacements that are common to both ENSURES and REQUIRES.
358
+ replace_symbolt common_replace;
360
359
if (type.return_type () != empty_typet ())
361
360
{
362
361
// Check whether the function's return value is not disregarded.
@@ -367,7 +366,7 @@ bool code_contractst::apply_function_contract(
367
366
// rewrite calls to foo as follows:
368
367
// x = foo() -> assume(__CPROVER_return_value > 5) -> assume(x > 5)
369
368
symbol_exprt ret_val (CPROVER_PREFIX " return_value" , call.lhs ().type ());
370
- replace .insert (ret_val, call.lhs ());
369
+ common_replace .insert (ret_val, call.lhs ());
371
370
}
372
371
else
373
372
{
@@ -388,7 +387,7 @@ bool code_contractst::apply_function_contract(
388
387
ns,
389
388
symbol_table);
390
389
symbol_exprt ret_val (CPROVER_PREFIX " return_value" , type.return_type ());
391
- replace .insert (ret_val, fresh.symbol_expr ());
390
+ common_replace .insert (ret_val, fresh.symbol_expr ());
392
391
}
393
392
}
394
393
}
@@ -403,19 +402,25 @@ bool code_contractst::apply_function_contract(
403
402
if (!p_it->get_identifier ().empty ())
404
403
{
405
404
symbol_exprt p (p_it->get_identifier (), p_it->type ());
406
- replace .insert (p, *a_it);
405
+ common_replace .insert (p, *a_it);
407
406
}
408
407
}
409
408
410
- // Add quantified variables in contracts to the symbol map
411
409
irep_idt mode = symbol_table.lookup_ref (function).mode ;
412
- code_contractst::add_quantified_variable (ensures, replace, mode);
413
- code_contractst::add_quantified_variable (requires , replace, mode);
414
410
415
- // Replace expressions in the contract components.
416
- replace (assigns);
417
- replace (requires );
418
- replace (ensures);
411
+ // Add quantified variables in contracts to the symbol map
412
+ // and create replacement maps for ENSURES and REQUIRES,
413
+ // which independently extend common_replace.
414
+ {
415
+ replace_symbolt replace (common_replace);
416
+ code_contractst::add_quantified_variable (ensures, replace, mode);
417
+ replace (requires );
418
+ }
419
+ {
420
+ replace_symbolt replace (common_replace);
421
+ code_contractst::add_quantified_variable (requires , replace, mode);
422
+ replace (ensures);
423
+ }
419
424
420
425
// Insert assertion of the precondition immediately before the call site.
421
426
if (requires .is_not_nil ())
0 commit comments