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 ()),
350
+ rhs_implication.rhs ()
351
+ );
352
+ } else {
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,17 @@ 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) );
1683
+ };
1671
1684
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
+ }
1673
1689
}
1674
1690
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)
1676
1692
{
1677
1693
INVARIANT (
1678
1694
if_expr.cond ().is_boolean (),
@@ -1681,21 +1697,21 @@ void goto_check_ct::check_rec_if(const if_exprt &if_expr, guardt &guard)
1681
1697
check_rec (if_expr.cond (), guard);
1682
1698
1683
1699
{
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 );
1688
1704
}
1689
1705
1690
1706
{
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 );
1695
1711
}
1696
1712
}
1697
1713
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)
1699
1715
{
1700
1716
const dereference_exprt &deref = to_dereference_expr (member.struct_op ());
1701
1717
@@ -1733,7 +1749,7 @@ bool goto_check_ct::check_rec_member(const member_exprt &member, guardt &guard)
1733
1749
return false ;
1734
1750
}
1735
1751
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)
1737
1753
{
1738
1754
div_by_zero_check (to_div_expr (div_expr), guard);
1739
1755
@@ -1746,7 +1762,7 @@ void goto_check_ct::check_rec_div(const div_exprt &div_expr, guardt &guard)
1746
1762
}
1747
1763
}
1748
1764
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)
1750
1766
{
1751
1767
if (expr.type ().id () == ID_signedbv || expr.type ().id () == ID_unsignedbv)
1752
1768
{
@@ -1771,12 +1787,12 @@ void goto_check_ct::check_rec_arithmetic_op(const exprt &expr, guardt &guard)
1771
1787
}
1772
1788
}
1773
1789
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)
1775
1791
{
1776
1792
// we don't look into quantifiers
1777
1793
if (expr.id () == ID_exists || expr.id () == ID_forall)
1778
1794
return ;
1779
-
1795
+
1780
1796
if (expr.id () == ID_address_of)
1781
1797
{
1782
1798
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)
1855
1871
1856
1872
void goto_check_ct::check (const exprt &expr)
1857
1873
{
1858
- guardt guard{true_exprt{}, guard_manager};
1859
- check_rec (expr, guard);
1874
+ check_rec (expr, identity);
1860
1875
}
1861
1876
1862
1877
// / expand the r_ok, w_ok and rw_ok predicates
@@ -2157,7 +2172,7 @@ void goto_check_ct::goto_check(
2157
2172
" pointer dereference" ,
2158
2173
i.source_location (),
2159
2174
pointer,
2160
- guardt ( true_exprt (), guard_manager) );
2175
+ identity );
2161
2176
}
2162
2177
2163
2178
// this has no successor
@@ -2253,7 +2268,7 @@ void goto_check_ct::goto_check(
2253
2268
" memory-leak" ,
2254
2269
source_location,
2255
2270
eq,
2256
- guardt ( true_exprt (), guard_manager) );
2271
+ identity );
2257
2272
}
2258
2273
}
2259
2274
0 commit comments