@@ -34,8 +34,7 @@ class code_contractst
3434 goto_functionst &_goto_functions):
3535 ns (_symbol_table),
3636 symbol_table (_symbol_table),
37- goto_functions (_goto_functions),
38- temporary_counter (0 )
37+ goto_functions (_goto_functions)
3938 {
4039 }
4140
@@ -46,10 +45,6 @@ class code_contractst
4645 symbol_tablet &symbol_table;
4746 goto_functionst &goto_functions;
4847
49- unsigned temporary_counter;
50-
51- std::unordered_set<irep_idt> summarized;
52-
5348 void apply_code_contracts ();
5449 void check_code_contracts ();
5550
@@ -76,160 +71,11 @@ class code_contractst
7671 const goto_programt::targett loop_head,
7772 const loopt &loop);
7873
79- void add_contract_check (
80- const irep_idt &function,
81- goto_programt &dest);
82-
8374 const symbolt &new_tmp_symbol (
8475 const typet &type,
8576 const source_locationt &source_location);
8677};
8778
88- static void check_apply_invariants (
89- goto_functionst::goto_functiont &goto_function,
90- const local_may_aliast &local_may_alias,
91- const goto_programt::targett loop_head,
92- const loopt &loop)
93- {
94- PRECONDITION (!loop.empty ());
95-
96- // find the last back edge
97- goto_programt::targett loop_end=loop_head;
98- for (const goto_programt::targett &inst : loop)
99- {
100- if (inst->is_goto () &&
101- inst->get_target () == loop_head &&
102- inst->location_number >loop_end->location_number )
103- {
104- loop_end = inst;
105- }
106- }
107-
108- // see whether we have an invariant
109- exprt invariant=
110- static_cast <const exprt&>(
111- loop_end->guard .find (ID_C_spec_loop_invariant));
112- if (invariant.is_nil ())
113- {
114- return ;
115- }
116-
117- // change H: loop; E: ...
118- // to
119- // H: assert(invariant);
120- // if(nondet) goto E:
121- // havoc reads and writes of loop;
122- // assume(invariant);
123- // assume(guard) [only for for/while loops]
124- // loop;
125- // assert(invariant);
126- // assume(false);
127- // E: havoc writes of loop;
128- // assume(invariant)
129- // assume(!guard)
130- // ...
131-
132- // find out what can get changed in the loop
133- modifiest modifies;
134- get_modifies (local_may_alias, loop, modifies);
135-
136- // find out what is used by the loop
137- usest uses;
138- get_uses (local_may_alias, loop, uses);
139-
140- // build the havocking code
141- goto_programt havoc_all_code;
142- goto_programt havoc_writes_code;
143-
144- // assert the invariant
145- {
146- goto_programt::targett a=havoc_all_code.add_instruction (ASSERT);
147- a->guard =invariant;
148- a->function =loop_head->function ;
149- a->source_location =loop_head->source_location ;
150- a->source_location .set_comment (" Loop invariant violated before entry" );
151- }
152-
153- // nondeterministically skip the loop
154- {
155- goto_programt::targett jump=havoc_all_code.add_instruction (GOTO);
156- jump->guard =side_effect_expr_nondett (bool_typet ());
157- jump->targets .push_back (loop_end);
158- jump->function =loop_head->function ;
159- jump->source_location =loop_head->source_location ;
160- }
161-
162- // havoc variables being written to
163- build_havoc_code (loop_head, uses, havoc_all_code);
164-
165- // assume the invariant
166- {
167- goto_programt::targett assume=havoc_all_code.add_instruction (ASSUME);
168- assume->guard =invariant;
169- assume->function =loop_head->function ;
170- assume->source_location =loop_head->source_location ;
171- }
172-
173- // assert the invariant at the end of the loop body
174- {
175- goto_programt::targett a = goto_function.body .insert_before (loop_end);
176- a->type =ASSERT;
177- a->guard =invariant;
178- a->function =loop_end->function ;
179- a->source_location =loop_end->source_location ;
180- a->source_location .set_comment (" Loop invariant not preserved" );
181- }
182-
183- // assume false at the end of the loop to discharge the havocking
184- {
185- goto_programt::targett assume = goto_function.body .insert_before (loop_end);
186- assume->type =ASSUME;
187- assume->guard .make_false ();
188- assume->function =loop_end->function ;
189- assume->source_location =loop_end->source_location ;
190- }
191-
192- build_havoc_code (loop_end, modifies, havoc_writes_code);
193-
194- // Assume the invariant (now after the loop)
195- {
196- goto_programt::targett assume=havoc_writes_code.add_instruction (ASSUME);
197- assume->guard =invariant;
198- assume->function =loop_head->function ;
199- assume->source_location =loop_head->source_location ;
200- }
201-
202- // change the back edge into assume(!guard)
203- loop_end->targets .clear ();
204- loop_end->type =ASSUME;
205- if (loop_head->is_goto ())
206- {
207- loop_end->guard = loop_head->guard ;
208- }
209- else
210- {
211- loop_end->guard .make_not ();
212- }
213-
214- // Change the loop head to assume the guard if a for/while loop.
215- // This needs to be done after we case on what loop_head is in the previous
216- // section of setup.
217- if (loop_head->is_goto ())
218- {
219- exprt guard = loop_head->guard ;
220- guard.make_not ();
221- loop_head->make_assumption (guard);
222- }
223-
224- // Now havoc at the loop head. Use insert_swap to
225- // preserve jumps to loop head.
226- goto_function.body .insert_before_swap (loop_head, havoc_all_code);
227-
228- // Now havoc at the loop end. Use insert_swap to
229- // preserve jumps to loop end.
230- goto_function.body .insert_before_swap (loop_end, havoc_writes_code);
231- }
232-
23379void code_contractst::apply_contract (
23480 goto_programt &goto_program,
23581 goto_programt::targett target)
@@ -297,8 +143,6 @@ void code_contractst::apply_contract(
297143 // TODO: Havoc write set of the function between assert and ensure.
298144
299145 target->make_assumption (ensures);
300-
301- summarized.insert (function);
302146}
303147
304148void code_contractst::apply_invariant (
@@ -599,28 +443,6 @@ void code_contractst::check_apply_invariant(
599443 goto_function.body .insert_before_swap (loop_head, havoc_code);
600444}
601445
602- void code_contractst::code_contracts (
603- goto_functionst::goto_functiont &goto_function)
604- {
605- local_may_aliast local_may_alias (goto_function);
606- natural_loops_mutablet natural_loops (goto_function.body );
607-
608- // iterate over the (natural) loops in the function
609- for (const auto &l_it : natural_loops.loop_map )
610- {
611- check_apply_invariants (
612- goto_function,
613- local_may_alias,
614- l_it.first ,
615- l_it.second );
616- }
617-
618- // look at all function calls
619- Forall_goto_program_instructions (it, goto_function.body )
620- if (it->is_function_call ())
621- apply_contract (goto_function.body , it);
622- }
623-
624446const symbolt &code_contractst::new_tmp_symbol (
625447 const typet &type,
626448 const source_locationt &source_location)
@@ -634,122 +456,6 @@ const symbolt &code_contractst::new_tmp_symbol(
634456 symbol_table);
635457}
636458
637- void code_contractst::add_contract_check (
638- const irep_idt &function,
639- goto_programt &dest)
640- {
641- PRECONDITION (!dest.instructions .empty ());
642-
643- goto_functionst::function_mapt::iterator f_it=
644- goto_functions.function_map .find (function);
645- assert (f_it!=goto_functions.function_map .end ());
646-
647- const goto_functionst::goto_functiont &gf=f_it->second ;
648-
649- exprt requires = static_cast <const exprt&>(gf.type .find (ID_C_spec_requires));
650- exprt ensures = static_cast <const exprt&>(gf.type .find (ID_C_spec_ensures));
651- assert (ensures.is_not_nil ());
652-
653- // build:
654- // if(nondet)
655- // decl ret
656- // decl parameter1 ...
657- // assume(requires) [optional]
658- // ret=function(parameter1, ...)
659- // assert(ensures)
660- // assume(false)
661- // skip: ...
662-
663- // build skip so that if(nondet) can refer to it
664- goto_programt tmp_skip;
665- goto_programt::targett skip=tmp_skip.add_instruction (SKIP);
666- skip->function =dest.instructions .front ().function ;
667- skip->source_location =ensures.source_location ();
668-
669- goto_programt check;
670-
671- // if(nondet)
672- goto_programt::targett g=check.add_instruction ();
673- g->make_goto (skip, side_effect_expr_nondett (bool_typet ()));
674- g->function =skip->function ;
675- g->source_location =skip->source_location ;
676-
677- // prepare function call including all declarations
678- code_function_callt call;
679- call.function ()=ns.lookup (function).symbol_expr ();
680- replace_symbolt replace;
681-
682- // decl ret
683- if (gf.type .return_type ()!=empty_typet ())
684- {
685- goto_programt::targett d=check.add_instruction (DECL);
686- d->function =skip->function ;
687- d->source_location =skip->source_location ;
688-
689- symbol_exprt r=
690- new_tmp_symbol (gf.type .return_type (),
691- d->source_location ).symbol_expr ();
692- d->code =code_declt (r);
693-
694- call.lhs ()=r;
695-
696- replace.insert (" __CPROVER_return_value" , r);
697- }
698-
699- // decl parameter1 ...
700- for (const auto &p_it : gf.type .parameters ())
701- {
702- goto_programt::targett d=check.add_instruction (DECL);
703- d->function =skip->function ;
704- d->source_location =skip->source_location ;
705-
706- symbol_exprt p=
707- new_tmp_symbol (p_it.type (),
708- d->source_location ).symbol_expr ();
709- d->code =code_declt (p);
710-
711- call.arguments ().push_back (p);
712-
713- if (!p_it.get_identifier ().empty ())
714- replace.insert (p_it.get_identifier (), p);
715- }
716-
717- // rewrite any use of parameters
718- replace (requires );
719- replace (ensures);
720-
721- // assume(requires)
722- if (requires .is_not_nil ())
723- {
724- goto_programt::targett a=check.add_instruction ();
725- a->make_assumption (requires );
726- a->function =skip->function ;
727- a->source_location =requires .source_location ();
728- }
729-
730- // ret=function(parameter1, ...)
731- goto_programt::targett f=check.add_instruction ();
732- f->make_function_call (call);
733- f->function =skip->function ;
734- f->source_location =skip->source_location ;
735-
736- // assert(ensures)
737- goto_programt::targett a=check.add_instruction ();
738- a->make_assertion (ensures);
739- a->function =skip->function ;
740- a->source_location =ensures.source_location ();
741-
742- // assume(false)
743- goto_programt::targett af=check.add_instruction ();
744- af->make_assumption (false_exprt ());
745- af->function =skip->function ;
746- af->source_location =ensures.source_location ();
747-
748- // prepend the new code to dest
749- check.destructive_append (tmp_skip);
750- dest.destructive_insert (dest.instructions .begin (), check);
751- }
752-
753459void code_contractst::apply_code_contracts ()
754460{
755461 Forall_goto_functions (it, goto_functions)
0 commit comments