@@ -42,7 +42,6 @@ Author: Daniel Kroening, kroening@kroening.com
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
4847class 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 ()), rhs_implication.rhs ());
350+ }
351+ else
352+ {
353+ return implies_exprt (std::move (lhs), std::move (rhs));
354+ }
355+ }
356+
341357void 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,23 @@ 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 (
1715+ const member_exprt &member,
1716+ const guardt &guard)
16991717{
17001718 const dereference_exprt &deref = to_dereference_expr (member.struct_op ());
17011719
@@ -1733,7 +1751,9 @@ bool goto_check_ct::check_rec_member(const member_exprt &member, guardt &guard)
17331751 return false ;
17341752}
17351753
1736- void goto_check_ct::check_rec_div (const div_exprt &div_expr, guardt &guard)
1754+ void goto_check_ct::check_rec_div (
1755+ const div_exprt &div_expr,
1756+ const guardt &guard)
17371757{
17381758 div_by_zero_check (to_div_expr (div_expr), guard);
17391759
@@ -1746,7 +1766,9 @@ void goto_check_ct::check_rec_div(const div_exprt &div_expr, guardt &guard)
17461766 }
17471767}
17481768
1749- void goto_check_ct::check_rec_arithmetic_op (const exprt &expr, guardt &guard)
1769+ void goto_check_ct::check_rec_arithmetic_op (
1770+ const exprt &expr,
1771+ const guardt &guard)
17501772{
17511773 if (expr.type ().id () == ID_signedbv || expr.type ().id () == ID_unsignedbv)
17521774 {
@@ -1771,7 +1793,7 @@ void goto_check_ct::check_rec_arithmetic_op(const exprt &expr, guardt &guard)
17711793 }
17721794}
17731795
1774- void goto_check_ct::check_rec (const exprt &expr, guardt &guard)
1796+ void goto_check_ct::check_rec (const exprt &expr, const guardt &guard)
17751797{
17761798 // we don't look into quantifiers
17771799 if (expr.id () == ID_exists || expr.id () == ID_forall)
@@ -1855,8 +1877,7 @@ void goto_check_ct::check_rec(const exprt &expr, guardt &guard)
18551877
18561878void goto_check_ct::check (const exprt &expr)
18571879{
1858- guardt guard{true_exprt{}, guard_manager};
1859- check_rec (expr, guard);
1880+ check_rec (expr, identity);
18601881}
18611882
18621883// / expand the r_ok, w_ok and rw_ok predicates
@@ -2157,7 +2178,7 @@ void goto_check_ct::goto_check(
21572178 " pointer dereference" ,
21582179 i.source_location (),
21592180 pointer,
2160- guardt ( true_exprt (), guard_manager) );
2181+ identity );
21612182 }
21622183
21632184 // this has no successor
@@ -2253,7 +2274,7 @@ void goto_check_ct::goto_check(
22532274 " memory-leak" ,
22542275 source_location,
22552276 eq,
2256- guardt ( true_exprt (), guard_manager) );
2277+ identity );
22572278 }
22582279 }
22592280
0 commit comments