Skip to content

Commit 10c5daf

Browse files
committed
goto_check: use a functor to guard the assertions
Original code by @kroening in branch `goto_check_guard`.
1 parent 1129e66 commit 10c5daf

File tree

1 file changed

+57
-42
lines changed

1 file changed

+57
-42
lines changed

src/analyses/goto_check_c.cpp

Lines changed: 57 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ Author: Daniel Kroening, [email protected]
4242
#include <goto-programs/goto_model.h>
4343
#include <goto-programs/remove_skip.h>
4444

45-
#include "guard.h"
4645
#include "local_bitvector_analysis.h"
4746

4847
class goto_check_ct
@@ -101,17 +100,19 @@ class goto_check_ct
101100
const namespacet &ns;
102101
std::unique_ptr<local_bitvector_analysist> local_bitvector_analysis;
103102
goto_programt::const_targett current_target;
104-
guard_managert guard_manager;
105103
messaget log;
106104

107105
bool no_enum_check;
108106

107+
using guardt = std::function<exprt(exprt)>;
108+
const guardt identity = [](exprt expr) { return expr; };
109+
109110
/// Check an address-of expression:
110111
/// if it is a dereference then check the pointer
111112
/// if it is an index then address-check the array and then check the index
112113
/// \param expr: the expression to be checked
113-
/// \param guard: the condition for the check (unmodified here)
114-
void check_rec_address(const exprt &expr, guardt &guard);
114+
/// \param guard: the condition for the check
115+
void check_rec_address(const exprt &expr, const guardt &guard);
115116

116117
/// Check a logical operation: check each operand in separation while
117118
/// extending the guarding condition as follows.
@@ -120,15 +121,15 @@ class goto_check_ct
120121
/// \param expr: the expression to be checked
121122
/// \param guard: the condition for the check (extended with the previous
122123
/// operands (or their negations) for recursively calls)
123-
void check_rec_logical_op(const exprt &expr, guardt &guard);
124+
void check_rec_logical_op(const exprt &expr, const guardt &guard);
124125

125126
/// Check an if expression: check the if-condition alone, and then check the
126127
/// true/false-cases with the guard extended with if-condition and it's
127128
/// negation, respectively.
128129
/// \param if_expr: the expression to be checked
129130
/// \param guard: the condition for the check (extended with the (negation of
130131
/// the) if-condition for recursively calls)
131-
void check_rec_if(const if_exprt &if_expr, guardt &guard);
132+
void check_rec_if(const if_exprt &if_expr, const guardt &guard);
132133

133134
/// Check that a member expression is valid:
134135
/// - check the structure this expression is a member of (via pointer of its
@@ -137,29 +138,29 @@ class goto_check_ct
137138
/// `s->member' to avoid checking safety of `s'
138139
/// - check all operands of the expression
139140
/// \param member: the expression to be checked
140-
/// \param guard: the condition for the check (unmodified here)
141+
/// \param guard: the condition for the check
141142
/// \return true if no more checks are required for \p member or its
142143
/// sub-expressions
143-
bool check_rec_member(const member_exprt &member, guardt &guard);
144+
bool check_rec_member(const member_exprt &member, const guardt &guard);
144145

145146
/// Check that a division is valid: check for division by zero, overflow and
146147
/// NaN (for floating point numbers).
147148
/// \param div_expr: the expression to be checked
148-
/// \param guard: the condition for the check (unmodified here)
149-
void check_rec_div(const div_exprt &div_expr, guardt &guard);
149+
/// \param guard: the condition for the check
150+
void check_rec_div(const div_exprt &div_expr, const guardt &guard);
150151

151152
/// Check that an arithmetic operation is valid: overflow check, NaN-check
152153
/// (for floating point numbers), and pointer overflow check.
153154
/// \param expr: the expression to be checked
154-
/// \param guard: the condition for the check (unmodified here)
155-
void check_rec_arithmetic_op(const exprt &expr, guardt &guard);
155+
/// \param guard: the condition for the check
156+
void check_rec_arithmetic_op(const exprt &expr, const guardt &guard);
156157

