@@ -15,8 +15,7 @@ Date: February 2016
15
15
16
16
#include < algorithm>
17
17
18
- #include < analyses/local_may_alias.h>
19
-
18
+ #include < goto-programs/goto_program.h>
20
19
#include < goto-programs/remove_skip.h>
21
20
22
21
#include < util/arith_tools.h>
@@ -30,8 +29,6 @@ Date: February 2016
30
29
#include < util/pointer_predicates.h>
31
30
#include < util/replace_symbol.h>
32
31
33
- #include " loop_utils.h"
34
-
35
32
// / Predicate to be used with the exprt::visit() function. The function
36
33
// / found_return_value() will return `true` iff this predicate is called on an
37
34
// / expr that contains `__CPROVER_return_value`.
@@ -70,11 +67,12 @@ exprt get_size(const typet &type, const namespacet &ns, messaget &log)
70
67
return result;
71
68
}
72
69
73
- static void check_apply_invariants (
70
+ void code_contractst:: check_apply_invariants (
74
71
goto_functionst::goto_functiont &goto_function,
75
72
const local_may_aliast &local_may_alias,
76
73
const goto_programt::targett loop_head,
77
- const loopt &loop)
74
+ const loopt &loop,
75
+ const irep_idt &mode)
78
76
{
79
77
PRECONDITION (!loop.empty ());
80
78
@@ -92,16 +90,18 @@ static void check_apply_invariants(
92
90
if (invariant.is_nil ())
93
91
return ;
94
92
95
- // change H: loop; E: ...
93
+ // change
94
+ // H: loop;
95
+ // E: ...
96
96
// to
97
- // H: assert(invariant);
98
- // havoc;
99
- // assume(invariant);
100
- // if(guard) goto E:
101
- // loop;
102
- // assert(invariant);
103
- // assume(false);
104
- // E: ...
97
+ // H: assert(invariant);
98
+ // havoc;
99
+ // assume(invariant);
100
+ // if(guard) goto E:
101
+ // loop;
102
+ // assert(invariant);
103
+ // assume(false);
104
+ // E: ...
105
105
106
106
// find out what can get changed in the loop
107
107
modifiest modifies;
@@ -112,17 +112,20 @@ static void check_apply_invariants(
112
112
113
113
// assert the invariant
114
114
{
115
- goto_programt::targett a = havoc_code.add (
116
- goto_programt::make_assertion (invariant, loop_head->source_location ));
117
- a->source_location .set_comment (" Check loop invariant before entry" );
115
+ auto assertion = code_assertt (invariant);
116
+ assertion.add_source_location ().swap (loop_head->source_location );
117
+ converter.goto_convert (assertion, havoc_code, mode);
118
+ havoc_code.instructions .back ().source_location .set_comment (
119
+ " Check loop invariant before entry" );
118
120
}
119
121
120
122
// havoc variables being written to
121
123
build_havoc_code (loop_head, modifies, havoc_code);
122
124
123
125
// assume the invariant
124
- havoc_code.add (
125
- goto_programt::make_assumption (invariant, loop_head->source_location ));
126
+ auto assumption = code_assumet (invariant);
127
+ assumption.add_source_location ().swap (loop_head->source_location );
128
+ converter.goto_convert (assumption, havoc_code, mode);
126
129
127
130
// non-deterministically skip the loop if it is a do-while loop
128
131
if (!loop_head->is_goto ())
@@ -138,11 +141,14 @@ static void check_apply_invariants(
138
141
139
142
// assert the invariant at the end of the loop body
140
143
{
141
- goto_programt::instructiont a =
142
- goto_programt::make_assertion (invariant, loop_end->source_location );
143
- a.source_location .set_comment (" Check that loop invariant is preserved" );
144
- goto_function.body .insert_before_swap (loop_end, a);
145
- ++loop_end;
144
+ auto assertion = code_assertt (invariant);
145
+ assertion.add_source_location ().swap (loop_end->source_location );
146
+ converter.goto_convert (assertion, havoc_code, mode);
147
+ havoc_code.instructions .back ().source_location .set_comment (
148
+ " Check that loop invariant is preserved" );
149
+ auto offset = havoc_code.instructions .size ();
150
+ goto_function.body .insert_before_swap (loop_end, havoc_code);
151
+ std::advance (loop_end, offset);
146
152
}
147
153
148
154
// change the back edge into assume(false) or assume(guard)
@@ -370,15 +376,21 @@ bool code_contractst::apply_function_contract(
370
376
}
371
377
372
378
void code_contractst::apply_loop_contract (
379
+ const irep_idt &function_name,
373
380
goto_functionst::goto_functiont &goto_function)
374
381
{
375
382
local_may_aliast local_may_alias (goto_function);
376
383
natural_loops_mutablet natural_loops (goto_function.body );
377
384
378
- // iterate over the (natural) loops in the function
385
+ // Iterate over the (natural) loops in the function,
386
+ // and apply any invariant annotations that we find.
379
387
for (const auto &loop : natural_loops.loop_map )
380
388
check_apply_invariants (
381
- goto_function, local_may_alias, loop.first , loop.second );
389
+ goto_function,
390
+ local_may_alias,
391
+ loop.first ,
392
+ loop.second ,
393
+ symbol_table.lookup_ref (function_name).mode );
382
394
}
383
395
384
396
const symbolt &code_contractst::new_tmp_symbol (
@@ -953,7 +965,7 @@ bool code_contractst::enforce_contracts()
953
965
if (has_contract (goto_function.first ))
954
966
funs_to_enforce.insert (id2string (goto_function.first ));
955
967
else
956
- apply_loop_contract (goto_function.second );
968
+ apply_loop_contract (goto_function.first , goto_function. second );
957
969
}
958
970
return enforce_contracts (funs_to_enforce);
959
971
}
@@ -973,7 +985,7 @@ bool code_contractst::enforce_contracts(
973
985
<< messaget::eom;
974
986
continue ;
975
987
}
976
- apply_loop_contract (goto_function->second );
988
+ apply_loop_contract (goto_function->first , goto_function-> second );
977
989
978
990
if (!has_contract (fun))
979
991
{
0 commit comments