@@ -16,6 +16,7 @@ Date: February 2016
16
16
17
17
#include < analyses/local_may_alias.h>
18
18
19
+ #include < goto-programs/goto_convert_class.h>
19
20
#include < goto-programs/remove_skip.h>
20
21
21
22
#include < linking/static_lifetime_init.h>
@@ -62,9 +63,11 @@ class return_value_visitort : public const_expr_visitort
62
63
63
64
static void check_apply_invariants (
64
65
goto_functionst::goto_functiont &goto_function,
66
+ goto_convertt &converter,
65
67
const local_may_aliast &local_may_alias,
66
68
const goto_programt::targett loop_head,
67
- const loopt &loop)
69
+ const loopt &loop,
70
+ const irep_idt &mode)
68
71
{
69
72
PRECONDITION (!loop.empty ());
70
73
@@ -82,16 +85,18 @@ static void check_apply_invariants(
82
85
if (invariant.is_nil ())
83
86
return ;
84
87
85
- // change H: loop; E: ...
88
+ // change
89
+ // H: loop;
90
+ // E: ...
86
91
// to
87
- // H: assert(invariant);
88
- // havoc;
89
- // assume(invariant);
90
- // if(guard) goto E:
91
- // loop;
92
- // assert(invariant);
93
- // assume(false);
94
- // E: ...
92
+ // H: assert(invariant);
93
+ // havoc;
94
+ // assume(invariant);
95
+ // if(guard) goto E:
96
+ // loop;
97
+ // assert(invariant);
98
+ // assume(false);
99
+ // E: ...
95
100
96
101
// find out what can get changed in the loop
97
102
modifiest modifies;
@@ -102,17 +107,20 @@ static void check_apply_invariants(
102
107
103
108
// assert the invariant
104
109
{
105
- goto_programt::targett a = havoc_code.add (
106
- goto_programt::make_assertion (invariant, loop_head->source_location ));
107
- a->source_location .set_comment (" Check loop invariant before entry" );
110
+ auto assertion = code_assertt (invariant);
111
+ assertion.add_source_location ().swap (loop_head->source_location );
112
+ converter.goto_convert (assertion, havoc_code, mode);
113
+ havoc_code.instructions .back ().source_location .set_comment (
114
+ " Check loop invariant before entry" );
108
115
}
109
116
110
117
// havoc variables being written to
111
118
build_havoc_code (loop_head, modifies, havoc_code);
112
119
113
120
// assume the invariant
114
- havoc_code.add (
115
- goto_programt::make_assumption (invariant, loop_head->source_location ));
121
+ auto assumption = code_assumet (invariant);
122
+ assumption.add_source_location ().swap (loop_head->source_location );
123
+ converter.goto_convert (assumption, havoc_code, mode);
116
124
117
125
// non-deterministically skip the loop if it is a do-while loop
118
126
if (!loop_head->is_goto ())
@@ -128,11 +136,14 @@ static void check_apply_invariants(
128
136
129
137
// assert the invariant at the end of the loop body
130
138
{
131
- goto_programt::instructiont a =
132
- goto_programt::make_assertion (invariant, loop_end->source_location );
133
- a.source_location .set_comment (" Check that loop invariant is preserved" );
134
- goto_function.body .insert_before_swap (loop_end, a);
135
- ++loop_end;
139
+ auto assertion = code_assertt (invariant);
140
+ assertion.add_source_location ().swap (loop_end->source_location );
141
+ converter.goto_convert (assertion, havoc_code, mode);
142
+ havoc_code.instructions .back ().source_location .set_comment (
143
+ " Check that loop invariant is preserved" );
144
+ auto offset = havoc_code.instructions .size ();
145
+ goto_function.body .insert_before_swap (loop_end, havoc_code);
146
+ std::advance (loop_end, offset);
136
147
}
137
148
138
149
// change the back edge into assume(false) or assume(guard)
@@ -293,15 +304,24 @@ bool code_contractst::apply_function_contract(
293
304
}
294
305
295
306
void code_contractst::apply_loop_contract (
307
+ const irep_idt &function_name,
296
308
goto_functionst::goto_functiont &goto_function)
297
309
{
298
310
local_may_aliast local_may_alias (goto_function);
299
311
natural_loops_mutablet natural_loops (goto_function.body );
300
312
313
+ // setup goto_convertt to convert C expressions to logic
314
+ goto_convertt converter (symbol_table, log.get_message_handler ());
315
+
301
316
// iterate over the (natural) loops in the function
302
317
for (const auto &loop : natural_loops.loop_map )
303
318
check_apply_invariants (
304
- goto_function, local_may_alias, loop.first , loop.second );
319
+ goto_function,
320
+ converter,
321
+ local_may_alias,
322
+ loop.first ,
323
+ loop.second ,
324
+ symbol_table.lookup_ref (function_name).mode );
305
325
}
306
326
307
327
const symbolt &code_contractst::new_tmp_symbol (
@@ -926,7 +946,7 @@ bool code_contractst::enforce_contracts()
926
946
if (has_contract (goto_function.first ))
927
947
funs_to_enforce.insert (id2string (goto_function.first ));
928
948
else
929
- apply_loop_contract (goto_function.second );
949
+ apply_loop_contract (goto_function.first , goto_function. second );
930
950
}
931
951
return enforce_contracts (funs_to_enforce);
932
952
}
@@ -946,7 +966,7 @@ bool code_contractst::enforce_contracts(
946
966
<< messaget::eom;
947
967
continue ;
948
968
}
949
- apply_loop_contract (goto_function->second );
969
+ apply_loop_contract (goto_function->first , goto_function-> second );
950
970
951
971
if (!has_contract (fun))
952
972
{
0 commit comments