157158
/// Recursively descend into \p expr and run the appropriate check for each
158159
/// sub-expression, while collecting the condition for the check in \p
159160
/// guard.
160161
/// \param expr: the expression to be checked
161162
/// \param guard: the condition for when the check should be made
162-
void check_rec(const exprt &expr, guardt &guard);
163+
void check_rec(const exprt &expr, const guardt &guard);
163164

164165
/// Initiate the recursively analysis of \p expr with its `guard' set to TRUE.
165166
/// \param expr: the expression to be checked
@@ -338,6 +339,21 @@ class goto_check_ct
338339
named_check_statust match_named_check(const irep_idt &named_check) const;
339340
};
340341

342+
static exprt implication(exprt lhs, exprt rhs)
343+
{
344+
// rewrite a => (b => c) to (a && b) => c
345+
if (rhs.id() == ID_implies)
346+
{
347+
const auto &rhs_implication = to_implies_expr(rhs);
348+
return implies_exprt(
349+
and_exprt(std::move(lhs), rhs_implication.lhs()),
350+
rhs_implication.rhs()
351+
);
352+
} else {
353+
return implies_exprt(std::move(lhs), std::move(rhs));
354+
}
355+
}
356+
341357
void goto_check_ct::collect_allocations(const goto_functionst &goto_functions)
342358
{
343359
for(const auto &gf_entry : goto_functions.function_map)
@@ -1601,10 +1617,7 @@ void goto_check_ct::add_guarded_property(
16011617
return;
16021618

16031619
// add the guard
1604-
exprt guarded_expr =
1605-
guard.is_true()
1606-
? std::move(simplified_expr)
1607-
: implies_exprt{guard.as_expr(), std::move(simplified_expr)};
1620+
exprt guarded_expr = guard(simplified_expr);
16081621

16091622
if(assertions.insert(std::make_pair(src_expr, guarded_expr)).second)
16101623
{
@@ -1625,7 +1638,7 @@ void goto_check_ct::add_guarded_property(
16251638
}
16261639
}
16271640

1628-
void goto_check_ct::check_rec_address(const exprt &expr, guardt &guard)
1641+
void goto_check_ct::check_rec_address(const exprt &expr, const guardt &guard)
16291642
{
16301643
// we don't look into quantifiers
16311644
if(expr.id() == ID_exists || expr.id() == ID_forall)
@@ -1648,15 +1661,15 @@ void goto_check_ct::check_rec_address(const exprt &expr, guardt &guard)
16481661
}
16491662
}
16501663

1651-
void goto_check_ct::check_rec_logical_op(const exprt &expr, guardt &guard)
1664+
void goto_check_ct::check_rec_logical_op(const exprt &expr, const guardt &guard)
16521665
{
16531666
PRECONDITION(
16541667
expr.id() == ID_and || expr.id() == ID_or || expr.id() == ID_implies);
16551668
INVARIANT(
16561669
expr.is_boolean(),
16571670
"'" + expr.id_string() + "' must be Boolean, but got " + expr.pretty());
16581671

1659-
guardt old_guard = guard;
1672+
exprt::operandst constraints;
16601673

16611674
for(const auto &op : expr.operands())
16621675
{
@@ -1665,14 +1678,17 @@ void goto_check_ct::check_rec_logical_op(const exprt &expr, guardt &guard)
16651678
"'" + expr.id_string() + "' takes Boolean operands only, but got " +
16661679
op.pretty());
16671680

1668-
check_rec(op, guard);
1669-
guard.add(expr.id() == ID_or ? boolean_negate(op) : op);
1670-
}
1681+
auto new_guard = [&guard, &constraints](exprt expr) {
1682+
return guard(implication(conjunction(constraints), expr));
1683+
};
16711684

1672-
guard = std::move(old_guard);
1685+
check_rec(op, new_guard);
1686+
1687+
constraints.push_back(expr.id() == ID_or ? boolean_negate(op) : op);
1688+
}
16731689
}
16741690

