@@ -17,6 +17,7 @@ Date: February 2016
17
17
18
18
#include < analyses/local_may_alias.h>
19
19
20
+ #include < goto-programs/goto_convert_class.h>
20
21
#include < goto-programs/remove_skip.h>
21
22
22
23
#include < linking/static_lifetime_init.h>
@@ -74,9 +75,11 @@ exprt get_size(const typet &type, const namespacet &ns, messaget &log)
74
75
75
76
static void check_apply_invariants (
76
77
goto_functionst::goto_functiont &goto_function,
78
+ goto_convertt &converter,
77
79
const local_may_aliast &local_may_alias,
78
80
const goto_programt::targett loop_head,
79
- const loopt &loop)
81
+ const loopt &loop,
82
+ const irep_idt &mode)
80
83
{
81
84
PRECONDITION (!loop.empty ());
82
85
@@ -94,16 +97,18 @@ static void check_apply_invariants(
94
97
if (invariant.is_nil ())
95
98
return ;
96
99
97
- // change H: loop; E: ...
100
+ // change
101
+ // H: loop;
102
+ // E: ...
98
103
// to
99
- // H: assert(invariant);
100
- // havoc;
101
- // assume(invariant);
102
- // if(guard) goto E:
103
- // loop;
104
- // assert(invariant);
105
- // assume(false);
106
- // E: ...
104
+ // H: assert(invariant);
105
+ // havoc;
106
+ // assume(invariant);
107
+ // if(guard) goto E:
108
+ // loop;
109
+ // assert(invariant);
110
+ // assume(false);
111
+ // E: ...
107
112
108
113
// find out what can get changed in the loop
109
114
modifiest modifies;
@@ -114,17 +119,20 @@ static void check_apply_invariants(
114
119
115
120
// assert the invariant
116
121
{
117
- goto_programt::targett a = havoc_code.add (
118
- goto_programt::make_assertion (invariant, loop_head->source_location ));
119
- a->source_location .set_comment (" Check loop invariant before entry" );
122
+ auto assertion = code_assertt (invariant);
123
+ assertion.add_source_location ().swap (loop_head->source_location );
124
+ converter.goto_convert (assertion, havoc_code, mode);
125
+ havoc_code.instructions .back ().source_location .set_comment (
126
+ " Check loop invariant before entry" );
120
127
}
121
128
122
129
// havoc variables being written to
123
130
build_havoc_code (loop_head, modifies, havoc_code);
124
131
125
132
// assume the invariant
126
- havoc_code.add (
127
- goto_programt::make_assumption (invariant, loop_head->source_location ));
133
+ auto assumption = code_assumet (invariant);
134
+ assumption.add_source_location ().swap (loop_head->source_location );
135
+ converter.goto_convert (assumption, havoc_code, mode);
128
136
129
137
// non-deterministically skip the loop if it is a do-while loop
130
138
if (!loop_head->is_goto ())
@@ -140,11 +148,14 @@ static void check_apply_invariants(
140
148
141
149
// assert the invariant at the end of the loop body
142
150
{
143
- goto_programt::instructiont a =
144
- goto_programt::make_assertion (invariant, loop_end->source_location );
145
- a.source_location .set_comment (" Check that loop invariant is preserved" );
146
- goto_function.body .insert_before_swap (loop_end, a);
147
- ++loop_end;
151
+ auto assertion = code_assertt (invariant);
152
+ assertion.add_source_location ().swap (loop_end->source_location );
153
+ converter.goto_convert (assertion, havoc_code, mode);
154
+ havoc_code.instructions .back ().source_location .set_comment (
155
+ " Check that loop invariant is preserved" );
156
+ auto offset = havoc_code.instructions .size ();
157
+ goto_function.body .insert_before_swap (loop_end, havoc_code);
158
+ std::advance (loop_end, offset);
148
159
}
149
160
150
161
// change the back edge into assume(false) or assume(guard)
@@ -290,15 +301,24 @@ bool code_contractst::apply_function_contract(
290
301
}
291
302
292
303
void code_contractst::apply_loop_contract (
304
+ const irep_idt &function_name,
293
305
goto_functionst::goto_functiont &goto_function)
294
306
{
295
307
local_may_aliast local_may_alias (goto_function);
296
308
natural_loops_mutablet natural_loops (goto_function.body );
297
309
310
+ // setup goto_convertt to convert C expressions to logic
311
+ goto_convertt converter (symbol_table, log.get_message_handler ());
312
+
298
313
// iterate over the (natural) loops in the function
299
314
for (const auto &loop : natural_loops.loop_map )
300
315
check_apply_invariants (
301
- goto_function, local_may_alias, loop.first , loop.second );
316
+ goto_function,
317
+ converter,
318
+ local_may_alias,
319
+ loop.first ,
320
+ loop.second ,
321
+ symbol_table.lookup_ref (function_name).mode );
302
322
}
303
323
304
324
const symbolt &code_contractst::new_tmp_symbol (
@@ -889,7 +909,7 @@ bool code_contractst::enforce_contracts()
889
909
if (has_contract (goto_function.first ))
890
910
funs_to_enforce.insert (id2string (goto_function.first ));
891
911
else
892
- apply_loop_contract (goto_function.second );
912
+ apply_loop_contract (goto_function.first , goto_function. second );
893
913
}
894
914
return enforce_contracts (funs_to_enforce);
895
915
}
@@ -909,7 +929,7 @@ bool code_contractst::enforce_contracts(
909
929
<< messaget::eom;
910
930
continue ;
911
931
}
912
- apply_loop_contract (goto_function->second );
932
+ apply_loop_contract (goto_function->first , goto_function-> second );
913
933
914
934
if (!has_contract (fun))
915
935
{
0 commit comments