@@ -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,15 +213,13 @@ 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
- // 1.1 create fresh symbol
222
+ // 1. create fresh symbol
225
223
symbolt new_symbol = get_fresh_aux_symbol (
226
224
quantified_symbol.type (),
227
225
id2string (quantified_symbol.get_identifier ()),
@@ -230,12 +228,12 @@ void code_contractst::add_quantified_variable(
230
228
mode,
231
229
symbol_table);
232
230
233
- // 1.2 add created fresh symbol to expression map
231
+ // 2. add created fresh symbol to expression map
234
232
symbol_exprt q (
235
233
quantified_symbol.get_identifier (), quantified_symbol.type ());
236
234
replace.insert (q, new_symbol.symbol_expr ());
237
235
238
- // 1.3 recursively check for nested quantified formulae
236
+ // 3. recursively check for nested quantified formulae
239
237
add_quantified_variable (quantifier_expression.where (), replace, mode);
240
238
}
241
239
}
@@ -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,29 @@ 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
409
+ // ASSIGNS clause should not refer to any quantified variables,
410
+ // and only refer to the common symbols to be replaced.
411
+ common_replace (assigns);
412
+
411
413
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
414
415
- // Replace expressions in the contract components.
416
- replace (assigns);
417
- replace (requires );
418
- replace (ensures);
415
+ // Add quantified variables in contracts to the symbol map
416
+ // and create replacement maps for ENSURES and REQUIRES,
417
+ // which independently extend common_replace.
418
+ {
419
+ replace_symbolt replace (common_replace);
420
+ code_contractst::add_quantified_variable (ensures, replace, mode);
421
+ replace (requires );
422
+ }
423
+ {
424
+ replace_symbolt replace (common_replace);
425
+ code_contractst::add_quantified_variable (requires , replace, mode);
426
+ replace (ensures);
427
+ }
419
428
420
429
// Insert assertion of the precondition immediately before the call site.
421
430
if (requires .is_not_nil ())
0 commit comments