CBMC
Loading...
Searching...
No Matches
goto_program2code.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Dump Goto-Program as C/C++ Source
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include "goto_program2code.h"
13
14#include <util/arith_tools.h>
15#include <util/bitvector_expr.h>
16#include <util/c_types.h>
17#include <util/expr_util.h>
18#include <util/ieee_float.h>
19#include <util/pointer_expr.h>
20#include <util/prefix.h>
21#include <util/simplify_expr.h>
22#include <util/std_code.h>
23
24#include <sstream>
25
27{
28 // labels stored for cleanup
30
31 // just an estimate
32 toplevel_block.reserve_operands(goto_program.instructions.size());
33
34 // find loops first
36
37 // gather variable scope information
39
40 // see whether var args are in use, identify va_list symbol
42
43 // convert
46 target,
47 goto_program.instructions.end(),
49
51}
52
54{
56 loops.loop_map.clear();
58
59 for(natural_loopst::loop_mapt::const_iterator
60 l_it=loops.loop_map.begin();
61 l_it!=loops.loop_map.end();
62 ++l_it)
63 {
64 PRECONDITION(!l_it->second.empty());
65
66 // l_it->first need not be the program-order first instruction in the
67 // natural loop, because a natural loop may have multiple entries. But we
68 // ignore all those before l_it->first
69 // Furthermore the loop may contain code after the source of the actual back
70 // edge -- we also ignore such code
73 for(natural_loopst::natural_loopt::const_iterator
74 it=l_it->second.begin();
75 it!=l_it->second.end();
76 ++it)
77 if((*it)->is_goto())
78 {
79 if((*it)->get_target()==loop_start &&
80 (*it)->location_number>loop_end->location_number)
81 loop_end=*it;
82 }
83
84 if(!loop_map.insert(std::make_pair(loop_start, loop_end)).second)
86 }
87}
88
90{
92
93 // record last dead X
94 for(const auto &instruction : goto_program.instructions)
95 {
96 if(instruction.is_dead())
97 {
98 dead_map[instruction.dead_symbol().get_identifier()] =
99 instruction.location_number;
100 }
101 }
102}
103
105{
107
108 for(const auto &instruction : goto_program.instructions)
109 {
110 if(instruction.is_assign())
111 {
112 const exprt &l = instruction.assign_lhs();
113 const exprt &r = instruction.assign_rhs();
114
115 // find va_start
116 if(
117 r.id() == ID_side_effect &&
119 {
120 va_list_expr.insert(to_unary_expr(r).op());
121 }
122 // try our modelling of va_start
123 else if(l.type().id()==ID_pointer &&
124 l.type().get(ID_C_typedef)=="va_list" &&
125 l.id()==ID_symbol &&
126 r.id()==ID_typecast &&
127 to_typecast_expr(r).op().id()==ID_address_of)
128 va_list_expr.insert(l);
129 }
130 }
131
132 if(!va_list_expr.empty())
133 system_headers.insert("stdarg.h");
134}
135
139 code_blockt &dest)
140{
141 PRECONDITION(target != goto_program.instructions.end());
142
143 if(
144 target->type() != ASSERT &&
145 !target->source_location().get_comment().empty())
146 {
147 dest.add(code_skipt());
148 dest.statements().back().add_source_location().set_comment(
149 target->source_location().get_comment());
150 }
151
152 // try do-while first
153 if(target->is_target() && !target->is_goto())
154 {
155 loopt::const_iterator loop_entry=loop_map.find(target);
156
157 if(loop_entry!=loop_map.end() &&
158 (upper_bound==goto_program.instructions.end() ||
159 upper_bound->location_number > loop_entry->second->location_number))
160 return convert_do_while(target, loop_entry->second, dest);
161 }
162
163 convert_labels(target, dest);
164
165 switch(target->type())
166 {
167 case SKIP:
168 case LOCATION:
169 case END_FUNCTION:
170 case DEAD:
171 // ignore for now
172 dest.add(code_skipt());
173 return target;
174
175 case FUNCTION_CALL:
176 {
178 target->call_lhs(), target->call_function(), target->call_arguments());
179 dest.add(call);
180 }
181 return target;
182
183 case OTHER:
184 dest.add(target->get_other());
185 return target;
186
187 case ASSIGN:
188 return convert_assign(target, upper_bound, dest);
189
190 case SET_RETURN_VALUE:
191 return convert_set_return_value(target, upper_bound, dest);
192
193 case DECL:
194 return convert_decl(target, upper_bound, dest);
195
196 case ASSERT:
197 system_headers.insert("assert.h");
198 dest.add(code_assertt(target->condition()));
199 dest.statements().back().add_source_location().set_comment(
200 target->source_location().get_comment());
201 return target;
202
203 case ASSUME:
204 dest.add(code_assumet(target->condition()));
205 return target;
206
207 case GOTO:
208 return convert_goto(target, upper_bound, dest);
209
210 case START_THREAD:
211 return convert_start_thread(target, upper_bound, dest);
212
213 case END_THREAD:
215 dest.statements().back().add_source_location().set_comment("END_THREAD");
216 return target;
217
218 case ATOMIC_BEGIN:
219 case ATOMIC_END:
220 {
221 const code_typet void_t({}, empty_typet());
223 target->is_atomic_begin() ? CPROVER_PREFIX "atomic_begin"
224 : CPROVER_PREFIX "atomic_end",
225 void_t));
226 dest.add(std::move(f));
227 return target;
228 }
229
230 case THROW:
231 return convert_throw(target, dest);
232
233 case CATCH:
234 return convert_catch(target, upper_bound, dest);
235
237 case INCOMPLETE_GOTO:
239 }
240
241 // not reached
243 return target;
244}
245
248 code_blockt &dest)
249{
250 code_blockt *latest_block = &dest;
251
253 if(target->is_target())
254 {
255 std::stringstream label;
256 label << CPROVER_PREFIX "DUMP_L" << target->target_number;
257 code_labelt l(label.str(), code_blockt());
258 l.add_source_location() = target->source_location();
260 latest_block->add(std::move(l));
262 &to_code_block(to_code_label(latest_block->statements().back()).code());
263 }
264
265 for(goto_programt::instructiont::labelst::const_iterator
266 it=target->labels.begin();
267 it!=target->labels.end();
268 ++it)
269 {
270 if(
271 it->starts_with(CPROVER_PREFIX "ASYNC_") ||
272 it->starts_with(CPROVER_PREFIX "DUMP_L"))
273 {
274 continue;
275 }
276
277 // keep all original labels
278 labels_in_use.insert(*it);
279
280 code_labelt l(*it, code_blockt());
281 l.add_source_location() = target->source_location();
282 latest_block->add(std::move(l));
284 &to_code_block(to_code_label(latest_block->statements().back()).code());
285 }
286
287 if(latest_block!=&dest)
288 latest_block->add(code_skipt());
289}
290
294 code_blockt &dest)
295{
296 const code_assignt a{target->assign_lhs(), target->assign_rhs()};
297
298 if(va_list_expr.find(a.lhs())!=va_list_expr.end())
299 return convert_assign_varargs(target, upper_bound, dest);
300 else
301 convert_assign_rec(a, dest);
302
303 return target;
304}
305
309 code_blockt &dest)
310{
311 const exprt this_va_list_expr = target->assign_lhs();
312 const exprt &r = skip_typecast(target->assign_rhs());
313
314 if(r.is_constant() && to_constant_expr(r).is_null_pointer())
315 {
317 symbol_exprt("va_end", code_typet({}, empty_typet())),
319
320 dest.add(std::move(f));
321 }
322 else if(
323 r.id() == ID_side_effect &&
325 {
330
331 dest.add(std::move(f));
332 }
333 else if(r.id() == ID_plus)
334 {
336 symbol_exprt("va_arg", code_typet({}, empty_typet())),
338
339 // we do not bother to set the correct types here, they are not relevant for
340 // generating the correct dumped output
342 symbol_exprt("__typeof__", code_typet({}, empty_typet())),
343 {},
344 typet{},
346
347 // if the return value is used, the next instruction will be assign
349 ++next;
350 CHECK_RETURN(next != goto_program.instructions.end());
351 if(next!=upper_bound &&
352 next->is_assign())
353 {
354 const exprt &n_r = next->assign_rhs();
355 if(
356 n_r.id() == ID_dereference &&
358 {
359 f.lhs() = next->assign_lhs();
360
361 type_of.arguments().push_back(f.lhs());
362 f.arguments().push_back(type_of);
363
364 dest.add(std::move(f));
365 return next;
366 }
367 }
368
369 // assignment not found, still need a proper typeof expression
371 r.find(ID_C_va_arg_type).is_not_nil(), "#va_arg_type must be set");
372 const typet &va_arg_type=
373 static_cast<typet const&>(r.find(ID_C_va_arg_type));
374
378
379 type_of.arguments().push_back(deref);
380 f.arguments().push_back(type_of);
381
383
384 dest.add(std::move(void_f));
385 }
386 else
387 {
389 symbol_exprt("va_copy", code_typet({}, empty_typet())),
391
392 dest.add(std::move(f));
393 }
394
395 return target;
396}
397
399 const code_assignt &assign,
400 code_blockt &dest)
401{
402 if(assign.rhs().id()==ID_array)
403 {
404 const array_typet &type = to_array_type(assign.rhs().type());
405
406 unsigned i=0;
407 for(const auto &op : assign.rhs().operands())
408 {
409 index_exprt index(
410 assign.lhs(),
411 from_integer(i++, type.index_type()),
412 type.element_type());
413 convert_assign_rec(code_assignt(index, op), dest);
414 }
415 }
416 else
417 dest.add(assign);
418}
419
423 code_blockt &dest)
424{
425 // add return instruction unless original code was missing a return
426 if(
427 target->return_value().id() != ID_side_effect ||
428 to_side_effect_expr(target->return_value()).get_statement() != ID_nondet)
429 {
430 dest.add(code_returnt{target->return_value()});
431 }
432
433 // all v3 (or later) goto programs have an explicit GOTO after return
435 ++next;
436 CHECK_RETURN(next != goto_program.instructions.end());
437
438 // skip goto (and possibly dead), unless crossing the current boundary
439 while(next!=upper_bound && next->is_dead() && !next->is_target())
440 ++next;
441
442 if(next!=upper_bound &&
443 next->is_goto() &&
444 !next->is_target())
445 target=next;
446
447 return target;
448}
449
453 code_blockt &dest)
454{
455 code_frontend_declt d = code_frontend_declt{target->decl_symbol()};
456 symbol_exprt &symbol = d.symbol();
457
459 ++next;
460 CHECK_RETURN(next != goto_program.instructions.end());
461
462 // see if decl can go in current dest block
463 dead_mapt::const_iterator entry=dead_map.find(symbol.get_identifier());
464 bool move_to_dest= &toplevel_block==&dest ||
465 (entry!=dead_map.end() &&
466 upper_bound->location_number > entry->second);
467
468 // move back initialising assignments into the decl, unless crossing the
469 // current boundary
470 if(next!=upper_bound &&
471 move_to_dest &&
472 !next->is_target() &&
473 (next->is_assign() || next->is_function_call()))
474 {
475 exprt lhs = next->is_assign() ? next->assign_lhs() : next->call_lhs();
476 if(lhs==symbol &&
477 va_list_expr.find(lhs)==va_list_expr.end())
478 {
479 if(next->is_assign())
480 {
481 d.set_initial_value({next->assign_rhs()});
482 }
483 else
484 {
485 // could hack this by just erasing the first operand
487 next->call_function(),
488 next->call_arguments(),
489 typet{},
492 }
493
494 ++target;
495 convert_labels(target, dest);
496 }
497 else
498 remove_const(symbol.type());
499 }
500 // if we have a constant but can't initialize them right away, we need to
501 // remove the const marker
502 else
503 remove_const(symbol.type());
504
505 if(move_to_dest)
506 dest.add(std::move(d));
507 else
509
510 return target;
511}
512
516 code_blockt &dest)
517{
518 PRECONDITION(loop_end->is_goto() && loop_end->is_backwards_goto());
519
520 code_dowhilet d(loop_end->condition(), code_blockt());
521 simplify(d.cond(), ns);
522
523 copy_source_location(loop_end->targets.front(), d);
524
525 loop_last_stack.push_back(std::make_pair(loop_end, true));
526
527 for( ; target!=loop_end; ++target)
528 target = convert_instruction(target, loop_end, to_code_block(d.body()));
529
530 loop_last_stack.pop_back();
531
533
534 dest.add(std::move(d));
535 return target;
536}
537
541 code_blockt &dest)
542{
543 PRECONDITION(target->is_goto());
544 // we only do one target for now
545 PRECONDITION(target->targets.size() == 1);
546
547 loopt::const_iterator loop_entry=loop_map.find(target);
548
549 if(loop_entry!=loop_map.end() &&
550 (upper_bound==goto_program.instructions.end() ||
551 upper_bound->location_number > loop_entry->second->location_number))
552 return convert_goto_while(target, loop_entry->second, dest);
553 else if(!target->condition().is_true())
554 return convert_goto_switch(target, upper_bound, dest);
555 else if(!loop_last_stack.empty())
556 return convert_goto_break_continue(target, upper_bound, dest);
557 else
558 return convert_goto_goto(target, dest);
559}
560
564 code_blockt &dest)
565{
566 PRECONDITION(loop_end->is_goto() && loop_end->is_backwards_goto());
567
568 if(target==loop_end) // 1: GOTO 1
569 return convert_goto_goto(target, dest);
570
573 ++after_loop;
574 CHECK_RETURN(after_loop != goto_program.instructions.end());
575
576 copy_source_location(target, w);
577
578 if(target->get_target()==after_loop)
579 {
580 w.cond() = not_exprt(target->condition());
581 simplify(w.cond(), ns);
582 }
583 else if(target->condition().is_true())
584 {
585 target = convert_goto_goto(target, to_code_block(w.body()));
586 }
587 else
588 {
589 target = convert_goto_switch(target, loop_end, to_code_block(w.body()));
590 }
591
592 loop_last_stack.push_back(std::make_pair(loop_end, true));
593
594 for(++target; target!=loop_end; ++target)
595 target = convert_instruction(target, loop_end, to_code_block(w.body()));
596
597 loop_last_stack.pop_back();
598
600 if(loop_end->condition().is_false())
601 {
602 to_code_block(w.body()).add(code_breakt());
603 }
604 else if(!loop_end->condition().is_true())
605 {
607 simplify(i.cond(), ns);
608
609 copy_source_location(target, i);
610
611 to_code_block(w.body()).add(std::move(i));
612 }
613
614 if(w.body().has_operands() &&
615 to_code(w.body().operands().back()).get_statement()==ID_assign)
616 {
617 exprt increment = w.body().operands().back();
618 w.body().operands().pop_back();
619 increment.id(ID_side_effect);
620
621 code_fort f(nil_exprt(), w.cond(), increment, w.body());
622
623 copy_source_location(target, f);
624
625 f.swap(w);
626 }
627 else if(w.body().has_operands() &&
628 w.cond().is_true())
629 {
630 const codet &back=to_code(w.body().operands().back());
631
632 if(back.get_statement()==ID_break ||
633 (back.get_statement()==ID_ifthenelse &&
634 to_code_ifthenelse(back).cond().is_true() &&
635 to_code_ifthenelse(back).then_case().get_statement()==ID_break))
636 {
637 w.body().operands().pop_back();
638 code_dowhilet d(false_exprt(), w.body());
639
640 copy_source_location(target, d);
641
642 d.swap(w);
643 }
644 }
645
646 dest.add(std::move(w));
647
648 return target;
649}
650
654 const exprt &switch_var,
655 cases_listt &cases,
657 goto_programt::const_targett &default_target)
658{
660 std::set<goto_programt::const_targett, goto_programt::target_less_than>
662
664 for( ;
665 cases_it!=upper_bound && cases_it!=first_target;
666 ++cases_it)
667 {
668 if(
669 cases_it->is_goto() && !cases_it->is_backwards_goto() &&
670 cases_it->condition().is_true())
671 {
672 default_target=cases_it->get_target();
673
674 if(first_target==goto_program.instructions.end() ||
675 first_target->location_number > default_target->location_number)
676 first_target=default_target;
677 if(last_target==goto_program.instructions.end() ||
678 last_target->location_number < default_target->location_number)
679 last_target=default_target;
680
681 cases.push_back(caset(
683 nil_exprt(),
684 cases_it,
685 default_target));
686 unique_targets.insert(default_target);
687
688 ++cases_it;
689 break;
690 }
691 else if(
692 cases_it->is_goto() && !cases_it->is_backwards_goto() &&
693 (cases_it->condition().id() == ID_equal ||
694 cases_it->condition().id() == ID_or))
695 {
697 if(cases_it->condition().id() == ID_equal)
698 eqs.push_back(cases_it->condition());
699 else
700 eqs = cases_it->condition().operands();
701
702 // goto conversion builds disjunctions in reverse order
703 // to ensure convergence, we turn this around again
704 for(exprt::operandst::const_reverse_iterator
705 e_it=eqs.rbegin();
706 e_it!=(exprt::operandst::const_reverse_iterator)eqs.rend();
707 ++e_it)
708 {
709 if(e_it->id()!=ID_equal ||
710 !skip_typecast(to_equal_expr(*e_it).rhs()).is_constant() ||
711 switch_var!=to_equal_expr(*e_it).lhs())
712 return target;
713
714 cases.push_back(caset(
716 to_equal_expr(*e_it).rhs(),
717 cases_it,
718 cases_it->get_target()));
719 DATA_INVARIANT(cases.back().value.is_not_nil(), "cases should be set");
720
721 if(first_target==goto_program.instructions.end() ||
722 first_target->location_number>
723 cases.back().case_start->location_number)
724 first_target=cases.back().case_start;
725 if(last_target==goto_program.instructions.end() ||
726 last_target->location_number<
727 cases.back().case_start->location_number)
728 last_target=cases.back().case_start;
729
730 unique_targets.insert(cases.back().case_start);
731 }
732 }
733 else
734 return target;
735 }
736
737 // if there are less than 3 targets, we revert to if/else instead; this should
738 // help convergence
739 if(unique_targets.size()<3)
740 return target;
741
742 // make sure we don't have some overlap of gotos and switch/case
743 if(cases_it==upper_bound ||
744 (upper_bound!=goto_program.instructions.end() &&
745 upper_bound->location_number < last_target->location_number) ||
746 (last_target!=goto_program.instructions.end() &&
747 last_target->location_number > default_target->location_number) ||
748 target->get_target()==default_target)
749 return target;
750
751 return cases_it;
752}
753
756 const cfg_dominatorst &dominators,
757 cases_listt &cases,
758 std::set<unsigned> &processed_locations)
759{
760 std::set<goto_programt::const_targett, goto_programt::target_less_than>
762
763 for(cases_listt::iterator it=cases.begin();
764 it!=cases.end();
765 ++it)
766 {
767 // some branch targets may be shared by multiple branch instructions,
768 // as in case 1: case 2: code; we build a nested code_switch_caset
769 if(!targets_done.insert(it->case_start).second)
770 continue;
771
772 // compute the block that belongs to this case
773 for(goto_programt::const_targett case_end = it->case_start;
774 case_end != goto_program.instructions.end() &&
775 case_end->type() != END_FUNCTION && case_end != upper_bound;
776 ++case_end)
777 {
778 const auto &case_end_node = dominators.get_node(case_end);
779
780 // ignore dead instructions for the following checks
782 {
783 // simplification may have figured out that a case is unreachable
784 // this is possibly getting too weird, abort to be safe
785 if(case_end==it->case_start)
786 return true;
787
788 continue;
789 }
790
791 // find the last instruction dominated by the case start
792 if(!dominators.dominates(it->case_start, case_end_node))
793 break;
794
795 if(!processed_locations.insert(case_end->location_number).second)
797
798 it->case_last=case_end;
799 }
800 }
801
802 return false;
803}
804
806 const cfg_dominatorst &dominators,
807 const cases_listt &cases,
808 goto_programt::const_targett default_target)
809{
810 for(cases_listt::const_iterator it=cases.begin();
811 it!=cases.end();
812 ++it)
813 {
814 // ignore empty cases
815 if(it->case_last==goto_program.instructions.end())
816 continue;
817
818 // the last case before default is the most interesting
819 cases_listt::const_iterator last=--cases.end();
820 if(last->case_start==default_target &&
821 it==--last)
822 {
823 // ignore dead instructions for the following checks
825 for(++next_case;
826 next_case!=goto_program.instructions.end();
827 ++next_case)
828 {
829 if(dominators.program_point_reachable(next_case))
830 break;
831 }
832
833 if(
834 next_case != goto_program.instructions.end() &&
835 next_case == default_target &&
836 (!it->case_last->is_goto() ||
837 (it->case_last->condition().is_true() &&
838 it->case_last->get_target() == default_target)))
839 {
840 // if there is no goto here, yet we got here, all others would
841 // branch to this - we don't need default
842 return true;
843 }
844 }
845
846 // jumps to default are ok
847 if(
848 it->case_last->is_goto() && it->case_last->condition().is_true() &&
849 it->case_last->get_target() == default_target)
850 continue;
851
852 // fall-through is ok
853 if(!it->case_last->is_goto())
854 continue;
855
856 return false;
857 }
858
859 return false;
860}
861
865 code_blockt &dest)
866{
867 // try to figure out whether this was a switch/case
868 exprt eq_cand = target->condition();
869 if(eq_cand.id()==ID_or)
870 eq_cand = to_or_expr(eq_cand).op0();
871
872 if(target->is_backwards_goto() ||
873 eq_cand.id()!=ID_equal ||
875 return convert_goto_if(target, upper_bound, dest);
876
877 const cfg_dominatorst &dominators=loops.get_dominator_info();
878
879 // always use convert_goto_if for dead code as the construction below relies
880 // on effective dominator information
881 if(!dominators.program_point_reachable(target))
882 return convert_goto_if(target, upper_bound, dest);
883
884 // maybe, let's try some more
886
887 copy_source_location(target, s);
888
889 // find the cases or fall back to convert_goto_if
890 cases_listt cases;
892 goto_program.instructions.end();
893 goto_programt::const_targett default_target=
894 goto_program.instructions.end();
895
897 get_cases(
898 target,
899 upper_bound,
900 s.value(),
901 cases,
903 default_target);
904
905 if(cases_start==target)
906 return convert_goto_if(target, upper_bound, dest);
907
908 // backup the top-level block as we might have to backtrack
910
911 // add any instructions that go in the body of the switch before any cases
913 for(target=cases_start; target!=first_target; ++target)
914 target = convert_instruction(target, first_target, to_code_block(s.body()));
915
916 std::set<unsigned> processed_locations;
917
918 // iterate over all cases to identify block end points
919 if(set_block_end_points(upper_bound, dominators, cases, processed_locations))
920 {
922 return convert_goto_if(orig_target, upper_bound, dest);
923 }
924
925 // figure out whether we really had a default target by testing
926 // whether all cases eventually jump to the default case
927 if(remove_default(dominators, cases, default_target))
928 {
929 cases.pop_back();
930 default_target=goto_program.instructions.end();
931 }
932
933 // find the last instruction belonging to any of the cases
935 for(cases_listt::const_iterator it=cases.begin();
936 it!=cases.end();
937 ++it)
938 if(it->case_last!=goto_program.instructions.end() &&
939 it->case_last->location_number > max_target->location_number)
940 max_target=it->case_last;
941
942 std::
943 map<goto_programt::const_targett, unsigned, goto_programt::target_less_than>
945 loop_last_stack.push_back(std::make_pair(max_target, false));
946
947 // iterate over all <branch conditions, branch instruction, branch target>
948 // triples, build their corresponding code
949 for(cases_listt::const_iterator it=cases.begin();
950 it!=cases.end();
951 ++it)
952 {
954 // branch condition is nil_exprt for default case;
955 if(it->value.is_nil())
956 csc.set_default();
957 else
958 csc.case_op()=it->value;
959
960 // some branch targets may be shared by multiple branch instructions,
961 // as in case 1: case 2: code; we build a nested code_switch_caset
962 if(targets_done.find(it->case_start)!=targets_done.end())
963 {
965 it->case_selector == orig_target || !it->case_selector->is_target(),
966 "valid case selector required");
967
968 // maintain the order to ensure convergence -> go to the innermost
970 to_code(s.body().operands()[targets_done[it->case_start]]));
971 while(cscp->code().get_statement()==ID_switch_case)
972 cscp=&to_code_switch_case(cscp->code());
973
974 csc.code().swap(cscp->code());
975 cscp->code().swap(csc);
976
977 continue;
978 }
979
981 if(it->case_selector!=orig_target)
982 convert_labels(it->case_selector, c);
983
984 // convert the block that belongs to this case
985 target=it->case_start;
986
987 // empty case
988 if(it->case_last==goto_program.instructions.end())
989 {
990 // only emit the jump out of the switch if it's not the last case
991 // this improves convergence
992 if(it->case_start!=(--cases.end())->case_start)
993 {
995 goto_programt::instructiont i=*(it->case_selector);
998 tmp.insert_before_swap(tmp.insert_before(tmp.instructions.end()), i);
999 convert_goto_goto(tmp.instructions.begin(), c);
1000 }
1001 }
1002 else
1003 {
1005 ++after_last;
1006 for( ; target!=after_last; ++target)
1007 target=convert_instruction(target, after_last, c);
1008 }
1009
1010 csc.code().swap(c);
1011 targets_done[it->case_start]=s.body().operands().size();
1012 to_code_block(s.body()).add(std::move(csc));
1013 }
1014
1015 loop_last_stack.pop_back();
1016
1017 // make sure we didn't miss any non-dead instruction
1019 it!=target;
1020 ++it)
1021 if(processed_locations.find(it->location_number)==
1022 processed_locations.end())
1023 {
1024 if(dominators.program_point_reachable(it))
1025 {
1027 return convert_goto_if(orig_target, upper_bound, dest);
1028 }
1029 }
1030
1031 dest.add(std::move(s));
1032 return max_target;
1033}
1034
1037 goto_programt::const_targett upper_bound,
1038 code_blockt &dest)
1039{
1040 goto_programt::const_targett else_case=target->get_target();
1042 goto_programt::const_targett end_if=target->get_target();
1043 PRECONDITION(end_if != goto_program.instructions.end());
1044 bool has_else=false;
1045
1046 if(!target->is_backwards_goto())
1047 {
1048 PRECONDITION(else_case != goto_program.instructions.begin());
1049 --before_else;
1050
1051 // goto 1
1052 // 1: ...
1053 if(before_else==target)
1054 {
1055 dest.add(code_skipt());
1056 return target;
1057 }
1058
1059 has_else =
1060 before_else->is_goto() &&
1061 before_else->get_target()->location_number > end_if->location_number &&
1062 before_else->condition().is_true() &&
1063 (upper_bound == goto_program.instructions.end() ||
1064 upper_bound->location_number >=
1065 before_else->get_target()->location_number);
1066
1067 if(has_else)
1068 end_if=before_else->get_target();
1069 }
1070
1071 // some nesting of loops and branches we might not be able to deal with
1072 if(target->is_backwards_goto() ||
1073 (upper_bound!=goto_program.instructions.end() &&
1074 upper_bound->location_number < end_if->location_number))
1075 {
1076 if(!loop_last_stack.empty())
1077 return convert_goto_break_continue(target, upper_bound, dest);
1078 else
1079 return convert_goto_goto(target, dest);
1080 }
1081
1082 code_ifthenelset i(not_exprt(target->condition()), code_blockt());
1083 copy_source_location(target, i);
1084 simplify(i.cond(), ns);
1085
1086 if(has_else)
1087 i.else_case()=code_blockt();
1088
1089 if(has_else)
1090 {
1091 for(++target; target!=before_else; ++target)
1092 target =
1094
1096
1097 for(++target; target!=end_if; ++target)
1098 target =
1100 }
1101 else
1102 {
1103 for(++target; target!=end_if; ++target)
1104 target =
1106 }
1107
1108 dest.add(std::move(i));
1109 return --target;
1110}
1111
1114 goto_programt::const_targett upper_bound,
1115 code_blockt &dest)
1116{
1117 PRECONDITION(!loop_last_stack.empty());
1118 const cfg_dominatorst &dominators=loops.get_dominator_info();
1119
1120 // goto 1
1121 // 1: ...
1122 goto_programt::const_targett next=target;
1123 for(++next;
1124 next!=upper_bound && next!=goto_program.instructions.end();
1125 ++next)
1126 {
1127 if(dominators.program_point_reachable(next))
1128 break;
1129 }
1130
1131 if(target->get_target()==next)
1132 {
1133 dest.add(code_skipt());
1134 // skip over all dead instructions
1135 return --next;
1136 }
1137
1139
1140 if(target->get_target()==loop_end &&
1141 loop_last_stack.back().second)
1142 {
1143 code_ifthenelset i(target->condition(), code_continuet());
1144 simplify(i.cond(), ns);
1145
1146 copy_source_location(target, i);
1147
1148 if(i.cond().is_true())
1149 dest.add(std::move(i.then_case()));
1150 else
1151 dest.add(std::move(i));
1152
1153 return target;
1154 }
1155
1157 for(++after_loop;
1158 after_loop!=goto_program.instructions.end();
1159 ++after_loop)
1160 {
1161 if(dominators.program_point_reachable(after_loop))
1162 break;
1163 }
1164
1165 if(target->get_target()==after_loop)
1166 {
1167 code_ifthenelset i(target->condition(), code_breakt());
1168 simplify(i.cond(), ns);
1169
1170 copy_source_location(target, i);
1171
1172 if(i.cond().is_true())
1173 dest.add(std::move(i.then_case()));
1174 else
1175 dest.add(std::move(i));
1176
1177 return target;
1178 }
1179
1180 return convert_goto_goto(target, dest);
1181}
1182
1185 code_blockt &dest)
1186{
1187 // filter out useless goto 1; 1: ...
1188 goto_programt::const_targett next=target;
1189 ++next;
1190 if(target->get_target()==next)
1191 return target;
1192
1193 const cfg_dominatorst &dominators=loops.get_dominator_info();
1194
1195 // skip dead goto L as the label might be skipped if it is dead
1196 // as well and at the end of a case block
1197 if(!dominators.program_point_reachable(target))
1198 return target;
1199
1200 std::stringstream label;
1201 // try user-defined labels first
1202 for(goto_programt::instructiont::labelst::const_iterator
1203 it=target->get_target()->labels.begin();
1204 it!=target->get_target()->labels.end();
1205 ++it)
1206 {
1207 if(
1208 it->starts_with(CPROVER_PREFIX "ASYNC_") ||
1209 it->starts_with(CPROVER_PREFIX "DUMP_L"))
1210 {
1211 continue;
1212 }
1213
1214 label << *it;
1215 break;
1216 }
1217
1218 if(label.str().empty())
1219 label << CPROVER_PREFIX "DUMP_L" << target->get_target()->target_number;
1220
1221 labels_in_use.insert(label.str());
1222
1223 code_gotot goto_code(label.str());
1224
1225 code_ifthenelset i(target->condition(), std::move(goto_code));
1226 simplify(i.cond(), ns);
1227
1228 copy_source_location(target, i);
1229
1230 if(i.cond().is_true())
1231 dest.add(std::move(i.then_case()));
1232 else
1233 dest.add(std::move(i));
1234
1235 return target;
1236}
1237
1240 goto_programt::const_targett upper_bound,
1241 code_blockt &dest)
1242{
1243 PRECONDITION(target->is_start_thread());
1244
1245 goto_programt::const_targett thread_start=target->get_target();
1246 PRECONDITION(thread_start->location_number > target->location_number);
1247
1248 goto_programt::const_targett next=target;
1249 ++next;
1250 CHECK_RETURN(next != goto_program.instructions.end());
1251
1252 // first check for old-style code:
1253 // __CPROVER_DUMP_0: START THREAD 1
1254 // code in existing thread
1255 // END THREAD
1256 // 1: code in new thread
1257 if(!next->is_goto())
1258 {
1260 ++this_end;
1261 DATA_INVARIANT(this_end->is_end_thread(), "should be end-of-thread");
1263 thread_start->location_number > this_end->location_number,
1264 "start of new thread must precede end of thread");
1265
1268
1269 for(goto_programt::instructiont::labelst::const_iterator
1270 it=target->labels.begin();
1271 it!=target->labels.end();
1272 ++it)
1273 if(it->starts_with(CPROVER_PREFIX "ASYNC_"))
1274 {
1275 labels_in_use.insert(*it);
1276
1277 code_labelt l(*it, std::move(b));
1278 l.add_source_location() = target->source_location();
1279 b = std::move(l);
1280 }
1281
1282 DATA_INVARIANT(b.get_statement() == ID_label, "must be label statement");
1283 dest.add(std::move(b));
1284 return this_end;
1285 }
1286
1287 // code is supposed to look like this:
1288 // __CPROVER_ASYNC_0: START THREAD 1
1289 // GOTO 2
1290 // 1: code in new thread
1291 // END THREAD
1292 // 2: code in existing thread
1293 /* check the structure and compute the iterators */
1295 next->is_goto() && next->condition().is_true(), "START THREAD pattern");
1296 DATA_INVARIANT(!next->is_backwards_goto(), "START THREAD pattern");
1298 thread_start->location_number < next->get_target()->location_number,
1299 "START THREAD pattern");
1302
1303 goto_programt::const_targett thread_end=next->get_target();
1304 --thread_end;
1306 thread_start->location_number < thread_end->location_number,
1307 "monotone location numbers");
1308 DATA_INVARIANT(thread_end->is_end_thread(), "should be end-of-thread");
1309
1311 upper_bound == goto_program.instructions.end() ||
1312 thread_end->location_number < upper_bound->location_number,
1313 "end or monotone location numbers");
1314 /* end structure check */
1315
1316 // use pthreads if "code in new thread" is a function call to a function with
1317 // suitable signature
1318 if(
1319 thread_start->is_function_call() &&
1320 thread_start->call_arguments().size() == 1 &&
1322 {
1323 system_headers.insert("pthread.h");
1324
1327 thread_start->call_lhs(),
1328 symbol_exprt("pthread_create", code_typet({}, empty_typet())),
1329 {n,
1330 n,
1331 thread_start->call_function(),
1332 thread_start->call_arguments().front()}));
1333
1334 return thread_end;
1335 }
1336
1339 thread_start =
1341
1342 for(goto_programt::instructiont::labelst::const_iterator
1343 it=target->labels.begin();
1344 it!=target->labels.end();
1345 ++it)
1346 if(it->starts_with(CPROVER_PREFIX "ASYNC_"))
1347 {
1348 labels_in_use.insert(*it);
1349
1350 code_labelt l(*it, std::move(b));
1351 l.add_source_location() = target->source_location();
1352 b = std::move(l);
1353 }
1354
1355 DATA_INVARIANT(b.get_statement() == ID_label, "should be label statement");
1356 dest.add(std::move(b));
1357 return thread_end;
1358}
1359
1362 code_blockt &)
1363{
1364 // this isn't really clear as throw is not supported in expr2cpp either
1366 return target;
1367}
1368
1372 code_blockt &)
1373{
1374 // this isn't really clear as catch is not supported in expr2cpp either
1376 return target;
1377}
1378
1380{
1381 if(type.id() == ID_struct_tag || type.id() == ID_union_tag)
1382 {
1383 const irep_idt &identifier = to_tag_type(type).get_identifier();
1384 const symbolt &symbol = ns.lookup(identifier);
1385
1386 if(
1387 symbol.location.get_function().empty() ||
1388 !type_names_set.insert(identifier).second)
1389 return;
1390
1391 const auto &components =
1392 ns.follow_tag(to_struct_or_union_tag_type(type)).components();
1393 for(const auto &c : components)
1394 add_local_types(c.type());
1395
1396 type_names.push_back(identifier);
1397 }
1398 else if(type.id()==ID_c_enum_tag)
1399 {
1400 const irep_idt &identifier=to_c_enum_tag_type(type).get_identifier();
1401 const symbolt &symbol=ns.lookup(identifier);
1402
1403 if(symbol.location.get_function().empty() ||
1404 !type_names_set.insert(identifier).second)
1405 return;
1406
1407 DATA_INVARIANT(!identifier.empty(), "identifier required");
1408 type_names.push_back(identifier);
1409 }
1410 else if(type.id()==ID_pointer ||
1411 type.id()==ID_array)
1412 {
1413 add_local_types(to_type_with_subtype(type).subtype());
1414 }
1415}
1416
1418 codet &code,
1419 const irep_idt parent_stmt)
1420{
1421 if(code.get_statement()==ID_decl)
1422 {
1423 if(code.operands().size()==2 &&
1424 code.op1().id()==ID_side_effect &&
1426 {
1429 cleanup_function_call(call.function(), call.arguments());
1430
1431 cleanup_expr(code.op1(), false);
1432 }
1433 else
1434 Forall_operands(it, code)
1435 cleanup_expr(*it, true);
1436
1437 if(code.op0().type().id()==ID_array)
1438 cleanup_expr(to_array_type(code.op0().type()).size(), true);
1439 else if(code.op0().type().id() == ID_c_bit_field)
1440 {
1443 to_bitvector_type(original_type.underlying_type());
1444 code.op0().type() = bv_type;
1445 if(code.operands().size() == 2)
1446 {
1447 exprt bit_mask =
1448 from_integer(power(2, original_type.get_width()) - 1, bv_type);
1449 code.op1() = bitand_exprt{code.op1(), bit_mask};
1450 }
1451 }
1452
1453 add_local_types(code.op0().type());
1454
1455 const irep_idt &typedef_str=code.op0().type().get(ID_C_typedef);
1456 if(!typedef_str.empty() &&
1458 code.op0().type().remove(ID_C_typedef);
1459
1460 return;
1461 }
1462 else if(code.get_statement()==ID_function_call)
1463 {
1465
1466 cleanup_function_call(call.function(), call.arguments());
1467
1468 while(call.lhs().is_not_nil() &&
1469 call.lhs().id()==ID_typecast)
1470 call.lhs()=to_typecast_expr(call.lhs()).op();
1471 }
1472
1473 if(code.has_operands())
1474 {
1475 for(auto &op : code.operands())
1476 {
1477 if(op.id() == ID_code)
1478 cleanup_code(to_code(op), code.get_statement());
1479 else
1480 cleanup_expr(op, false);
1481 }
1482 }
1483
1484 const irep_idt &statement=code.get_statement();
1485 if(statement==ID_label)
1486 {
1488 const irep_idt &label=cl.get_label();
1489
1490 DATA_INVARIANT(!label.empty(), "label must be set");
1491
1492 if(labels_in_use.find(label)==labels_in_use.end())
1493 {
1494 codet tmp = cl.code();
1495 code.swap(tmp);
1496 }
1497 }
1498 else if(statement==ID_block)
1500 else if(statement==ID_ifthenelse)
1502 else if(statement==ID_dowhile)
1503 {
1505
1506 // turn an empty do {} while(...); into a while(...);
1507 // to ensure convergence
1508 if(do_while.body().get_statement()==ID_skip)
1509 do_while.set_statement(ID_while);
1510 // do stmt while(false) is just stmt
1511 else if(do_while.cond().is_false() &&
1512 do_while.body().get_statement()!=ID_block)
1513 code=do_while.body();
1514 }
1515}
1516
1518 const exprt &function,
1520{
1521 if(function.id()!=ID_symbol)
1522 return;
1523
1524 const symbol_exprt &fn=to_symbol_expr(function);
1525
1526 // don't edit function calls we might have introduced
1527 const symbolt *s;
1528 if(!ns.lookup(fn.get_identifier(), s))
1529 {
1530 const symbolt &fn_sym=ns.lookup(fn.get_identifier());
1532 const code_typet::parameterst &parameters=code_type.parameters();
1533
1534 if(parameters.size()==arguments.size())
1535 {
1536 code_typet::parameterst::const_iterator it=parameters.begin();
1537 for(auto &argument : arguments)
1538 {
1539 if(
1540 argument.type().id() == ID_union ||
1541 argument.type().id() == ID_union_tag)
1542 {
1543 argument.type() = it->type();
1544 }
1545 ++it;
1546 }
1547 }
1548 }
1549}
1550
1552 codet &code,
1553 const irep_idt parent_stmt)
1554{
1556
1557 exprt::operandst &operands=code.operands();
1558 for(exprt::operandst::size_type i=0;
1559 operands.size()>1 && i<operands.size();
1560 ) // no ++i
1561 {
1562 exprt::operandst::iterator it=operands.begin()+i;
1563 // remove skip
1564 if(to_code(*it).get_statement()==ID_skip &&
1565 it->source_location().get_comment().empty())
1566 operands.erase(it);
1567 // merge nested blocks, unless there are declarations in the inner block
1568 else if(to_code(*it).get_statement()==ID_block)
1569 {
1570 bool has_decl=false;
1571 for(const auto &op : as_const(*it).operands())
1572 {
1573 if(op.id() == ID_code && to_code(op).get_statement() == ID_decl)
1574 {
1575 has_decl=true;
1576 break;
1577 }
1578 }
1579
1580 if(!has_decl)
1581 {
1582 operands.insert(operands.begin()+i+1,
1583 it->operands().begin(), it->operands().end());
1584 operands.erase(operands.begin()+i);
1585 // no ++i
1586 }
1587 else
1588 ++i;
1589 }
1590 else
1591 ++i;
1592 }
1593
1594 if(operands.empty() && parent_stmt!=ID_nil)
1595 code=code_skipt();
1596 else if(operands.size()==1 &&
1598 to_code(code.op0()).get_statement()!=ID_decl)
1599 {
1600 codet tmp = to_code(code.op0());
1601 code.swap(tmp);
1602 }
1603}
1604
1606{
1607 if(type.get_bool(ID_C_constant))
1608 type.remove(ID_C_constant);
1609
1610 if(type.id() == ID_struct_tag || type.id() == ID_union_tag)
1611 {
1612 const irep_idt &identifier = to_tag_type(type).get_identifier();
1613 if(!const_removed.insert(identifier).second)
1614 return;
1615
1616 symbolt &symbol = symbol_table.get_writeable_ref(identifier);
1617 INVARIANT(
1618 symbol.is_type,
1619 "Symbol "+id2string(identifier)+" should be a type");
1620
1621 remove_const(symbol.type);
1622 }
1623 else if(type.id()==ID_array)
1624 remove_const(to_array_type(type).element_type());
1625 else if(type.id()==ID_struct ||
1626 type.id()==ID_union)
1627 {
1630
1631 for(struct_union_typet::componentst::iterator
1632 it=c.begin();
1633 it!=c.end();
1634 ++it)
1635 remove_const(it->type());
1636 }
1637 else if(type.id() == ID_c_bit_field)
1638 {
1639 to_c_bit_field_type(type).underlying_type().remove(ID_C_constant);
1640 }
1641}
1642
1643static bool has_labels(const codet &code)
1644{
1645 if(code.get_statement()==ID_label)
1646 return true;
1647
1648 for(const auto &op : code.operands())
1649 {
1650 if(op.id() == ID_code && has_labels(to_code(op)))
1651 return true;
1652 }
1653
1654 return false;
1655}
1656
1658{
1659 if(expr.is_nil() || to_code(expr).get_statement() != ID_block)
1660 return false;
1661
1662 code_blockt &block=to_code_block(to_code(expr));
1663 if(
1664 !block.has_operands() ||
1665 block.statements().back().get_statement() != ID_label)
1666 {
1667 return false;
1668 }
1669
1670 code_labelt &label = to_code_label(block.statements().back());
1671
1672 if(label.get_label().empty() ||
1673 label.code().get_statement()!=ID_skip)
1674 {
1675 return false;
1676 }
1677
1678 label_dest=label;
1679 code_skipt s;
1680 label.swap(s);
1681
1682 return true;
1683}
1684
1686 codet &code,
1687 const irep_idt parent_stmt)
1688{
1690 const exprt cond=simplify_expr(i_t_e.cond(), ns);
1691
1692 // assert(false) expands to if(true) assert(false), simplify again (and also
1693 // simplify other cases)
1694 if(
1695 cond.is_true() &&
1696 (i_t_e.else_case().is_nil() || !has_labels(i_t_e.else_case())))
1697 {
1698 codet tmp = i_t_e.then_case();
1699 code.swap(tmp);
1700 }
1701 else if(cond.is_false() && !has_labels(i_t_e.then_case()))
1702 {
1703 if(i_t_e.else_case().is_nil())
1704 code=code_skipt();
1705 else
1706 {
1707 codet tmp = i_t_e.else_case();
1708 code.swap(tmp);
1709 }
1710 }
1711 else
1712 {
1713 if(
1714 i_t_e.then_case().is_not_nil() &&
1715 i_t_e.then_case().get_statement() == ID_ifthenelse)
1716 {
1717 // we re-introduce 1-code blocks with if-then-else to avoid dangling-else
1718 // ambiguity
1719 i_t_e.then_case() = code_blockt({i_t_e.then_case()});
1720 }
1721
1722 if(
1723 i_t_e.else_case().is_not_nil() &&
1724 i_t_e.then_case().get_statement() == ID_skip &&
1725 i_t_e.else_case().get_statement() == ID_ifthenelse)
1726 {
1727 // we re-introduce 1-code blocks with if-then-else to avoid dangling-else
1728 // ambiguity
1729 i_t_e.else_case() = code_blockt({i_t_e.else_case()});
1730 }
1731 }
1732
1733 // move labels at end of then or else case out
1734 if(code.get_statement()==ID_ifthenelse)
1735 {
1737
1738 bool moved=false;
1739 if(i_t_e.then_case().is_not_nil())
1741 if(i_t_e.else_case().is_not_nil())
1743
1744 if(moved)
1745 {
1748 }
1749 }
1750
1751 // remove empty then/else
1752 if(
1753 code.get_statement() == ID_ifthenelse &&
1754 i_t_e.then_case().get_statement() == ID_skip)
1755 {
1756 not_exprt tmp(i_t_e.cond());
1757 simplify(tmp, ns);
1758 // simplification might have removed essential type casts
1759 cleanup_expr(tmp, false);
1760 i_t_e.cond().swap(tmp);
1761 i_t_e.then_case().swap(i_t_e.else_case());
1762 }
1763 if(
1764 code.get_statement() == ID_ifthenelse && i_t_e.else_case().is_not_nil() &&
1765 i_t_e.else_case().get_statement() == ID_skip)
1766 i_t_e.else_case().make_nil();
1767 // or even remove the if altogether if the then case is now empty
1768 if(
1769 code.get_statement() == ID_ifthenelse && i_t_e.else_case().is_nil() &&
1770 (i_t_e.then_case().is_nil() ||
1771 i_t_e.then_case().get_statement() == ID_skip))
1772 code=code_skipt();
1773}
1774
1776{
1777 // we might have to do array -> pointer conversions
1778 if(no_typecast &&
1779 (expr.id()==ID_address_of || expr.id()==ID_member))
1780 {
1781 Forall_operands(it, expr)
1782 cleanup_expr(*it, false);
1783 }
1784 else if(!no_typecast &&
1785 (expr.id()==ID_union || expr.id()==ID_struct ||
1786 expr.id()==ID_array || expr.id()==ID_vector))
1787 {
1788 Forall_operands(it, expr)
1789 cleanup_expr(*it, true);
1790 }
1791 else
1792 {
1793 Forall_operands(it, expr)
1795 }
1796
1797 // work around transparent union argument
1798 if(
1799 expr.id() == ID_union && expr.type().id() != ID_union &&
1800 expr.type().id() != ID_union_tag)
1801 {
1802 expr=to_union_expr(expr).op();
1803 }
1804
1805 // try to get rid of type casts, revealing (char)97 -> 'a'
1806 if(expr.id()==ID_typecast &&
1807 to_typecast_expr(expr).op().is_constant())
1808 simplify(expr, ns);
1809
1810 if(expr.id()==ID_union ||
1811 expr.id()==ID_struct)
1812 {
1813 if(no_typecast)
1814 return;
1815
1817 expr.type().id() == ID_struct_tag || expr.type().id() == ID_union_tag,
1818 "union/struct expressions should have a tag type");
1819
1820 const typet &t=expr.type();
1821
1822 add_local_types(t);
1823 expr=typecast_exprt(expr, t);
1824
1825 const irep_idt &typedef_str=expr.type().get(ID_C_typedef);
1826 if(!typedef_str.empty() &&
1828 expr.type().remove(ID_C_typedef);
1829 }
1830 else if(expr.id()==ID_array ||
1831 expr.id()==ID_vector)
1832 {
1833 if(no_typecast ||
1835 return;
1836
1837 const typet &t=expr.type();
1838
1839 expr = typecast_exprt(expr, t);
1840 add_local_types(t);
1841
1842 const irep_idt &typedef_str=expr.type().get(ID_C_typedef);
1843 if(!typedef_str.empty() &&
1845 expr.type().remove(ID_C_typedef);
1846 }
1847 else if(expr.id()==ID_side_effect)
1848 {
1849 const irep_idt &statement=to_side_effect_expr(expr).get_statement();
1850
1851 if(statement==ID_nondet)
1852 {
1853 // Replace by a function call to nondet_...
1854 // We first search for a suitable one in the symbol table.
1855
1856 irep_idt id;
1857
1858 for(symbol_tablet::symbolst::const_iterator
1859 it=symbol_table.symbols.begin();
1860 it!=symbol_table.symbols.end();
1861 it++)
1862 {
1863 if(it->second.type.id()!=ID_code)
1864 continue;
1865 if(!it->second.base_name.starts_with("nondet_"))
1866 continue;
1867 const code_typet &code_type=to_code_type(it->second.type);
1868 if(code_type.return_type() != expr.type())
1869 continue;
1870 if(!code_type.parameters().empty())
1871 continue;
1872 id=it->second.name;
1873 break;
1874 }
1875
1876 // none found? make one
1877
1878 if(id.empty())
1879 {
1880 irep_idt base_name;
1881
1882 if(!expr.type().get(ID_C_c_type).empty())
1883 {
1884 irep_idt suffix;
1885 suffix=expr.type().get(ID_C_c_type);
1886
1887 if(symbol_table.symbols.find("nondet_"+id2string(suffix))==
1888 symbol_table.symbols.end())
1889 base_name="nondet_"+id2string(suffix);
1890 }
1891
1892 if(base_name.empty())
1893 {
1894 unsigned count=0;
1895 while(symbol_table.symbols.find("nondet_"+std::to_string(count))!=
1896 symbol_table.symbols.end())
1897 ++count;
1898 base_name="nondet_"+std::to_string(count);
1899 }
1900
1901 symbolt symbol{base_name, code_typet({}, expr.type()), ID_C};
1902 symbol.base_name=base_name;
1903 id=symbol.name;
1904
1905 symbol_table.insert(std::move(symbol));
1906 }
1907
1908 const symbolt &symbol=ns.lookup(id);
1909
1910 symbol_exprt symbol_expr(symbol.name, symbol.type);
1911 symbol_expr.add_source_location()=expr.source_location();
1912
1914 symbol_expr, {}, expr.type(), expr.source_location());
1915
1916 expr.swap(call);
1917 }
1918 }
1919 else if(expr.id()==ID_isnan ||
1920 expr.id()==ID_sign)
1921 system_headers.insert("math.h");
1922 else if(expr.is_constant())
1923 {
1924 if(expr.type().id()==ID_floatbv)
1925 {
1926 const ieee_float_valuet f(to_constant_expr(expr));
1927 if(f.is_NaN() || f.is_infinity())
1928 system_headers.insert("math.h");
1929 }
1930 else if(expr.type().id()==ID_pointer)
1931 add_local_types(expr.type());
1932
1934
1935 if(c_sizeof_type.is_not_nil())
1936 add_local_types(static_cast<const typet &>(c_sizeof_type));
1937 }
1938 else if(expr.id()==ID_typecast)
1939 {
1940 if(expr.type().id() == ID_c_bit_field)
1941 expr=to_typecast_expr(expr).op();
1942 else
1943 {
1944 add_local_types(expr.type());
1945
1946 const irep_idt &typedef_str=expr.type().get(ID_C_typedef);
1947 if(!typedef_str.empty() &&
1949 expr.type().remove(ID_C_typedef);
1950
1953 "typedef must not be that of a struct or union type");
1954 }
1955 }
1956 else if(expr.id()==ID_symbol)
1957 {
1958 if(expr.type().id()!=ID_code)
1959 {
1960 const irep_idt &identifier=to_symbol_expr(expr).get_identifier();
1961 const symbolt &symbol=ns.lookup(identifier);
1962
1963 if(symbol.is_static_lifetime &&
1964 symbol.type.id()!=ID_code &&
1965 !symbol.is_extern &&
1966 !symbol.location.get_function().empty() &&
1967 local_static_set.insert(identifier).second)
1968 {
1969 if(symbol.value.is_not_nil())
1970 {
1971 exprt value=symbol.value;
1972 cleanup_expr(value, true);
1973 }
1974
1975 local_static.push_back(identifier);
1976 }
1977 }
1978 }
1979}
1980
1983 codet &dst)
1984{
1985 if(src->code().source_location().is_not_nil())
1986 dst.add_source_location() = src->code().source_location();
1987 else if(src->source_location().is_not_nil())
1988 dst.add_source_location() = src->source_location();
1989}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition as_const.h:14
API to expression classes for bitvectors.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition c_types.h:80
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition c_types.h:377
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Arrays with given size.
Definition std_types.h:807
typet index_type() const
The type of the index expressions into any instance of this type.
Definition std_types.cpp:34
const typet & element_type() const
The type of the elements of the array.
Definition std_types.h:827
Bit-wise AND.
Base class of fixed-width bit-vector types.
Definition std_types.h:909
Type for C bit fields These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (...
Definition c_types.h:20
const cfgt::nodet & get_node(const T &program_point) const
Get the graph node (which gives dominators, predecessors and successors) for program_point.
bool dominates(T lhs, const nodet &rhs_node) const
Returns true if the program point corresponding to rhs_node is dominated by program point lhs.
bool program_point_reachable(const nodet &program_point_node) const
Returns true if the program point for program_point_node is reachable from the entry point.
A non-fatal assertion, which checks a condition then permits execution to continue.
Definition std_code.h:270
A goto_instruction_codet representing an assignment in the program.
An assumption, which must hold in subsequent code.
Definition std_code.h:217
A codet representing sequential composition of program statements.
Definition std_code.h:130
code_operandst & statements()
Definition std_code.h:138
void add(const codet &code)
Definition std_code.h:168
codet representation of a break statement (within a for or while loop).
Definition std_code.h:1182
codet representation of a continue statement (within a for or while loop).
Definition std_code.h:1218
codet representation of a do while statement.
Definition std_code.h:672
const codet & body() const
Definition std_code.h:689
const exprt & cond() const
Definition std_code.h:679
codet representation of an expression statement.
Definition std_code.h:1394
codet representation of a for statement.
Definition std_code.h:734
A codet representing the declaration of a local variable.
Definition std_code.h:347
symbol_exprt & symbol()
Definition std_code.h:354
void set_initial_value(std::optional< exprt > initial_value)
Sets the value to which this declaration initializes the declared variable.
Definition std_code.h:384
goto_instruction_codet representation of a function call statement.
codet representation of a goto statement.
Definition std_code.h:841
codet representation of an if-then-else statement.
Definition std_code.h:460
const exprt & cond() const
Definition std_code.h:478
const codet & else_case() const
Definition std_code.h:498
const codet & then_case() const
Definition std_code.h:488
codet representation of a label for branch targets.
Definition std_code.h:959
const irep_idt & get_label() const
Definition std_code.h:967
codet & code()
Definition std_code.h:977
goto_instruction_codet representation of a "return from a function" statement.
const exprt & return_value() const
A codet representing a skip statement.
Definition std_code.h:322
codet representation of a switch-case, i.e. a case statement within a switch.
Definition std_code.h:1023
codet representing a switch statement.
Definition std_code.h:548
const codet & body() const
Definition std_code.h:565
const exprt & value() const
Definition std_code.h:555
Base type of functions.
Definition std_types.h:583
std::vector< parametert > parameterst
Definition std_types.h:586
codet representing a while statement.
Definition std_code.h:610
Data structure for representing an arbitrary statement in a program.
exprt & op0()
Definition expr.h:133
exprt & op1()
Definition expr.h:136
const irep_idt & get_statement() const
Operator to dereference a pointer.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
bool empty() const
Definition dstring.h:89
The empty type.
Definition std_types.h:51
Base class for all expressions.
Definition expr.h:56
std::vector< exprt > operandst
Definition expr.h:58
bool has_operands() const
Return true if there is at least one operand.
Definition expr.h:91
bool is_true() const
Return whether the expression is a constant representing true.
Definition expr.cpp:27
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition expr.h:163
bool is_false() const
Return whether the expression is a constant representing false.
Definition expr.cpp:34
void reserve_operands(operandst::size_type n)
Definition expr.h:158
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:212
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
const source_locationt & source_location() const
Definition expr.h:231
source_locationt & add_source_location()
Definition expr.h:236
The Boolean constant false.
Definition std_expr.h:3199
goto_programt::const_targett convert_goto_switch(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
goto_programt::const_targett convert_assign_varargs(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
std::unordered_set< irep_idt > local_static_set
std::unordered_set< irep_idt > type_names_set
goto_programt::const_targett convert_goto_break_continue(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
void cleanup_code_ifthenelse(codet &code, const irep_idt parent_stmt)
loop_last_stackt loop_last_stack
void convert_labels(goto_programt::const_targett target, code_blockt &dest)
goto_programt::const_targett convert_decl(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
symbol_tablet & symbol_table
goto_programt::const_targett convert_do_while(goto_programt::const_targett target, goto_programt::const_targett loop_end, code_blockt &dest)
goto_programt::const_targett convert_goto_goto(goto_programt::const_targett target, code_blockt &dest)
const goto_programt & goto_program
goto_programt::const_targett convert_start_thread(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
goto_programt::const_targett get_cases(goto_programt::const_targett target, goto_programt::const_targett upper_bound, const exprt &switch_var, cases_listt &cases, goto_programt::const_targett &first_target, goto_programt::const_targett &default_target)
void cleanup_code_block(codet &code, const irep_idt parent_stmt)
std::list< caset > cases_listt
void copy_source_location(goto_programt::const_targett, codet &dst)
bool remove_default(const cfg_dominatorst &dominators, const cases_listt &cases, goto_programt::const_targett default_target)
goto_programt::const_targett convert_throw(goto_programt::const_targett target, code_blockt &dest)
std::unordered_set< irep_idt > const_removed
goto_programt::const_targett convert_catch(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
void remove_const(typet &type)
std::unordered_set< exprt, irep_hash > va_list_expr
goto_programt::const_targett convert_goto(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
void add_local_types(const typet &type)
void cleanup_expr(exprt &expr, bool no_typecast)
void cleanup_code(codet &code, const irep_idt parent_stmt)
void cleanup_function_call(const exprt &function, code_function_callt::argumentst &arguments)
goto_programt::const_targett convert_assign(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
goto_programt::const_targett convert_instruction(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
void convert_assign_rec(const code_assignt &assign, code_blockt &dest)
std::unordered_set< irep_idt > labels_in_use
goto_programt::const_targett convert_goto_while(goto_programt::const_targett target, goto_programt::const_targett loop_end, code_blockt &dest)
goto_programt::const_targett convert_goto_if(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
std::set< std::string > & system_headers
const namespacet ns
code_blockt & toplevel_block
const std::unordered_set< irep_idt > & typedef_names
goto_programt::const_targett convert_set_return_value(goto_programt::const_targett target, goto_programt::const_targett upper_bound, code_blockt &dest)
bool set_block_end_points(goto_programt::const_targett upper_bound, const cfg_dominatorst &dominators, cases_listt &cases, std::set< unsigned > &processed_locations)
This class represents an instruction in the GOTO intermediate representation.
exprt & condition_nonconst()
Get the condition of gotos, assume, assert.
A generic container class for the GOTO intermediate representation of one function.
instructionst::const_iterator const_targett
An IEEE 754 floating-point value, including specificiation.
Definition ieee_float.h:117
bool is_NaN() const
Definition ieee_float.h:259
bool is_infinity() const
Definition ieee_float.h:260
Array index operator.
Definition std_expr.h:1470
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
void remove(const irep_idt &name)
Definition irep.cpp:87
bool is_not_nil() const
Definition irep.h:372
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
bool is_nil() const
Definition irep.h:368
loop_mapt loop_map
const cfg_dominators_templatet< P, T, false > & get_dominator_info() const
The NIL expression.
Definition std_expr.h:3208
Boolean negation.
Definition std_expr.h:2454
The null pointer constant.
A side_effect_exprt representation of a function call side effect.
Definition std_code.h:1692
const irep_idt & get_statement() const
Definition std_code.h:1472
const irep_idt & get_function() const
Base type for structs and unions.
Definition std_types.h:62
std::vector< componentt > componentst
Definition std_types.h:140
Expression to hold a symbol (variable)
Definition std_expr.h:131
const irep_idt & get_identifier() const
Definition std_expr.h:160
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
const symbolst & symbols
Read-only field, used to look up symbols given their names.
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Symbol table entry.
Definition symbol.h:28
bool is_extern
Definition symbol.h:74
bool is_static_lifetime
Definition symbol.h:70
bool is_type
Definition symbol.h:61
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
typet type
Type of symbol.
Definition symbol.h:31
irep_idt name
The unique identifier.
Definition symbol.h:40
exprt value
Initial value of symbol.
Definition symbol.h:34
The Boolean constant true.
Definition std_expr.h:3190
Semantic type conversion.
Definition std_expr.h:2073
The type of an expression, extends irept.
Definition type.h:29
#define CPROVER_PREFIX
#define Forall_operands(it, expr)
Definition expr.h:27
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
bool is_null_pointer(const constant_exprt &expr)
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Deprecated expression utility functions.
const code_function_callt & to_code_function_call(const goto_instruction_codet &code)
static bool has_labels(const codet &code)
static bool move_label_ifthenelse(exprt &expr, exprt &label_dest)
Dump Goto-Program as C/C++ Source.
#define forall_goto_program_instructions(it, program)
@ FUNCTION_CALL
@ ATOMIC_END
@ DEAD
@ LOCATION
@ END_FUNCTION
@ ASSIGN
@ ASSERT
@ SET_RETURN_VALUE
@ ATOMIC_BEGIN
@ CATCH
@ END_THREAD
@ SKIP
@ NO_INSTRUCTION_TYPE
@ START_THREAD
@ THROW
@ DECL
@ OTHER
@ GOTO
@ INCOMPLETE_GOTO
@ ASSUME
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
static int8_t r
Definition irep_hash.h:60
bool is_true(const literalt &l)
Definition literal.h:198
API to expression classes for Pointers.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
bool simplify(exprt &expr, const namespacet &ns)
exprt simplify_expr(exprt src, const namespacet &ns)
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
side_effect_exprt & to_side_effect_expr(exprt &expr)
Definition std_code.h:1506
const code_switch_caset & to_code_switch_case(const codet &code)
Definition std_code.h:1077
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
Definition std_code.h:1739
const code_dowhilet & to_code_dowhile(const codet &code)
Definition std_code.h:716
const code_labelt & to_code_label(const codet &code)
Definition std_code.h:1004
const code_blockt & to_code_block(const codet &code)
Definition std_code.h:203
const code_ifthenelset & to_code_ifthenelse(const codet &code)
Definition std_code.h:530
const codet & to_code(const exprt &expr)
const or_exprt & to_or_expr(const exprt &expr)
Cast an exprt to a or_exprt.
Definition std_expr.h:2317
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:426
const union_exprt & to_union_expr(const exprt &expr)
Cast an exprt to a union_exprt.
Definition std_expr.h:1816
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.
Definition std_expr.h:1407
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition std_types.h:29
const struct_or_union_tag_typet & to_struct_or_union_tag_type(const typet &type)
Cast a typet to a struct_or_union_tag_typet.
Definition std_types.h:478
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
const tag_typet & to_tag_type(const typet &type)
Cast a typet to a tag_typet.
Definition std_types.h:434
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:208