@@ -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>
@@ -75,9 +76,11 @@ exprt get_size(const typet &type, const namespacet &ns, messaget &log)
75
76
76
77
static void check_apply_invariants (
77
78
goto_functionst::goto_functiont &goto_function,
79
+ goto_convertt &converter,
78
80
const local_may_aliast &local_may_alias,
79
81
const goto_programt::targett loop_head,
80
- const loopt &loop)
82
+ const loopt &loop,
83
+ const irep_idt &mode)
81
84
{
82
85
PRECONDITION (!loop.empty ());
83
86
@@ -95,16 +98,18 @@ static void check_apply_invariants(
95
98
if (invariant.is_nil ())
96
99
return ;
97
100
98
- // change H: loop; E: ...
101
+ // change
102
+ // H: loop;
103
+ // E: ...
99
104
// to
100
- // H: assert(invariant);
101
- // havoc;
102
- // assume(invariant);
103
- // if(guard) goto E:
104
- // loop;
105
- // assert(invariant);
106
- // assume(false);
107
- // E: ...
105
+ // H: assert(invariant);
106
+ // havoc;
107
+ // assume(invariant);
108
+ // if(guard) goto E:
109
+ // loop;
110
+ // assert(invariant);
111
+ // assume(false);
112
+ // E: ...
108
113
109
114
// find out what can get changed in the loop
110
115
modifiest modifies;
@@ -115,17 +120,20 @@ static void check_apply_invariants(
115
120
116
121
// assert the invariant
117
122
{
118
- goto_programt::targett a = havoc_code.add (
119
- goto_programt::make_assertion (invariant, loop_head->source_location ));
120
- a->source_location .set_comment (" Check loop invariant before entry" );
123
+ auto assertion = code_assertt (invariant);
124
+ assertion.add_source_location ().swap (loop_head->source_location );
125
+ converter.goto_convert (assertion, havoc_code, mode);
126
+ havoc_code.instructions .back ().source_location .set_comment (
127
+ " Check loop invariant before entry" );
121
128
}
122
129
123
130
// havoc variables being written to
124
131
build_havoc_code (loop_head, modifies, havoc_code);
125
132
126
133
// assume the invariant
127
- havoc_code.add (
128
- goto_programt::make_assumption (invariant, loop_head->source_location ));
134
+ auto assumption = code_assumet (invariant);
135
+ assumption.add_source_location ().swap (loop_head->source_location );
136
+ converter.goto_convert (assumption, havoc_code, mode);
129
137
130
138
// non-deterministically skip the loop if it is a do-while loop
131
139
if (!loop_head->is_goto ())
@@ -141,11 +149,14 @@ static void check_apply_invariants(
141
149
142
150
// assert the invariant at the end of the loop body
143
151
{
144
- goto_programt::instructiont a =
145
- goto_programt::make_assertion (invariant, loop_end->source_location );
146
- a.source_location .set_comment (" Check that loop invariant is preserved" );
147
- goto_function.body .insert_before_swap (loop_end, a);
148
- ++loop_end;
152
+ auto assertion = code_assertt (invariant);
153
+ assertion.add_source_location ().swap (loop_end->source_location );
154
+ converter.goto_convert (assertion, havoc_code, mode);
155
+ havoc_code.instructions .back ().source_location .set_comment (
156
+ " Check that loop invariant is preserved" );
157
+ auto offset = havoc_code.instructions .size ();
158
+ goto_function.body .insert_before_swap (loop_end, havoc_code);
159
+ std::advance (loop_end, offset);
149
160
}
150
161
151
162
// change the back edge into assume(false) or assume(guard)
@@ -366,15 +377,24 @@ bool code_contractst::apply_function_contract(
366
377
}
367
378
368
379
void code_contractst::apply_loop_contract (
380
+ const irep_idt &function_name,
369
381
goto_functionst::goto_functiont &goto_function)
370
382
{
371
383
local_may_aliast local_may_alias (goto_function);
372
384
natural_loops_mutablet natural_loops (goto_function.body );
373
385
386
+ // setup goto_convertt to convert C expressions to logic
387
+ goto_convertt converter (symbol_table, log.get_message_handler ());
388
+
374
389
// iterate over the (natural) loops in the function
375
390
for (const auto &loop : natural_loops.loop_map )
376
391
check_apply_invariants (
377
- goto_function, local_may_alias, loop.first , loop.second );
392
+ goto_function,
393
+ converter,
394
+ local_may_alias,
395
+ loop.first ,
396
+ loop.second ,
397
+ symbol_table.lookup_ref (function_name).mode );
378
398
}
379
399
380
400
const symbolt &code_contractst::new_tmp_symbol (
@@ -971,7 +991,7 @@ bool code_contractst::enforce_contracts()
971
991
if (has_contract (goto_function.first ))
972
992
funs_to_enforce.insert (id2string (goto_function.first ));
973
993
else
974
- apply_loop_contract (goto_function.second );
994
+ apply_loop_contract (goto_function.first , goto_function. second );
975
995
}
976
996
return enforce_contracts (funs_to_enforce);
977
997
}
@@ -991,7 +1011,7 @@ bool code_contractst::enforce_contracts(
991
1011
<< messaget::eom;
992
1012
continue ;
993
1013
}
994
- apply_loop_contract (goto_function->second );
1014
+ apply_loop_contract (goto_function->first , goto_function-> second );
995
1015
996
1016
if (!has_contract (fun))
997
1017
{
0 commit comments