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