1675-
void goto_check_ct::check_rec_if(const if_exprt &if_expr, guardt &guard)
1691+
void goto_check_ct::check_rec_if(const if_exprt &if_expr, const guardt &guard)
16761692
{
16771693
INVARIANT(
16781694
if_expr.cond().is_boolean(),
@@ -1681,21 +1697,21 @@ void goto_check_ct::check_rec_if(const if_exprt &if_expr, guardt &guard)
16811697
check_rec(if_expr.cond(), guard);
16821698

16831699
{
1684-
guardt old_guard = guard;
1685-
guard.add(if_expr.cond());
1686-
check_rec(if_expr.true_case(), guard);
1687-
guard = std::move(old_guard);
1700+
auto new_guard = [&guard, &if_expr](exprt expr) {
1701+
return guard(implication(if_expr.cond(), std::move(expr)));
1702+
};
1703+
check_rec(if_expr.true_case(), new_guard);
16881704
}
16891705

16901706
{
1691-
guardt old_guard = guard;
1692-
guard.add(not_exprt{if_expr.cond()});
1693-
check_rec(if_expr.false_case(), guard);
1694-
guard = std::move(old_guard);
1707+
auto new_guard = [&guard, &if_expr](exprt expr) {
1708+
return guard(implication(not_exprt(if_expr.cond()), std::move(expr)));
1709+
};
1710+
check_rec(if_expr.false_case(), new_guard);
16951711
}
16961712
}
16971713

1698-
bool goto_check_ct::check_rec_member(const member_exprt &member, guardt &guard)
1714+
bool goto_check_ct::check_rec_member(const member_exprt &member, const guardt &guard)
16991715
{
17001716
const dereference_exprt &deref = to_dereference_expr(member.struct_op());
17011717

@@ -1733,7 +1749,7 @@ bool goto_check_ct::check_rec_member(const member_exprt &member, guardt &guard)
17331749
return false;
17341750
}
17351751

1736-
void goto_check_ct::check_rec_div(const div_exprt &div_expr, guardt &guard)
1752+
void goto_check_ct::check_rec_div(const div_exprt &div_expr, const guardt &guard)
17371753
{
17381754
div_by_zero_check(to_div_expr(div_expr), guard);
17391755

@@ -1746,7 +1762,7 @@ void goto_check_ct::check_rec_div(const div_exprt &div_expr, guardt &guard)
17461762
}
17471763
}
17481764

1749-
void goto_check_ct::check_rec_arithmetic_op(const exprt &expr, guardt &guard)
1765+
void goto_check_ct::check_rec_arithmetic_op(const exprt &expr, const guardt &guard)
17501766
{
17511767
if(expr.type().id() == ID_signedbv || expr.type().id() == ID_unsignedbv)
17521768
{
@@ -1771,12 +1787,12 @@ void goto_check_ct::check_rec_arithmetic_op(const exprt &expr, guardt &guard)
17711787
}
17721788
}
17731789

1774-
void goto_check_ct::check_rec(const exprt &expr, guardt &guard)
1790+
void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
17751791
{
17761792
// we don't look into quantifiers
17771793
if(expr.id() == ID_exists || expr.id() == ID_forall)
17781794
return;
1779-
1795+
17801796
if(expr.id() == ID_address_of)
17811797
{
17821798
check_rec_address(to_address_of_expr(expr).object(), guard);
@@ -1855,8 +1871,7 @@ void goto_check_ct::check_rec(const exprt &expr, guardt &guard)
18551871

18561872
void goto_check_ct::check(const exprt &expr)
18571873
{
1858-
guardt guard{true_exprt{}, guard_manager};
1859-
check_rec(expr, guard);
1874+
check_rec(expr, identity);
18601875
}
18611876

18621877
/// expand the r_ok, w_ok and rw_ok predicates
@@ -2157,7 +2172,7 @@ void goto_check_ct::goto_check(
21572172
"pointer dereference",
21582173
i.source_location(),
21592174
pointer,
2160-
guardt(true_exprt(), guard_manager));
2175+
identity);
21612176
}
21622177

21632178
// this has no successor
@@ -2253,7 +2268,7 @@ void goto_check_ct::goto_check(
22532268
"memory-leak",
22542269
source_location,
22552270
eq,
2256-
guardt(true_exprt(), guard_manager));
2271+
identity);
22572272
}
22582273
}
22592274

0 commit comments

Comments
 (0)