@@ -23,6 +23,7 @@ Date: February 2016
23
23
#include < linking/static_lifetime_init.h>
24
24
25
25
#include " loop_utils.h"
26
+ #include " function_modifies.h"
26
27
27
28
enum class contract_opst { APPLY, CHECK };
28
29
@@ -52,6 +53,7 @@ class code_contractst
52
53
53
54
void apply_contract (
54
55
goto_programt &goto_program,
56
+ const local_may_aliast &local_may_alias,
55
57
goto_programt::targett target);
56
58
57
59
void apply_invariant (
@@ -78,6 +80,7 @@ class code_contractst
78
80
79
81
void code_contractst::apply_contract (
80
82
goto_programt &goto_program,
83
+ const local_may_aliast &local_may_alias,
81
84
goto_programt::targett target)
82
85
{
83
86
const code_function_callt &call=to_code_function_call (target->code );
@@ -109,6 +112,23 @@ void code_contractst::apply_contract(
109
112
}
110
113
}
111
114
115
+ // find out what can be written by the function
116
+ // TODO Use a better write-set analysis.
117
+ modifiest modifies;
118
+ function_modifiest function_modifies (goto_functions);
119
+
120
+ // Handle return value of the function
121
+ if (call.lhs ().is_not_nil ())
122
+ {
123
+ function_modifies.get_modifies_lhs (local_may_alias, target,
124
+ call.lhs (), modifies);
125
+ }
126
+ function_modifies (call.function (), modifies);
127
+
128
+ // build the havocking code
129
+ goto_programt havoc_code;
130
+ build_havoc_code (target, modifies, havoc_code);
131
+
112
132
// replace formal parameters by arguments, replace return
113
133
replace_symbolt replace;
114
134
@@ -140,7 +160,9 @@ void code_contractst::apply_contract(
140
160
goto_program.insert_before_swap (target, a);
141
161
++target;
142
162
}
143
- // TODO: Havoc write set of the function between assert and ensure.
163
+
164
+ // TODO some sort of replacement on havoc code
165
+ goto_program.destructive_insert (target, havoc_code);
144
166
145
167
target->make_assumption (ensures);
146
168
}
@@ -151,7 +173,7 @@ void code_contractst::apply_invariant(
151
173
const goto_programt::targett loop_head,
152
174
const loopt &loop)
153
175
{
154
- assert (!loop.empty ());
176
+ PRECONDITION (!loop.empty ());
155
177
156
178
// find the last back edge
157
179
goto_programt::targett loop_end=loop_head;
@@ -172,8 +194,6 @@ void code_contractst::apply_invariant(
172
194
return ;
173
195
}
174
196
175
- // TODO: Allow for not havocking in the for/while case
176
-
177
197
// change H: loop; E: ...
178
198
// to
179
199
// H: assert(invariant);
@@ -210,8 +230,6 @@ void code_contractst::apply_invariant(
210
230
}
211
231
212
232
// assume !guard
213
- // TODO: consider breaks and how they're implemented.
214
- // TODO: Also consider continues and whether they jump to loop end or head
215
233
{
216
234
goto_programt::targett assume = havoc_code.add_instruction (ASSUME);
217
235
if (loop_head->is_goto ())
@@ -246,7 +264,7 @@ void code_contractst::check_contract(
246
264
goto_functionst::goto_functiont &goto_function,
247
265
goto_programt &dest)
248
266
{
249
- assert (!dest.instructions .empty ());
267
+ PRECONDITION (!dest.instructions .empty ());
250
268
251
269
exprt requires =
252
270
static_cast <const exprt&>(goto_function.type .find (ID_C_spec_requires));
@@ -321,16 +339,17 @@ void code_contractst::check_contract(
321
339
replace.insert (p_it.get_identifier (), p);
322
340
}
323
341
342
+ // rewrite any use of parameters
343
+ replace (requires);
344
+ replace (ensures);
345
+
324
346
// assume(requires)
325
347
if (requires.is_not_nil ())
326
348
{
327
349
goto_programt::targett a=check.add_instruction ();
328
350
a->make_assumption (requires);
329
351
a->function =skip->function ;
330
352
a->source_location =requires.source_location ();
331
-
332
- // rewrite any use of parameters
333
- replace (a->guard );
334
353
}
335
354
336
355
// ret=function(parameter1, ...)
@@ -345,9 +364,6 @@ void code_contractst::check_contract(
345
364
a->function =skip->function ;
346
365
a->source_location =ensures.source_location ();
347
366
348
- // rewrite any use of __CPROVER_return_value
349
- replace (a->guard );
350
-
351
367
// prepend the new code to dest
352
368
check.destructive_append (tmp_skip);
353
369
dest.destructive_insert (dest.instructions .begin (), check);
@@ -359,7 +375,7 @@ void code_contractst::check_apply_invariant(
359
375
const goto_programt::targett loop_head,
360
376
const loopt &loop)
361
377
{
362
- assert (!loop.empty ());
378
+ PRECONDITION (!loop.empty ());
363
379
364
380
// find the last back edge
365
381
goto_programt::targett loop_end=loop_head;
@@ -478,7 +494,7 @@ void code_contractst::apply_code_contracts()
478
494
{
479
495
if (it->is_function_call ())
480
496
{
481
- apply_contract (goto_function.body , it);
497
+ apply_contract (goto_function.body , local_may_alias, it);
482
498
}
483
499
}
484
500
}
@@ -512,7 +528,7 @@ void code_contractst::check_code_contracts()
512
528
{
513
529
if (it->is_function_call ())
514
530
{
515
- apply_contract (goto_function.body , it);
531
+ apply_contract (goto_function.body , local_may_alias, it);
516
532
}
517
533
}
518
534
}
@@ -522,7 +538,6 @@ void code_contractst::check_code_contracts()
522
538
check_contract (it->first , it->second , i_it->second .body );
523
539
}
524
540
525
- // remove skips
526
541
remove_skip (i_it->second .body );
527
542
528
543
goto_functions.update ();
0 commit comments