42
42
#include < goto-programs/goto_model.h>
43
43
#include < goto-programs/remove_skip.h>
44
44
45
- #include " guard.h"
46
45
#include " local_bitvector_analysis.h"
47
46
48
47
class goto_check_ct
@@ -101,17 +100,19 @@ class goto_check_ct
101
100
const namespacet &ns;
102
101
std::unique_ptr<local_bitvector_analysist> local_bitvector_analysis;
103
102
goto_programt::const_targett current_target;
104
- guard_managert guard_manager;
105
103
messaget log;
106
104
107
105
bool no_enum_check;
108
106
107
+ using guardt = std::function<exprt(exprt)>;
108
+ const guardt identity = [](exprt expr) { return expr; };
109
+
109
110
// / Check an address-of expression:
110
111
// / if it is a dereference then check the pointer
111
112
// / if it is an index then address-check the array and then check the index
112
113
// / \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);
115
116
116
117
// / Check a logical operation: check each operand in separation while
117
118
// / extending the guarding condition as follows.
@@ -120,15 +121,15 @@ class goto_check_ct
120
121
// / \param expr: the expression to be checked
121
122
// / \param guard: the condition for the check (extended with the previous
122
123
// / 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);
124
125
125
126
// / Check an if expression: check the if-condition alone, and then check the
126
127
// / true/false-cases with the guard extended with if-condition and it's
127
128
// / negation, respectively.
128
129
// / \param if_expr: the expression to be checked
129
130
// / \param guard: the condition for the check (extended with the (negation of
130
131
// / 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);
132
133
133
134
// / Check that a member expression is valid:
134
135
// / - check the structure this expression is a member of (via pointer of its
@@ -137,29 +138,29 @@ class goto_check_ct
137
138
// / `s->member' to avoid checking safety of `s'
138
139
// / - check all operands of the expression
139
140
// / \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
141
142
// / \return true if no more checks are required for \p member or its
142
143
// / 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);
144
145
145
146
// / Check that a division is valid: check for division by zero, overflow and
146
147
// / NaN (for floating point numbers).
147
148
// / \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);
150
151
151
152
// / Check that an arithmetic operation is valid: overflow check, NaN-check
152
153
// / (for floating point numbers), and pointer overflow check.
153
154
// / \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);
156
157
157
158
// / Recursively descend into \p expr and run the appropriate check for each
158
159
// / sub-expression, while collecting the condition for the check in \p
159
160
// / guard.
160
161
// / \param expr: the expression to be checked
161
162
// / \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);
163
164
164
165
// / Initiate the recursively analysis of \p expr with its `guard' set to TRUE.
165
166
// / \param expr: the expression to be checked
@@ -338,6 +339,21 @@ class goto_check_ct
338
339
named_check_statust match_named_check (const irep_idt &named_check) const ;
339
340
};
340
341
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 ()), rhs_implication.rhs ());
350
+ }
351
+ else
352
+ {
353
+ return implies_exprt (std::move (lhs), std::move (rhs));
354
+ }
355
+ }
356
+
341
357
void goto_check_ct::collect_allocations (const goto_functionst &goto_functions)
342
358
{
343
359
for (const auto &gf_entry : goto_functions.function_map )
@@ -1601,10 +1617,7 @@ void goto_check_ct::add_guarded_property(
1601
1617
return ;
1602
1618
1603
1619
// 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);
1608
1621
1609
1622
if (assertions.insert (std::make_pair (src_expr, guarded_expr)).second )
1610
1623
{
@@ -1625,7 +1638,7 @@ void goto_check_ct::add_guarded_property(
1625
1638
}
1626
1639
}
1627
1640
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)
1629
1642
{
1630
1643
// we don't look into quantifiers
1631
1644
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)
1648
1661
}
1649
1662
}
1650
1663
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)
1652
1665
{
1653
1666
PRECONDITION (
1654
1667
expr.id () == ID_and || expr.id () == ID_or || expr.id () == ID_implies);
1655
1668
INVARIANT (
1656
1669
expr.is_boolean (),
1657
1670
" '" + expr.id_string () + " ' must be Boolean, but got " + expr.pretty ());
1658
1671
1659
- guardt old_guard = guard ;
1672
+ exprt::operandst constraints ;
1660
1673
1661
1674
for (const auto &op : expr.operands ())
1662
1675
{
@@ -1665,14 +1678,16 @@ void goto_check_ct::check_rec_logical_op(const exprt &expr, guardt &guard)
1665
1678
" '" + expr.id_string () + " ' takes Boolean operands only, but got " +
1666
1679
op.pretty ());
1667
1680
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)); };
1671
1683
1672
- guard = std::move (old_guard);
1684
+ check_rec (op, new_guard);
1685
+
1686
+ constraints.push_back (expr.id () == ID_or ? boolean_negate (op) : op);
1687
+ }
1673
1688
}
1674
1689
1675
- void goto_check_ct::check_rec_if (const if_exprt &if_expr, guardt &guard)
1690
+ void goto_check_ct::check_rec_if (const if_exprt &if_expr, const guardt &guard)
1676
1691
{
1677
1692
INVARIANT (
1678
1693
if_expr.cond ().is_boolean (),
@@ -1681,21 +1696,21 @@ void goto_check_ct::check_rec_if(const if_exprt &if_expr, guardt &guard)
1681
1696
check_rec (if_expr.cond (), guard);
1682
1697
1683
1698
{
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);
1699
+ auto new_guard = [&guard, &if_expr](exprt expr)
1700
+ { return guard (implication (if_expr.cond (), std::move (expr))); };
1701
+ check_rec (if_expr.true_case (), new_guard);
1688
1702
}
1689
1703
1690
1704
{
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);
1705
+ auto new_guard = [&guard, &if_expr](exprt expr)
1706
+ { return guard (implication (not_exprt (if_expr.cond ()), std::move (expr))); };
1707
+ check_rec (if_expr.false_case (), new_guard);
1695
1708
}
1696
1709
}
1697
1710
1698
- bool goto_check_ct::check_rec_member (const member_exprt &member, guardt &guard)
1711
+ bool goto_check_ct::check_rec_member (
1712
+ const member_exprt &member,
1713
+ const guardt &guard)
1699
1714
{
1700
1715
const dereference_exprt &deref = to_dereference_expr (member.struct_op ());
1701
1716
@@ -1733,7 +1748,9 @@ bool goto_check_ct::check_rec_member(const member_exprt &member, guardt &guard)
1733
1748
return false ;
1734
1749
}
1735
1750
1736
- void goto_check_ct::check_rec_div (const div_exprt &div_expr, guardt &guard)
1751
+ void goto_check_ct::check_rec_div (
1752
+ const div_exprt &div_expr,
1753
+ const guardt &guard)
1737
1754
{
1738
1755
div_by_zero_check (to_div_expr (div_expr), guard);
1739
1756
@@ -1746,7 +1763,9 @@ void goto_check_ct::check_rec_div(const div_exprt &div_expr, guardt &guard)
1746
1763
}
1747
1764
}
1748
1765
1749
- void goto_check_ct::check_rec_arithmetic_op (const exprt &expr, guardt &guard)
1766
+ void goto_check_ct::check_rec_arithmetic_op (
1767
+ const exprt &expr,
1768
+ const guardt &guard)
1750
1769
{
1751
1770
if (expr.type ().id () == ID_signedbv || expr.type ().id () == ID_unsignedbv)
1752
1771
{
@@ -1771,7 +1790,7 @@ void goto_check_ct::check_rec_arithmetic_op(const exprt &expr, guardt &guard)
1771
1790
}
1772
1791
}
1773
1792
1774
- void goto_check_ct::check_rec (const exprt &expr, guardt &guard)
1793
+ void goto_check_ct::check_rec (const exprt &expr, const guardt &guard)
1775
1794
{
1776
1795
// we don't look into quantifiers
1777
1796
if (expr.id () == ID_exists || expr.id () == ID_forall)
@@ -1855,8 +1874,7 @@ void goto_check_ct::check_rec(const exprt &expr, guardt &guard)
1855
1874
1856
1875
void goto_check_ct::check (const exprt &expr)
1857
1876
{
1858
- guardt guard{true_exprt{}, guard_manager};
1859
- check_rec (expr, guard);
1877
+ check_rec (expr, identity);
1860
1878
}
1861
1879
1862
1880
// / expand the r_ok, w_ok and rw_ok predicates
@@ -2157,7 +2175,7 @@ void goto_check_ct::goto_check(
2157
2175
" pointer dereference" ,
2158
2176
i.source_location (),
2159
2177
pointer,
2160
- guardt ( true_exprt (), guard_manager) );
2178
+ identity );
2161
2179
}
2162
2180
2163
2181
// this has no successor
@@ -2253,7 +2271,7 @@ void goto_check_ct::goto_check(
2253
2271
" memory-leak" ,
2254
2272
source_location,
2255
2273
eq,
2256
- guardt ( true_exprt (), guard_manager) );
2274
+ identity );
2257
2275
}
2258
2276
}
2259
2277
0 commit comments