@@ -23,6 +23,7 @@ Date: February 2016
2323#include < linking/static_lifetime_init.h>
2424
2525#include " loop_utils.h"
26+ #include " function_modifies.h"
2627
2728enum class contract_opst { APPLY, CHECK };
2829
@@ -52,6 +53,7 @@ class code_contractst
5253
5354 void apply_contract (
5455 goto_programt &goto_program,
56+ const local_may_aliast &local_may_alias,
5557 goto_programt::targett target);
5658
5759 void apply_invariant (
@@ -78,6 +80,7 @@ class code_contractst
7880
7981void code_contractst::apply_contract (
8082 goto_programt &goto_program,
83+ const local_may_aliast &local_may_alias,
8184 goto_programt::targett target)
8285{
8386 const code_function_callt &call=to_code_function_call (target->code );
@@ -109,6 +112,23 @@ void code_contractst::apply_contract(
109112 }
110113 }
111114
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+
112132 // replace formal parameters by arguments, replace return
113133 replace_symbolt replace;
114134
@@ -140,7 +160,9 @@ void code_contractst::apply_contract(
140160 goto_program.insert_before_swap (target, a);
141161 ++target;
142162 }
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);
144166
145167 target->make_assumption (ensures);
146168}
@@ -151,7 +173,7 @@ void code_contractst::apply_invariant(
151173 const goto_programt::targett loop_head,
152174 const loopt &loop)
153175{
154- assert (!loop.empty ());
176+ PRECONDITION (!loop.empty ());
155177
156178 // find the last back edge
157179 goto_programt::targett loop_end=loop_head;
@@ -172,8 +194,6 @@ void code_contractst::apply_invariant(
172194 return ;
173195 }
174196
175- // TODO: Allow for not havocking in the for/while case
176-
177197 // change H: loop; E: ...
178198 // to
179199 // H: assert(invariant);
@@ -210,8 +230,6 @@ void code_contractst::apply_invariant(
210230 }
211231
212232 // 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
215233 {
216234 goto_programt::targett assume = havoc_code.add_instruction (ASSUME);
217235 if (loop_head->is_goto ())
@@ -246,7 +264,7 @@ void code_contractst::check_contract(
246264 goto_functionst::goto_functiont &goto_function,
247265 goto_programt &dest)
248266{
249- assert (!dest.instructions .empty ());
267+ PRECONDITION (!dest.instructions .empty ());
250268
251269 exprt requires =
252270 static_cast <const exprt&>(goto_function.type .find (ID_C_spec_requires));
@@ -321,16 +339,17 @@ void code_contractst::check_contract(
321339 replace.insert (p_it.get_identifier (), p);
322340 }
323341
342+ // rewrite any use of parameters
343+ replace (requires );
344+ replace (ensures);
345+
324346 // assume(requires)
325347 if (requires .is_not_nil ())
326348 {
327349 goto_programt::targett a=check.add_instruction ();
328350 a->make_assumption (requires );
329351 a->function =skip->function ;
330352 a->source_location =requires .source_location ();
331-
332- // rewrite any use of parameters
333- replace (a->guard );
334353 }
335354
336355 // ret=function(parameter1, ...)
@@ -345,9 +364,6 @@ void code_contractst::check_contract(
345364 a->function =skip->function ;
346365 a->source_location =ensures.source_location ();
347366
348- // rewrite any use of __CPROVER_return_value
349- replace (a->guard );
350-
351367 // prepend the new code to dest
352368 check.destructive_append (tmp_skip);
353369 dest.destructive_insert (dest.instructions .begin (), check);
@@ -359,7 +375,7 @@ void code_contractst::check_apply_invariant(
359375 const goto_programt::targett loop_head,
360376 const loopt &loop)
361377{
362- assert (!loop.empty ());
378+ PRECONDITION (!loop.empty ());
363379
364380 // find the last back edge
365381 goto_programt::targett loop_end=loop_head;
@@ -478,7 +494,7 @@ void code_contractst::apply_code_contracts()
478494 {
479495 if (it->is_function_call ())
480496 {
481- apply_contract (goto_function.body , it);
497+ apply_contract (goto_function.body , local_may_alias, it);
482498 }
483499 }
484500 }
@@ -512,7 +528,7 @@ void code_contractst::check_code_contracts()
512528 {
513529 if (it->is_function_call ())
514530 {
515- apply_contract (goto_function.body , it);
531+ apply_contract (goto_function.body , local_may_alias, it);
516532 }
517533 }
518534 }
@@ -522,7 +538,6 @@ void code_contractst::check_code_contracts()
522538 check_contract (it->first , it->second , i_it->second .body );
523539 }
524540
525- // remove skips
526541 remove_skip (i_it->second .body );
527542
528543 goto_functions.update ();
0 commit comments