Skip to content

Commit e675709

Browse files
committed
Add a partial-skolemization (bound-variable renaming) module in goto-programs.
That allows us to do a bound-variables renaming early in `process-goto-programs`, which then allows us to not have problems with clashing identifiers later on. This performs only partial-skolemisation (doesn't eliminate the quantifier, but renames the bound variables) because for the correct operation of VCCs we need to preserve the exists statement.
1 parent d821c53 commit e675709

File tree

5 files changed

+104
-1
lines changed

5 files changed

+104
-1
lines changed

regression/cbmc-primitives/exists_memory_checks/negated_exists.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
CORE
2-
valid_index_range.c
2+
negated_exists.c
33
--pointer-check
44
^EXIT=0$
55
^SIGNAL=0$

src/goto-programs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ SRC = allocate_objects.cpp \
6565
show_goto_functions_xml.cpp \
6666
show_properties.cpp \
6767
show_symbol_table.cpp \
68+
skolemization.cpp \
6869
slice_global_inits.cpp \
6970
string_abstraction.cpp \
7071
string_instrumentation.cpp \

src/goto-programs/process_goto_program.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Author: Martin Brain, [email protected]
2323
#include <goto-programs/remove_returns.h>
2424
#include <goto-programs/remove_vector.h>
2525
#include <goto-programs/rewrite_union.h>
26+
#include <goto-programs/skolemization.h>
2627
#include <goto-programs/string_abstraction.h>
2728
#include <goto-programs/string_instrumentation.h>
2829

@@ -64,6 +65,8 @@ bool process_goto_program(
6465
if(options.get_bool_option("rewrite-union"))
6566
rewrite_union(goto_model);
6667

68+
rename_variables_in_existential_quantifiers(goto_model);
69+
6770
// add generic checks
6871
log.status() << "Generic Property Instrumentation" << messaget::eom;
6972
goto_check(options, goto_model);

src/goto-programs/skolemization.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/// \file skolemization.h
2+
/// Rename variables in existentially quantified statements.
3+
/// Author: Diffblue Ltd.
4+
5+
#include "skolemization.h"
6+
7+
#include "goto_model.h"
8+
9+
#include <ansi-c/expr2c.h>
10+
11+
#include <util/expr_util.h>
12+
#include <util/fresh_symbol.h>
13+
#include <util/irep.h> // for id2string
14+
#include <util/mathematical_expr.h>
15+
16+
void rename_variables_in_existential_quantifiers(goto_modelt &goto_model)
17+
{
18+
for(auto &function : goto_model.goto_functions.function_map)
19+
{
20+
for(auto &instruction : function.second.body.instructions)
21+
{
22+
if(instruction.has_condition())
23+
{
24+
auto &cond = instruction.condition_nonconst();
25+
recurse_on_condition(cond, goto_model);
26+
}
27+
}
28+
}
29+
}
30+
31+
void recurse_on_condition(exprt &cond, goto_modelt &model)
32+
{
33+
// recurse on the condition's subexpressions first - that allows us
34+
// to correctly identify the nodes we care about in a compound
35+
// expression, for instance something like `1 == 1 && exists(i.i>=0 && i>1)`
36+
for(exprt &subexpr : cond.operands())
37+
{
38+
recurse_on_condition(subexpr, model);
39+
}
40+
41+
// if the expression we're in doesn't have any more operands,
42+
// it means it's a leaf node, so we go ahead and process it.
43+
rename_and_substitute(cond, model);
44+
}
45+
46+
void rename_and_substitute(exprt &cond, goto_modelt &model)
47+
{
48+
// perform the first part of skolemisation, by identifying an existentially
49+
// quantified statement and substituting the variables with skolem constants.
50+
if(can_cast_expr<exists_exprt>(cond))
51+
{
52+
quantifier_exprt &quantifier_expr = to_quantifier_expr(cond);
53+
const auto &quantifier_sym = quantifier_expr.symbol();
54+
55+
const auto new_symbol = get_fresh_aux_symbol(
56+
quantifier_sym.type(),
57+
CPROVER_PREFIX,
58+
id2string(
59+
model.symbol_table.lookup(quantifier_sym.get_identifier())->base_name),
60+
quantifier_expr.source_location(),
61+
ID_C,
62+
model.symbol_table);
63+
const auto symbol_expr =
64+
symbol_exprt(new_symbol.name, quantifier_sym.type());
65+
const std::vector<exprt> new_sym_vec{symbol_expr};
66+
67+
cond = exists_exprt(symbol_expr, quantifier_expr.instantiate(new_sym_vec));
68+
}
69+
}

src/goto-programs/skolemization.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// \file skolemization.h
2+
/// Rename variables in existentially quantified statements.
3+
/// Author: Diffblue Ltd.
4+
5+
#ifndef CPROVER_GOTO_PROGRAMS_SKOLEMIZATION_H
6+
#define CPROVER_GOTO_PROGRAMS_SKOLEMIZATION_H
7+
8+
class exprt;
9+
class goto_modelt;
10+
11+
/// Rename bound variables in existential quantifiers. This is the entry
12+
/// point to the module.
13+
/// \param goto_model The goto_model on which we operate. Needed
14+
/// for making changes to the symbol table at variable renaming time.
15+
void rename_variables_in_existential_quantifiers(goto_modelt &goto_model);
16+
17+
/// Helper function that recurses over the condition expression of instructions.
18+
/// \param cond The condition on which we recurse over the operands (subexpressions).
19+
/// \param model The goto_model we are inserting the new symbol to.
20+
void recurse_on_condition(exprt &cond, goto_modelt &model);
21+
22+
/// Helper function that does the actual renaming of the variables.
23+
/// This is called when we reach the atomic parts of the condition expression,
24+
/// to identify and rename the variables of any quantified statements that
25+
/// exist as part of the guard.
26+
/// \param cond The condition in which we are doing the renaming.
27+
/// \param model The goto_model we are inserting the new symbol to.
28+
void rename_and_substitute(exprt &cond, goto_modelt &model);
29+
30+
#endif

0 commit comments

Comments
 (0)