@@ -20,7 +20,6 @@ Date: February 2016
2020
2121#include < ansi-c/c_expr.h>
2222
23- #include < goto-programs/goto_convert_class.h>
2423#include < goto-programs/remove_skip.h>
2524
2625#include < util/arith_tools.h>
@@ -34,8 +33,6 @@ Date: February 2016
3433#include < util/pointer_predicates.h>
3534#include < util/replace_symbol.h>
3635
37- #include " loop_utils.h"
38-
3936// / Predicate to be used with the exprt::visit() function. The function
4037// / found_return_value() will return `true` iff this predicate is called on an
4138// / expr that contains `__CPROVER_return_value`.
@@ -74,11 +71,12 @@ exprt get_size(const typet &type, const namespacet &ns, messaget &log)
7471 return result;
7572}
7673
77- static void check_apply_invariants (
74+ void code_contractst:: check_apply_invariants (
7875 goto_functionst::goto_functiont &goto_function,
7976 const local_may_aliast &local_may_alias,
8077 const goto_programt::targett loop_head,
81- const loopt &loop)
78+ const loopt &loop,
79+ const irep_idt &mode)
8280{
8381 PRECONDITION (!loop.empty ());
8482
@@ -96,16 +94,18 @@ static void check_apply_invariants(
9694 if (invariant.is_nil ())
9795 return ;
9896
99- // change H: loop; E: ...
97+ // change
98+ // H: loop;
99+ // E: ...
100100 // to
101- // H: assert(invariant);
102- // havoc;
103- // assume(invariant);
104- // if(guard) goto E:
105- // loop;
106- // assert(invariant);
107- // assume(false);
108- // E: ...
101+ // H: assert(invariant);
102+ // havoc;
103+ // assume(invariant);
104+ // if(guard) goto E:
105+ // loop;
106+ // assert(invariant);
107+ // assume(false);
108+ // E: ...
109109
110110 // find out what can get changed in the loop
111111 modifiest modifies;
@@ -116,17 +116,20 @@ static void check_apply_invariants(
116116
117117 // assert the invariant
118118 {
119- goto_programt::targett a = havoc_code.add (
120- goto_programt::make_assertion (invariant, loop_head->source_location ));
121- a->source_location .set_comment (" Check loop invariant before entry" );
119+ code_assertt assertion{invariant};
120+ assertion.add_source_location () = loop_head->source_location ;
121+ converter.goto_convert (assertion, havoc_code, mode);
122+ havoc_code.instructions .back ().source_location .set_comment (
123+ " Check loop invariant before entry" );
122124 }
123125
124126 // havoc variables being written to
125127 build_havoc_code (loop_head, modifies, havoc_code);
126128
127129 // assume the invariant
128- havoc_code.add (
129- goto_programt::make_assumption (invariant, loop_head->source_location ));
130+ code_assumet assumption{invariant};
131+ assumption.add_source_location () = loop_head->source_location ;
132+ converter.goto_convert (assumption, havoc_code, mode);
130133
131134 // non-deterministically skip the loop if it is a do-while loop
132135 if (!loop_head->is_goto ())
@@ -142,11 +145,14 @@ static void check_apply_invariants(
142145
143146 // assert the invariant at the end of the loop body
144147 {
145- goto_programt::instructiont a =
146- goto_programt::make_assertion (invariant, loop_end->source_location );
147- a.source_location .set_comment (" Check that loop invariant is preserved" );
148- goto_function.body .insert_before_swap (loop_end, a);
149- ++loop_end;
148+ code_assertt assertion{invariant};
149+ assertion.add_source_location () = loop_end->source_location ;
150+ converter.goto_convert (assertion, havoc_code, mode);
151+ havoc_code.instructions .back ().source_location .set_comment (
152+ " Check that loop invariant is preserved" );
153+ auto offset = havoc_code.instructions .size ();
154+ goto_function.body .insert_before_swap (loop_end, havoc_code);
155+ std::advance (loop_end, offset);
150156 }
151157
152158 // change the back edge into assume(false) or assume(guard)
@@ -158,15 +164,6 @@ static void check_apply_invariants(
158164 loop_end->set_condition (boolean_negate (loop_end->get_condition ()));
159165}
160166
161- void code_contractst::convert_to_goto (
162- const codet &code,
163- const irep_idt &mode,
164- goto_programt &program)
165- {
166- goto_convertt converter (symbol_table, log.get_message_handler ());
167- converter.goto_convert (code, program, mode);
168- }
169-
170167bool code_contractst::has_contract (const irep_idt fun_name)
171168{
172169 const symbolt &function_symbol = ns.lookup (fun_name);
@@ -322,7 +319,7 @@ code_contractst::create_ensures_instruction(
322319
323320 // Create instructions corresponding to the ensures clause
324321 goto_programt ensures_program;
325- convert_to_goto (expression, mode, ensures_program );
322+ converter. goto_convert (expression, ensures_program, mode );
326323
327324 // return a pair containing:
328325 // 1. instructions corresponding to the ensures clause
@@ -424,10 +421,10 @@ bool code_contractst::apply_function_contract(
424421 if (requires .is_not_nil ())
425422 {
426423 goto_programt assertion;
427- convert_to_goto (
424+ converter. goto_convert (
428425 code_assertt (requires ),
429- symbol_table. lookup_ref (function). mode ,
430- assertion );
426+ assertion ,
427+ symbol_table. lookup_ref (function). mode );
431428 auto lines_to_iterate = assertion.instructions .size ();
432429 goto_program.insert_before_swap (target, assertion);
433430 std::advance (target, lines_to_iterate);
@@ -483,15 +480,21 @@ bool code_contractst::apply_function_contract(
483480}
484481
485482void code_contractst::apply_loop_contract (
483+ const irep_idt &function_name,
486484 goto_functionst::goto_functiont &goto_function)
487485{
488486 local_may_aliast local_may_alias (goto_function);
489487 natural_loops_mutablet natural_loops (goto_function.body );
490488
491- // iterate over the (natural) loops in the function
489+ // Iterate over the (natural) loops in the function,
490+ // and apply any invariant annotations that we find.
492491 for (const auto &loop : natural_loops.loop_map )
493492 check_apply_invariants (
494- goto_function, local_may_alias, loop.first , loop.second );
493+ goto_function,
494+ local_may_alias,
495+ loop.first ,
496+ loop.second ,
497+ symbol_table.lookup_ref (function_name).mode );
495498}
496499
497500const symbolt &code_contractst::new_tmp_symbol (
@@ -966,8 +969,8 @@ void code_contractst::add_contract_check(
966969 replace (requires_cond);
967970
968971 goto_programt assumption;
969- convert_to_goto (
970- code_assumet (requires_cond), function_symbol.mode , assumption );
972+ converter. goto_convert (
973+ code_assumet (requires_cond), assumption, function_symbol.mode );
971974 check.destructive_append (assumption);
972975 }
973976
@@ -1078,7 +1081,7 @@ bool code_contractst::enforce_contracts()
10781081 if (has_contract (goto_function.first ))
10791082 funs_to_enforce.insert (id2string (goto_function.first ));
10801083 else
1081- apply_loop_contract (goto_function.second );
1084+ apply_loop_contract (goto_function.first , goto_function. second );
10821085 }
10831086 return enforce_contracts (funs_to_enforce);
10841087}
@@ -1098,7 +1101,7 @@ bool code_contractst::enforce_contracts(
10981101 << messaget::eom;
10991102 continue ;
11001103 }
1101- apply_loop_contract (goto_function->second );
1104+ apply_loop_contract (goto_function->first , goto_function-> second );
11021105
11031106 if (!has_contract (fun))
11041107 {
0 commit comments