Skip to content

Commit 27af620

Browse files
committed
Refactor and cleanup
We do not need to do quantifier replacement within ASSIGNS annotation. The replacement maps for ENSURES and REQUIRES clauses should also be maintained independently.
1 parent 60abd1e commit 27af620

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

src/goto-instrument/code_contracts.cpp

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,9 @@ bool code_contractst::has_contract(const irep_idt fun_name)
172172
}
173173

174174
void code_contractst::add_quantified_variable(
175-
exprt expression,
175+
const exprt &expression,
176176
replace_symbolt &replace,
177-
irep_idt mode)
177+
const irep_idt &mode)
178178
{
179179
if(expression.id() == ID_not || expression.id() == ID_typecast)
180180
{
@@ -213,15 +213,13 @@ void code_contractst::add_quantified_variable(
213213
else if(expression.id() == ID_exists || expression.id() == ID_forall)
214214
{
215215
// When a quantifier expression is found,
216-
// 1. get quantified variables
216+
// for each quantified variable ...
217217
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())
220219
{
221-
// for each quantified variable...
222220
const auto &quantified_symbol = to_symbol_expr(quantified_variable);
223221

224-
// 1.1 create fresh symbol
222+
// 1. create fresh symbol
225223
symbolt new_symbol = get_fresh_aux_symbol(
226224
quantified_symbol.type(),
227225
id2string(quantified_symbol.get_identifier()),
@@ -230,12 +228,12 @@ void code_contractst::add_quantified_variable(
230228
mode,
231229
symbol_table);
232230

233-
// 1.2 add created fresh symbol to expression map
231+
// 2. add created fresh symbol to expression map
234232
symbol_exprt q(
235233
quantified_symbol.get_identifier(), quantified_symbol.type());
236234
replace.insert(q, new_symbol.symbol_expr());
237235

238-
// 1.3 recursively check for nested quantified formulae
236+
// 3. recursively check for nested quantified formulae
239237
add_quantified_variable(quantifier_expression.where(), replace, mode);
240238
}
241239
}
@@ -356,7 +354,8 @@ bool code_contractst::apply_function_contract(
356354

357355
// Create a replace_symbolt object, for replacing expressions in the callee
358356
// 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;
360359
if(type.return_type() != empty_typet())
361360
{
362361
// Check whether the function's return value is not disregarded.
@@ -367,7 +366,7 @@ bool code_contractst::apply_function_contract(
367366
// rewrite calls to foo as follows:
368367
// x = foo() -> assume(__CPROVER_return_value > 5) -> assume(x > 5)
369368
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());
371370
}
372371
else
373372
{
@@ -388,7 +387,7 @@ bool code_contractst::apply_function_contract(
388387
ns,
389388
symbol_table);
390389
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());
392391
}
393392
}
394393
}
@@ -403,19 +402,29 @@ bool code_contractst::apply_function_contract(
403402
if(!p_it->get_identifier().empty())
404403
{
405404
symbol_exprt p(p_it->get_identifier(), p_it->type());
406-
replace.insert(p, *a_it);
405+
common_replace.insert(p, *a_it);
407406
}
408407
}
409408

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+
411413
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);
414414

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+
}
419428

420429
// Insert assertion of the precondition immediately before the call site.
421430
if(requires.is_not_nil())

src/goto-instrument/code_contracts.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,9 @@ class code_contractst
185185
/// the quantified variable is added to the symbol table
186186
/// and to the expression map.
187187
void add_quantified_variable(
188-
exprt expression,
188+
const exprt &expression,
189189
replace_symbolt &replace,
190-
irep_idt mode);
190+
const irep_idt &mode);
191191

192192
/// This function recursively identifies the "old" expressions within expr
193193
/// and replaces them with correspoding history variables.

0 commit comments

Comments
 (0)