CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
goto_convert.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Program Transformation
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include "goto_convert.h"
13#include "goto_convert_class.h"
14
15#include <util/arith_tools.h>
16#include <util/c_types.h>
17#include <util/cprover_prefix.h>
19#include <util/expr_util.h>
20#include <util/fresh_symbol.h>
21#include <util/pointer_expr.h>
22#include <util/simplify_expr.h>
23#include <util/std_expr.h>
26
28
29#include "destructor.h"
30
31static bool is_empty(const goto_programt &goto_program)
32{
33 forall_goto_program_instructions(it, goto_program)
34 if(!is_skip(goto_program, it))
35 return false;
36
37 return true;
38}
39
43{
44 std::map<irep_idt, goto_programt::targett> label_targets;
45
46 // in the first pass collect the labels and the corresponding targets
48 {
49 if(!it->labels.empty())
50 {
51 for(auto label : it->labels)
52 // record the label and the corresponding target
53 label_targets.insert(std::make_pair(label, it));
54 }
55 }
56
57 // in the second pass set the targets
58 for(auto &instruction : dest.instructions)
59 {
60 if(
61 instruction.is_catch() &&
62 instruction.code().get_statement() == ID_push_catch)
63 {
64 // Populate `targets` with a GOTO instruction target per
65 // exception handler if it isn't already populated.
66 // (Java handlers, for example, need this finish step; C++
67 // handlers will already be populated by now)
68
69 if(instruction.targets.empty())
70 {
71 bool handler_added = true;
73 to_code_push_catch(instruction.code()).exception_list();
74
75 for(const auto &handler : handler_list)
76 {
77 // some handlers may not have been converted (if there was no
78 // exception to be caught); in such a situation we abort
79 if(label_targets.find(handler.get_label()) == label_targets.end())
80 {
81 handler_added = false;
82 break;
83 }
84 }
85
86 if(!handler_added)
87 continue;
88
89 for(const auto &handler : handler_list)
90 instruction.targets.push_back(label_targets.at(handler.get_label()));
91 }
92 }
93 }
94}
95
105
108 goto_programt &program,
109 std::unordered_map<irep_idt, symbolt, irep_id_hash> &label_flags,
110 const build_declaration_hops_inputst &inputs)
111{
112 // In the case of a goto jumping into a scope, the declarations (but not the
113 // initialisations) need to be executed. This function prepares a
114 // transformation from code that looks like -
115 // {
116 // statement_block_a();
117 // if(...)
118 // goto user_label;
119 // statement_block_b();
120 // int x;
121 // x = 0;
122 // statement_block_c();
123 // int y;
124 // y = 0;
125 // statement_block_d();
126 // user_label:
127 // statement_block_e();
128 // }
129 // to code which looks like -
130 // {
131 // __CPROVER_bool __CPROVER_going_to::user_label;
132 // __CPROVER_going_to::user_label = false;
133 // statement_block_a();
134 // if(...)
135 // {
136 // __CPROVER_going_to::user_label = true;
137 // goto scope_x_label;
138 // }
139 // statement_block_b();
140 // scope_x_label:
141 // int x;
142 // if __CPROVER_going_to::user_label goto scope_y_label:
143 // x = 0;
144 // statement_block_c();
145 // scope_y_label:
146 // int y;
147 // if __CPROVER_going_to::user_label goto user_label:
148 // y = 0;
149 // statement_block_d();
150 // user_label:
151 // __CPROVER_going_to::user_label = false;
152 // statement_block_e();
153 // }
154 //
155 // The actual insertion of instructions needs to be performed by the caller,
156 // which needs to use the result of this method.
157
159
161
162 const auto flag = [&]() -> symbolt {
163 const auto existing_flag = label_flags.find(inputs.label);
164 if(existing_flag != label_flags.end())
165 return existing_flag->second;
167 inputs.label_instruction->source_location();
168 label_location.set_hide();
170 bool_typet{},
171 CPROVER_PREFIX "going_to",
172 id2string(inputs.label),
174 inputs.mode,
176 label_flags.emplace(inputs.label, new_flag);
177
178 // Create and initialise flag.
179 instructions_to_add.emplace_back(
180 program.instructions.begin(),
182 const auto make_clear_flag = [&]() -> goto_programt::instructiont {
184 new_flag.symbol_expr(), false_exprt{}, label_location);
185 };
186 instructions_to_add.emplace_back(
187 program.instructions.begin(), make_clear_flag());
188
189 // Clear flag on arrival at label.
191 instructions_to_add.emplace_back(
193 return new_flag;
194 }();
195
196 auto goto_instruction = inputs.goto_instruction;
197 {
198 // Set flag before the goto.
199 auto goto_location = goto_instruction->source_location();
200 goto_location.set_hide();
201 auto set_flag = goto_programt::make_assignment(
202 flag.symbol_expr(), true_exprt{}, goto_location);
203 instructions_to_add.emplace_back(goto_instruction, set_flag);
204 }
205
206 auto target = inputs.label_instruction;
207 targets.scope_stack.set_current_node(inputs.label_scope_index);
208 while(targets.scope_stack.get_current_node() > inputs.end_scope_index)
209 {
210 node_indext current_node = targets.scope_stack.get_current_node();
211 auto &declaration = targets.scope_stack.get_declaration(current_node);
212 targets.scope_stack.descend_tree();
213 if(!declaration)
214 continue;
215
216 bool add_if = declaration->accounted_flags.find(flag.name) ==
217 declaration->accounted_flags.end();
218 if(add_if)
219 {
220 auto declaration_location = declaration->instruction->source_location();
221 declaration_location.set_hide();
223 target, flag.symbol_expr(), declaration_location);
224 // this isn't changing any previously existing instruction so we insert
225 // directly rather than going through instructions_to_add
226 program.instructions.insert(
227 std::next(declaration->instruction), std::move(if_goto));
228 declaration->accounted_flags.insert(flag.name);
229 }
230 target = declaration->instruction;
231 }
232
233 // Update the goto so that it goes to the first declaration rather than its
234 // original/final destination.
235 goto_instruction->set_target(target);
236
237 return instructions_to_add;
238}
239
240/******************************************************************* \
241
242Function: goto_convertt::finish_gotos
243
244 Inputs:
245
246 Outputs:
247
248 Purpose:
249
250\*******************************************************************/
251
253{
254 std::unordered_map<irep_idt, symbolt, irep_id_hash> label_flags;
256
257 for(const auto &g_it : targets.gotos)
258 {
259 goto_programt::instructiont &i = *(g_it.first);
260
261 if(i.is_start_thread())
262 {
263 const irep_idt &goto_label = i.code().get(ID_destination);
264 const auto l_it = targets.labels.find(goto_label);
265
266 if(l_it == targets.labels.end())
267 {
269 "goto label \'" + id2string(goto_label) + "\' not found",
270 i.code().find_source_location());
271 }
272
273 i.targets.push_back(l_it->second.first);
274 }
275 else if(i.is_incomplete_goto())
276 {
277 const irep_idt &goto_label = i.code().get(ID_destination);
278 const auto l_it = targets.labels.find(goto_label);
279
280 if(l_it == targets.labels.end())
281 {
283 "goto label \'" + id2string(goto_label) + "\' not found",
284 i.code().find_source_location());
285 }
286
287 i.complete_goto(l_it->second.first);
288
289 node_indext label_target = l_it->second.second;
291
292 // Compare the currently-live variables on the path of the GOTO and label.
293 // We want to work out what variables should die during the jump.
295 targets.scope_stack.get_nearest_common_ancestor_info(
297
298 // If our goto had no variables of note, just skip (0 is the index of the
299 // root of the scope tree)
300 if(goto_target != 0)
301 {
302 // If the goto recorded a destructor stack, execute as much as is
303 // appropriate for however many automatic variables leave scope.
305 debug() << "adding goto-destructor code on jump to '" << goto_label
306 << "'" << eom;
307
311 i.source_location(),
313 mode,
317
318 // This should leave iterators intact, as long as
319 // goto_programt::instructionst is std::list.
320 }
321
322 // Variables *entering* scope on goto, is illegal for C++ non-pod types
323 // and impossible in Java. However, with the exception of Variable Length
324 // Arrays (VLAs), this is valid C and should be taken into account.
325 const bool variables_added_to_scope =
326 intersection_result.right_depth_below_common_ancestor > 0;
328 {
329 // If the goto recorded a destructor stack, execute as much as is
330 // appropriate for however many automatic variables leave scope.
332 debug() << "encountered goto '" << goto_label
333 << "' that enters one or more lexical blocks; "
334 << "adding declaration code on jump to '" << goto_label << "'"
335 << eom;
336
338 inputs.mode = mode;
339 inputs.label = l_it->first;
340 inputs.goto_instruction = g_it.first;
341 inputs.label_instruction = l_it->second.first;
343 inputs.end_scope_index = intersection_result.common_ancestor;
346 build_declaration_hops(dest, label_flags, inputs));
347 }
348 }
349 else
350 {
352 }
353 }
354
355 for(auto r_it = instructions_to_insert.rbegin();
357 ++r_it)
358 {
359 dest.insert_before_swap(r_it->first, r_it->second);
360 }
361
362 targets.gotos.clear();
363}
364
366{
367 for(auto &g_it : targets.computed_gotos)
368 {
371 const exprt pointer = destination.pointer();
372
373 // remember the expression for later checks
374 i =
376
377 // insert huge case-split
378 for(const auto &label : targets.labels)
379 {
381 label_expr.set(ID_identifier, label.first);
382
384
385 goto_program.insert_after(
386 g_it,
388 label.second.first, guard, i.source_location()));
389 }
390 }
391
392 targets.computed_gotos.clear();
393}
394
399{
400 // We cannot use a set of targets, as target iterators
401 // cannot be compared at this stage.
402
403 // collect targets: reset marking
404 for(auto &i : dest.instructions)
406
407 // mark the goto targets
408 unsigned cnt = 0;
409 for(auto &i : dest.instructions)
410 if(i.is_goto())
411 i.get_target()->target_number = (++cnt);
412
413 for(auto it = dest.instructions.begin(); it != dest.instructions.end(); it++)
414 {
415 if(!it->is_goto())
416 continue;
417
418 auto it_goto_y = std::next(it);
419
420 if(
421 it_goto_y == dest.instructions.end() || !it_goto_y->is_goto() ||
422 !it_goto_y->condition().is_true() || it_goto_y->is_target())
423 {
424 continue;
425 }
426
427 auto it_z = std::next(it_goto_y);
428
429 if(it_z == dest.instructions.end())
430 continue;
431
432 // cannot compare iterators, so compare target number instead
433 if(it->get_target()->target_number == it_z->target_number)
434 {
436 it->condition().find(ID_C_spec_assigns).is_nil() &&
437 it->condition().find(ID_C_spec_loop_invariant).is_nil() &&
438 it->condition().find(ID_C_spec_decreases).is_nil(),
439 "no loop invariant expected");
440 irept y_assigns = it_goto_y->condition().find(ID_C_spec_assigns);
442 it_goto_y->condition().find(ID_C_spec_loop_invariant);
443 irept y_decreases = it_goto_y->condition().find(ID_C_spec_decreases);
444
445 it->set_target(it_goto_y->get_target());
446 exprt updated_condition = boolean_negate(it->condition());
447 if(y_assigns.is_not_nil())
449 if(y_loop_invariant.is_not_nil())
451 if(y_decreases.is_not_nil())
453 it->condition_nonconst() = updated_condition;
454 it_goto_y->turn_into_skip();
455 }
456 }
457}
458
460 const codet &code,
461 goto_programt &dest,
462 const irep_idt &mode)
463{
464 goto_convert_rec(code, dest, mode);
465}
466
468 const codet &code,
469 goto_programt &dest,
470 const irep_idt &mode)
471{
472 convert(code, dest, mode);
473
474 finish_gotos(dest, mode);
478}
479
481 const codet &code,
483 goto_programt &dest)
484{
486 code, code.source_location(), type, nil_exprt(), {}));
487}
488
490 const code_labelt &code,
491 goto_programt &dest,
492 const irep_idt &mode)
493{
494 // grab the label
495 const irep_idt &label = code.get_label();
496
498
499 // magic thread creation label.
500 // The "__CPROVER_ASYNC_" signals the start of a sequence of instructions
501 // that can be executed in parallel, i.e, a new thread.
502 if(label.starts_with(CPROVER_PREFIX "ASYNC_"))
503 {
504 // the body of the thread is expected to be
505 // in the operand.
507 to_code_label(code).code().is_not_nil(),
508 "code() in magic thread creation label is null");
509
510 // replace the magic thread creation label with a
511 // thread block (START_THREAD...END_THREAD).
513 thread_body.add(to_code_label(code).code());
514 thread_body.add_source_location() = code.source_location();
516 }
517 else
518 {
519 convert(to_code_label(code).code(), tmp, mode);
520
521 goto_programt::targett target = tmp.instructions.begin();
523
524 targets.labels.insert(
525 {label, {target, targets.scope_stack.get_current_node()}});
526 target->labels.push_front(label);
527 }
528}
529
531{
532 // ignore for now
533}
534
536 const code_switch_caset &code,
537 goto_programt &dest,
538 const irep_idt &mode)
539{
541 convert(code.code(), tmp, mode);
542
543 goto_programt::targett target = tmp.instructions.begin();
545
546 // is a default target given?
547
548 if(code.is_default())
549 targets.set_default(target);
550 else
551 {
552 // cases?
553
554 cases_mapt::iterator cases_entry = targets.cases_map.find(target);
555 if(cases_entry == targets.cases_map.end())
556 {
557 targets.cases.push_back(std::make_pair(target, caset()));
559 targets.cases_map.insert(std::make_pair(target, --targets.cases.end()))
560 .first;
561 }
562
563 exprt::operandst &case_op_dest = cases_entry->second->second;
564 case_op_dest.push_back(code.case_op());
565 // make sure we have a source location in the case operand as otherwise we
566 // end up with a GOTO instruction without a source location
568 case_op_dest.back().source_location().is_not_nil(),
569 "case operand should have a source location",
570 case_op_dest.back().pretty(),
571 code.pretty());
572 }
573}
574
576 const code_gcc_switch_case_ranget &code,
577 goto_programt &dest,
578 const irep_idt &mode)
579{
580 const auto lb = numeric_cast<mp_integer>(code.lower());
581 const auto ub = numeric_cast<mp_integer>(code.upper());
582
584 lb.has_value() && ub.has_value(),
585 "GCC's switch-case-range statement requires constant bounds",
586 code.find_source_location());
587
588 if(*lb > *ub)
589 {
591 warning() << "GCC's switch-case-range statement with empty case range"
592 << eom;
593 }
594
596 convert(code.code(), tmp, mode);
597
598 goto_programt::targett target = tmp.instructions.begin();
600
601 cases_mapt::iterator cases_entry = targets.cases_map.find(target);
602 if(cases_entry == targets.cases_map.end())
603 {
604 targets.cases.push_back({target, caset()});
606 targets.cases_map.insert({target, --targets.cases.end()}).first;
607 }
608
609 // create a skeleton for case_guard
610 cases_entry->second->second.push_back(and_exprt{
613}
614
617 const codet &code,
618 goto_programt &dest,
619 const irep_idt &mode)
620{
621 const irep_idt &statement = code.get_statement();
622
623 if(statement == ID_block)
624 convert_block(to_code_block(code), dest, mode);
625 else if(statement == ID_decl)
627 else if(statement == ID_decl_type)
628 convert_decl_type(code, dest);
629 else if(statement == ID_expression)
630 convert_expression(to_code_expression(code), dest, mode);
631 else if(statement == ID_assign)
632 convert_assign(to_code_assign(code), dest, mode);
633 else if(statement == ID_assert)
634 convert_assert(to_code_assert(code), dest, mode);
635 else if(statement == ID_assume)
636 convert_assume(to_code_assume(code), dest, mode);
637 else if(statement == ID_function_call)
639 else if(statement == ID_label)
640 convert_label(to_code_label(code), dest, mode);
641 else if(statement == ID_gcc_local_label)
642 convert_gcc_local_label(code, dest);
643 else if(statement == ID_switch_case)
644 convert_switch_case(to_code_switch_case(code), dest, mode);
645 else if(statement == ID_gcc_switch_case_range)
647 to_code_gcc_switch_case_range(code), dest, mode);
648 else if(statement == ID_for)
649 convert_for(to_code_for(code), dest, mode);
650 else if(statement == ID_while)
651 convert_while(to_code_while(code), dest, mode);
652 else if(statement == ID_dowhile)
653 convert_dowhile(to_code_dowhile(code), dest, mode);
654 else if(statement == ID_switch)
655 convert_switch(to_code_switch(code), dest, mode);
656 else if(statement == ID_break)
657 convert_break(to_code_break(code), dest, mode);
658 else if(statement == ID_return)
659 convert_return(to_code_frontend_return(code), dest, mode);
660 else if(statement == ID_continue)
661 convert_continue(to_code_continue(code), dest, mode);
662 else if(statement == ID_goto)
663 convert_goto(to_code_goto(code), dest);
664 else if(statement == ID_gcc_computed_goto)
665 convert_gcc_computed_goto(code, dest);
666 else if(statement == ID_skip)
667 convert_skip(code, dest);
668 else if(statement == ID_ifthenelse)
669 convert_ifthenelse(to_code_ifthenelse(code), dest, mode);
670 else if(statement == ID_start_thread)
671 convert_start_thread(code, dest);
672 else if(statement == ID_end_thread)
673 convert_end_thread(code, dest);
674 else if(statement == ID_atomic_begin)
675 convert_atomic_begin(code, dest);
676 else if(statement == ID_atomic_end)
677 convert_atomic_end(code, dest);
678 else if(statement == ID_cpp_delete || statement == "cpp_delete[]")
679 convert_cpp_delete(code, dest);
680 else if(statement == ID_msc_try_except)
681 convert_msc_try_except(code, dest, mode);
682 else if(statement == ID_msc_try_finally)
683 convert_msc_try_finally(code, dest, mode);
684 else if(statement == ID_msc_leave)
685 convert_msc_leave(code, dest, mode);
686 else if(statement == ID_try_catch) // C++ try/catch
687 convert_try_catch(code, dest, mode);
688 else if(statement == ID_CPROVER_try_catch) // CPROVER-homemade
689 convert_CPROVER_try_catch(code, dest, mode);
690 else if(statement == ID_CPROVER_throw) // CPROVER-homemade
691 convert_CPROVER_throw(code, dest, mode);
692 else if(statement == ID_CPROVER_try_finally)
693 convert_CPROVER_try_finally(code, dest, mode);
694 else if(statement == ID_asm)
695 convert_asm(to_code_asm(code), dest);
696 else if(statement == ID_static_assert)
697 {
698 // C23 allows static_assert without message
699 PRECONDITION(code.operands().size() == 1 || code.operands().size() == 2);
700 // We are double-checking the work of the type checker here.
701 exprt assertion =
703 simplify(assertion, ns);
705 !assertion.is_false(),
706 "static assertion is false",
707 code.op0().find_source_location());
708 }
709 else if(statement == ID_dead)
710 copy(code, DEAD, dest);
711 else if(statement == ID_decl_block)
712 {
713 for(const auto &op : code.operands())
714 convert(to_code(op), dest, mode);
715 }
716 else if(
717 statement == ID_push_catch || statement == ID_pop_catch ||
718 statement == ID_exception_landingpad)
719 copy(code, CATCH, dest);
720 else
721 copy(code, OTHER, dest);
722
723 // make sure dest is never empty
724 if(dest.instructions.empty())
725 {
727 }
728}
729
731 const code_blockt &code,
732 goto_programt &dest,
733 const irep_idt &mode)
734{
735 const source_locationt &end_location = code.end_location();
736
737 // this saves the index of the destructor stack
738 node_indext old_stack_top = targets.scope_stack.get_current_node();
739
740 // now convert block
741 for(const auto &b_code : code.statements())
742 convert(b_code, dest, mode);
743
744 // see if we need to do any destructors -- may have been processed
745 // in a prior break/continue/return already, don't create dead code
746 if(
747 !dest.empty() && dest.instructions.back().is_goto() &&
748 dest.instructions.back().condition().is_true())
749 {
750 // don't do destructors when we are unreachable
751 }
752 else
753 unwind_destructor_stack(end_location, dest, mode, old_stack_top);
754
755 // Set the current node of our destructor stack back to before the block.
756 targets.scope_stack.set_current_node(old_stack_top);
757}
758
760 const code_expressiont &code,
761 goto_programt &dest,
762 const irep_idt &mode)
763{
764 exprt expr = code.expression();
765
766 if(expr.id() == ID_if)
767 {
768 // We do a special treatment for c?t:f
769 // by compiling to if(c) t; else f;
770 const if_exprt &if_expr = to_if_expr(expr);
772 if_expr.cond(),
773 code_expressiont(if_expr.true_case()),
774 code_expressiont(if_expr.false_case()));
775 tmp_code.add_source_location() = expr.source_location();
776 tmp_code.then_case().add_source_location() = expr.source_location();
777 tmp_code.else_case().add_source_location() = expr.source_location();
778 convert_ifthenelse(tmp_code, dest, mode);
779 }
780 else
781 {
782 // result _not_ used
783 clean_expr_resultt side_effects = clean_expr(expr, mode, false);
784 dest.destructive_append(side_effects.side_effects);
785
786 // Any residual expression?
787 // We keep it to add checks later.
788 if(expr.is_not_nil())
789 {
790 codet tmp = code;
791 tmp.op0() = expr;
792 tmp.add_source_location() = expr.source_location();
793 copy(tmp, OTHER, dest);
794 }
795
796 destruct_locals(side_effects.temporaries, dest, ns);
797 }
798}
799
801 const code_frontend_declt &code,
802 goto_programt &dest,
803 const irep_idt &mode)
804{
805 const irep_idt &identifier = code.get_identifier();
806
807 const symbolt &symbol = ns.lookup(identifier);
808
809 if(symbol.is_static_lifetime || symbol.type.id() == ID_code)
810 return; // this is a SKIP!
811
813 if(code.operands().size() == 1)
814 {
815 copy(code, DECL, dest);
816 return std::prev(dest.instructions.end());
817 }
818
819 exprt initializer = code.op1();
820
821 codet tmp = code;
822 tmp.operands().resize(1);
823 // hide this declaration-without-initializer step in the goto trace
824 tmp.add_source_location().set_hide();
825
826 // Break up into decl and assignment.
827 // Decl must be visible before initializer.
828 copy(tmp, DECL, dest);
829 const auto declaration_iterator = std::prev(dest.instructions.end());
830
831 auto initializer_location = initializer.find_source_location();
832 clean_expr_resultt side_effects = clean_expr(initializer, mode);
833 dest.destructive_append(side_effects.side_effects);
834
835 if(initializer.is_not_nil())
836 {
837 code_assignt assign(code.op0(), initializer);
839
840 convert_assign(assign, dest, mode);
841 }
842
843 destruct_locals(side_effects.temporaries, dest, ns);
844
846 }();
847
848 // now create a 'dead' instruction -- will be added after the
849 // destructor created below as unwind_destructor_stack pops off the
850 // top of the destructor stack
851 const symbol_exprt symbol_expr(symbol.name, symbol.type);
852
853 {
854 code_deadt code_dead(symbol_expr);
855
856 targets.scope_stack.add(code_dead, {declaration_iterator});
857 }
858
859 // do destructor
860 code_function_callt destructor = get_destructor(ns, symbol.type);
861
862 if(destructor.is_not_nil())
863 {
864 // add "this"
865 address_of_exprt this_expr(symbol_expr, pointer_type(symbol.type));
866 destructor.arguments().push_back(this_expr);
867
868 targets.scope_stack.add(destructor, {});
869 }
870}
871
873{
874 // we remove these
875}
876
878 const code_assignt &code,
879 goto_programt &dest,
880 const irep_idt &mode)
881{
882 exprt lhs = code.lhs(), rhs = code.rhs();
883
884 clean_expr_resultt side_effects = clean_expr(lhs, mode);
885 dest.destructive_append(side_effects.side_effects);
886
887 if(rhs.id() == ID_side_effect && rhs.get(ID_statement) == ID_function_call)
888 {
890
892 rhs.operands().size() == 2,
893 "function_call sideeffect takes two operands",
894 rhs.find_source_location());
895
896 Forall_operands(it, rhs)
897 {
898 side_effects.add(clean_expr(*it, mode));
899 dest.destructive_append(side_effects.side_effects);
900 }
901
903 lhs,
904 rhs_function_call.function(),
905 rhs_function_call.arguments(),
906 dest,
907 mode);
908 }
909 else if(
910 rhs.id() == ID_side_effect && (rhs.get(ID_statement) == ID_cpp_new ||
911 rhs.get(ID_statement) == ID_cpp_new_array))
912 {
913 Forall_operands(it, rhs)
914 {
915 side_effects.add(clean_expr(*it, mode));
916 dest.destructive_append(side_effects.side_effects);
917 }
918
919 // TODO: This should be done in a separate pass
920 do_cpp_new(lhs, to_side_effect_expr(rhs), dest);
921 }
922 else if(
923 rhs.id() == ID_side_effect &&
924 (rhs.get(ID_statement) == ID_assign ||
925 rhs.get(ID_statement) == ID_postincrement ||
926 rhs.get(ID_statement) == ID_preincrement ||
929 {
930 // handle above side effects
931 side_effects.add(clean_expr(rhs, mode));
932 dest.destructive_append(side_effects.side_effects);
933
935 new_assign.lhs() = lhs;
936 new_assign.rhs() = rhs;
937
938 copy(new_assign, ASSIGN, dest);
939 }
940 else if(rhs.id() == ID_side_effect)
941 {
942 // preserve side effects that will be handled at later stages,
943 // such as allocate, new operators of other languages, e.g. java, etc
944 Forall_operands(it, rhs)
945 {
946 side_effects.add(clean_expr(*it, mode));
947 dest.destructive_append(side_effects.side_effects);
948 }
949
951 new_assign.lhs() = lhs;
952 new_assign.rhs() = rhs;
953
954 copy(new_assign, ASSIGN, dest);
955 }
956 else
957 {
958 // do everything else
959 side_effects.add(clean_expr(rhs, mode));
960 dest.destructive_append(side_effects.side_effects);
961
963 new_assign.lhs() = lhs;
964 new_assign.rhs() = rhs;
965
966 copy(new_assign, ASSIGN, dest);
967 }
968
969 destruct_locals(side_effects.temporaries, dest, ns);
970}
971
973{
975 code.operands().size() == 1,
976 "cpp_delete statement takes one operand",
977 code.find_source_location());
978
979 exprt tmp_op = code.op0();
980
982 dest.destructive_append(side_effects.side_effects);
983
984 // we call the destructor, and then free
985 const exprt &destructor =
986 static_cast<const exprt &>(code.find(ID_destructor));
987
989
991 delete_identifier = "__delete_array";
992 else if(code.get_statement() == ID_cpp_delete)
993 delete_identifier = "__delete";
994 else
996
997 if(destructor.is_not_nil())
998 {
1000 {
1001 // build loop
1002 }
1003 else if(code.get_statement() == ID_cpp_delete)
1004 {
1005 // just one object
1007
1008 codet tmp_code = to_code(destructor);
1010 convert(tmp_code, dest, ID_cpp);
1011 }
1012 else
1014 }
1015
1016 // now do "free"
1018
1020 to_code_type(delete_symbol.type()).parameters().size() == 1,
1021 "delete statement takes 1 parameter");
1022
1023 typet arg_type =
1024 to_code_type(delete_symbol.type()).parameters().front().type();
1025
1028 delete_call.add_source_location() = code.source_location();
1029
1030 convert(delete_call, dest, ID_cpp);
1031
1032 destruct_locals(side_effects.temporaries, dest, ns);
1033}
1034
1036 const code_assertt &code,
1037 goto_programt &dest,
1038 const irep_idt &mode)
1039{
1040 exprt cond = code.assertion();
1041
1042 clean_expr_resultt side_effects = clean_expr(cond, mode);
1043 dest.destructive_append(side_effects.side_effects);
1044
1046 annotated_location.set("user-provided", true);
1048
1049 destruct_locals(side_effects.temporaries, dest, ns);
1050}
1051
1053{
1055 code, code.source_location(), SKIP, nil_exprt(), {}));
1056}
1057
1059 const code_assumet &code,
1060 goto_programt &dest,
1061 const irep_idt &mode)
1062{
1063 exprt op = code.assumption();
1064
1065 clean_expr_resultt side_effects = clean_expr(op, mode);
1066 dest.destructive_append(side_effects.side_effects);
1067
1069
1070 destruct_locals(side_effects.temporaries, dest, ns);
1071}
1072
1074 const codet &code,
1076{
1077 auto assigns = static_cast<const unary_exprt &>(code.find(ID_C_spec_assigns));
1078 if(assigns.is_not_nil())
1079 {
1080 PRECONDITION(loop->is_goto() || loop->is_incomplete_goto());
1081 loop->condition_nonconst().add(ID_C_spec_assigns).swap(assigns.op());
1082 }
1083
1084 auto invariant =
1085 static_cast<const exprt &>(code.find(ID_C_spec_loop_invariant));
1086 if(!invariant.is_nil())
1087 {
1088 PRECONDITION(loop->is_goto() || loop->is_incomplete_goto());
1089 loop->condition_nonconst().add(ID_C_spec_loop_invariant).swap(invariant);
1090 }
1091
1092 auto decreases_clause =
1093 static_cast<const exprt &>(code.find(ID_C_spec_decreases));
1094 if(!decreases_clause.is_nil())
1095 {
1096 PRECONDITION(loop->is_goto() || loop->is_incomplete_goto());
1097 loop->condition_nonconst().add(ID_C_spec_decreases).swap(decreases_clause);
1098 }
1099}
1100
1102 const code_fort &code,
1103 goto_programt &dest,
1104 const irep_idt &mode)
1105{
1106 // turn for(A; c; B) { P } into
1107 // A; while(c) { P; B; }
1108 //-----------------------------
1109 // A;
1110 // u: sideeffects in c
1111 // v: if(!c) goto Z;
1112 // cleanup-loop;
1113 // w: P;
1114 // x: B; <-- continue target
1115 // y: goto u;
1116 // Z: cleanup-out;
1117 // z: ; <-- break target
1118
1119 // A;
1120 if(code.init().is_not_nil())
1121 convert(to_code(code.init()), dest, mode);
1122
1123 exprt cond = code.cond();
1124
1125 clean_expr_resultt side_effects = clean_expr(cond, mode);
1126
1127 // save break/continue targets
1129
1130 // do the u label
1131 goto_programt::targett u = side_effects.side_effects.instructions.begin();
1132
1133 // do the v label
1136 destruct_locals(side_effects.temporaries, tmp_v, ns);
1137
1138 // do the z and Z labels
1140 destruct_locals(side_effects.temporaries, tmp_z, ns);
1143 goto_programt::targett Z = tmp_z.instructions.begin();
1144
1145 // do the x label
1147
1148 if(code.iter().is_nil())
1149 {
1151 }
1152 else
1153 {
1154 exprt tmp_B = code.iter();
1155
1157 tmp_x.destructive_append(side_effects_iter.side_effects);
1159
1160 if(tmp_x.instructions.empty())
1162 }
1163
1164 // optimize the v label
1165 if(side_effects.side_effects.instructions.empty())
1166 u = v;
1167
1168 // set the targets
1169 targets.set_break(z);
1170 targets.set_continue(tmp_x.instructions.begin());
1171
1172 // v: if(!c) goto Z;
1173 *v =
1175
1176 // do the w label
1178 convert(code.body(), tmp_w, mode);
1179
1180 // y: goto u;
1184
1185 // assigns clause, loop invariant and decreases clause
1187
1188 dest.destructive_append(side_effects.side_effects);
1194
1195 // restore break/continue
1196 old_targets.restore(targets);
1197}
1198
1200 const code_whilet &code,
1201 goto_programt &dest,
1202 const irep_idt &mode)
1203{
1204 const exprt &cond = code.cond();
1205 const source_locationt &source_location = code.source_location();
1206
1207 // while(c) P;
1208 //--------------------
1209 // v: sideeffects in c
1210 // if(!c) goto z;
1211 // x: P;
1212 // y: goto v; <-- continue target
1213 // z: ; <-- break target
1214
1215 // save break/continue targets
1217
1218 // do the z label
1221 tmp_z.add(goto_programt::make_skip(source_location));
1222
1225 boolean_negate(cond), z, source_location, tmp_branch, mode);
1226
1227 // do the v label
1228 goto_programt::targett v = tmp_branch.instructions.begin();
1229
1230 // y: goto v;
1234
1235 // set the targets
1236 targets.set_break(z);
1237 targets.set_continue(y);
1238
1239 // do the x label
1241 convert(code.body(), tmp_x, mode);
1242
1243 // assigns clause, loop invariant and decreases clause
1245
1250
1251 // restore break/continue
1252 old_targets.restore(targets);
1253}
1254
1256 const code_dowhilet &code,
1257 goto_programt &dest,
1258 const irep_idt &mode)
1259{
1261 code.operands().size() == 2,
1262 "dowhile takes two operands",
1263 code.find_source_location());
1264
1265 // save source location
1266 source_locationt condition_location = code.cond().find_source_location();
1267
1268 exprt cond = code.cond();
1269
1270 clean_expr_resultt side_effects = clean_expr(cond, mode);
1271
1272 // do P while(c);
1273 //--------------------
1274 // w: P;
1275 // x: sideeffects in c <-- continue target
1276 // y: if(!c) goto C;
1277 // cleanup-loop;
1278 // W: goto w;
1279 // C: cleanup-out;
1280 // z: ; <-- break target
1281
1282 // save break/continue targets
1284
1285 // do the y label
1289 destruct_locals(side_effects.temporaries, tmp_y, ns);
1292
1293 // do the z label and C labels
1295 destruct_locals(side_effects.temporaries, tmp_z, ns);
1298 goto_programt::targett C = tmp_z.instructions.begin();
1299
1300 // y: if(!c) goto C;
1301 y->complete_goto(C);
1302
1303 // do the x label
1305 if(side_effects.side_effects.instructions.empty())
1306 x = y;
1307 else
1308 x = side_effects.side_effects.instructions.begin();
1309
1310 // set the targets
1311 targets.set_break(z);
1312 targets.set_continue(x);
1313
1314 // do the w label
1316 convert(code.body(), tmp_w, mode);
1317 goto_programt::targett w = tmp_w.instructions.begin();
1318
1319 // W: goto w;
1320 W->complete_goto(w);
1321
1322 // assigns_clause, loop invariant and decreases clause
1324
1326 dest.destructive_append(side_effects.side_effects);
1329
1330 // restore break/continue targets
1331 old_targets.restore(targets);
1332}
1333
1335 const exprt &value,
1336 const exprt::operandst &case_op)
1337{
1338 PRECONDITION(!case_op.empty());
1339
1341 disjuncts.reserve(case_op.size());
1342
1343 for(const auto &op : case_op)
1344 {
1345 // could be a skeleton generated by convert_gcc_switch_case_range
1346 if(op.id() == ID_and)
1347 {
1349 PRECONDITION(to_binary_expr(and_expr.op0()).op1().is_nil());
1350 PRECONDITION(to_binary_expr(and_expr.op1()).op0().is_nil());
1351 binary_exprt skeleton = and_expr;
1352 to_binary_expr(skeleton.op0()).op1() = value;
1353 to_binary_expr(skeleton.op1()).op0() = value;
1354 disjuncts.push_back(skeleton);
1355 }
1356 else
1357 disjuncts.push_back(equal_exprt(value, op));
1358 }
1359
1360 return disjunction(disjuncts);
1361}
1362
1364 const code_switcht &code,
1365 goto_programt &dest,
1366 const irep_idt &mode)
1367{
1368 // switch(v) {
1369 // case x: Px;
1370 // case y: Py;
1371 // ...
1372 // default: Pd;
1373 // }
1374 // --------------------
1375 // location
1376 // x: if(v==x) goto X;
1377 // y: if(v==y) goto Y;
1378 // goto d;
1379 // X: Px;
1380 // Y: Py;
1381 // d: Pd;
1382 // z: ;
1383
1384 // we first add a 'location' node for the switch statement,
1385 // which would otherwise not be recorded
1387
1388 // get the location of the end of the body, but
1389 // default to location of switch, if none
1391 code.body().get_statement() == ID_block
1392 ? to_code_block(code.body()).end_location()
1393 : code.source_location();
1394
1395 // do the value we switch over
1396 exprt argument = code.value();
1397
1398 clean_expr_resultt side_effects = clean_expr(argument, mode);
1399
1400 // Avoid potential performance penalties caused by evaluating the value
1401 // multiple times (as the below chain-of-ifs does). "needs_cleaning" isn't
1402 // necessarily the right check here, and we may need to introduce a different
1403 // way of identifying the class of non-trivial expressions that warrant
1404 // introduction of a temporary.
1406 {
1407 symbolt &new_symbol = new_tmp_symbol(
1408 argument.type(),
1409 "switch_value",
1410 side_effects.side_effects,
1411 code.source_location(),
1412 mode);
1413
1415 new_symbol.symbol_expr(), argument, code.source_location()};
1416 convert(copy_value, side_effects.side_effects, mode);
1417
1418 argument = new_symbol.symbol_expr();
1419 side_effects.add_temporary(to_symbol_expr(argument).get_identifier());
1420 }
1421
1422 // save break/default/cases targets
1424
1425 // do the z label
1429
1430 // set the new targets -- continue stays as is
1431 targets.set_break(z);
1432 targets.set_default(z);
1433 targets.cases.clear();
1434 targets.cases_map.clear();
1435
1437 convert(code.body(), tmp, mode);
1438
1440
1441 // The case number represents which case this corresponds to in the sequence
1442 // of case statements.
1443 //
1444 // switch (x)
1445 // {
1446 // case 2: // case_number 1
1447 // ...;
1448 // case 3: // case_number 2
1449 // ...;
1450 // case 10: // case_number 3
1451 // ...;
1452 // }
1453 size_t case_number = 1;
1454 for(auto &case_pair : targets.cases)
1455 {
1456 const caset &case_ops = case_pair.second;
1457
1458 if(case_ops.empty())
1459 continue;
1460
1461 exprt guard_expr = case_guard(argument, case_ops);
1462
1463 source_locationt source_location = case_ops.front().find_source_location();
1464 source_location.set_case_number(std::to_string(case_number));
1465 case_number++;
1466
1467 if(side_effects.temporaries.empty())
1468 {
1469 guard_expr.add_source_location() = source_location;
1470
1472 case_pair.first, std::move(guard_expr), source_location));
1473 }
1474 else
1475 {
1476 guard_expr = boolean_negate(guard_expr);
1477 guard_expr.add_source_location() = source_location;
1478
1481 std::move(guard_expr), source_location));
1482 destruct_locals(side_effects.temporaries, tmp_cases, ns);
1484 case_pair.first, true_exprt{}, source_location));
1486 tmp_cases.add(goto_programt::make_skip(source_location));
1487 try_next->complete_goto(next_case);
1488 }
1489 }
1490
1492 targets.default_target, targets.default_target->source_location()));
1493
1494 dest.destructive_append(side_effects.side_effects);
1496 dest.destructive_append(tmp);
1498
1499 // restore old targets
1500 old_targets.restore(targets);
1501}
1502
1504 const code_breakt &code,
1505 goto_programt &dest,
1506 const irep_idt &mode)
1507{
1509 targets.break_set, "break without target", code.find_source_location());
1510
1511 // need to process destructor stack
1513 code.source_location(), dest, mode, targets.break_stack_node);
1514
1515 // add goto
1516 dest.add(
1517 goto_programt::make_goto(targets.break_target, code.source_location()));
1518}
1519
1521 const code_frontend_returnt &code,
1522 goto_programt &dest,
1523 const irep_idt &mode)
1524{
1525 if(!targets.return_set)
1526 {
1528 "return without target", code.find_source_location());
1529 }
1530
1532 code.operands().empty() || code.operands().size() == 1,
1533 "return takes none or one operand",
1534 code.find_source_location());
1535
1536 code_frontend_returnt new_code(code);
1537 clean_expr_resultt side_effects;
1538
1539 if(new_code.has_return_value())
1540 {
1541 bool result_is_used = new_code.return_value().type().id() != ID_empty;
1542
1543 side_effects = clean_expr(new_code.return_value(), mode, result_is_used);
1544 dest.destructive_append(side_effects.side_effects);
1545
1546 // remove void-typed return value
1547 if(!result_is_used)
1548 new_code.return_value().make_nil();
1549 }
1550
1551 if(targets.has_return_value)
1552 {
1554 new_code.has_return_value(),
1555 "function must return value",
1556 new_code.find_source_location());
1557
1558 // Now add a 'set return value' instruction to set the return value.
1560 new_code.return_value(), new_code.source_location()));
1561 destruct_locals(side_effects.temporaries, dest, ns);
1562 }
1563 else
1564 {
1566 !new_code.has_return_value() ||
1567 new_code.return_value().type().id() == ID_empty,
1568 "function must not return value",
1569 code.find_source_location());
1570 }
1571
1572 // Need to process _entire_ destructor stack.
1573 unwind_destructor_stack(code.source_location(), dest, mode);
1574
1575 // add goto to end-of-function
1577 targets.return_target, new_code.source_location()));
1578}
1579
1581 const code_continuet &code,
1582 goto_programt &dest,
1583 const irep_idt &mode)
1584{
1586 targets.continue_set,
1587 "continue without target",
1588 code.find_source_location());
1589
1590 // need to process destructor stack
1592 code.source_location(), dest, mode, targets.continue_stack_node);
1593
1594 // add goto
1595 dest.add(
1596 goto_programt::make_goto(targets.continue_target, code.source_location()));
1597}
1598
1600{
1601 // this instruction will be completed during post-processing
1604
1605 // Loop contracts annotated in GOTO
1606 convert_loop_contracts(code, t);
1607
1608 // remember it to do the target later
1609 targets.gotos.emplace_back(t, targets.scope_stack.get_current_node());
1610}
1611
1613 const codet &code,
1614 goto_programt &dest)
1615{
1616 // this instruction will turn into OTHER during post-processing
1618 code, code.source_location(), NO_INSTRUCTION_TYPE, nil_exprt(), {}));
1619
1620 // remember it to do this later
1621 targets.computed_gotos.push_back(t);
1622}
1623
1625{
1627 code, code.source_location(), START_THREAD, nil_exprt(), {}));
1628
1629 // remember it to do target later
1630 targets.gotos.emplace_back(
1631 start_thread, targets.scope_stack.get_current_node());
1632}
1633
1635{
1637 code.operands().empty(),
1638 "end_thread expects no operands",
1639 code.find_source_location());
1640
1641 copy(code, END_THREAD, dest);
1642}
1643
1645{
1647 code.operands().empty(),
1648 "atomic_begin expects no operands",
1649 code.find_source_location());
1650
1651 copy(code, ATOMIC_BEGIN, dest);
1652}
1653
1655{
1657 code.operands().empty(),
1658 ": atomic_end expects no operands",
1659 code.find_source_location());
1660
1661 copy(code, ATOMIC_END, dest);
1662}
1663
1665 const code_ifthenelset &code,
1666 goto_programt &dest,
1667 const irep_idt &mode)
1668{
1669 DATA_INVARIANT(code.then_case().is_not_nil(), "cannot accept an empty body");
1670
1671 bool has_else = !code.else_case().is_nil();
1672
1673 const source_locationt &source_location = code.source_location();
1674
1675 // We do a bit of special treatment for && in the condition
1676 // in case cleaning would be needed otherwise.
1677 if(
1678 code.cond().id() == ID_and && code.cond().operands().size() == 2 &&
1679 (needs_cleaning(to_binary_expr(code.cond()).op0()) ||
1680 needs_cleaning(to_binary_expr(code.cond()).op1())) &&
1681 !has_else)
1682 {
1683 // if(a && b) XX --> if(a) if(b) XX
1685 to_binary_expr(code.cond()).op1(), code.then_case());
1686 new_if1.add_source_location() = source_location;
1688 to_binary_expr(code.cond()).op0(), std::move(new_if1));
1689 new_if0.add_source_location() = source_location;
1690 return convert_ifthenelse(new_if0, dest, mode);
1691 }
1692
1693 exprt tmp_guard = code.cond();
1694 clean_expr_resultt side_effects = clean_expr(tmp_guard, mode);
1695 dest.destructive_append(side_effects.side_effects);
1696
1697 // convert 'then'-branch
1699 destruct_locals(side_effects.temporaries, tmp_then, ns);
1700 convert(code.then_case(), tmp_then, mode);
1702 code.then_case().get_statement() == ID_block
1703 ? to_code_block(code.then_case()).end_location()
1704 : code.then_case().source_location();
1705
1707 destruct_locals(side_effects.temporaries, tmp_else, ns);
1709
1710 if(has_else)
1711 {
1712 convert(code.else_case(), tmp_else, mode);
1713 else_end_location = code.else_case().get_statement() == ID_block
1714 ? to_code_block(code.else_case()).end_location()
1715 : code.else_case().source_location();
1716 }
1717
1719 tmp_guard,
1720 source_location,
1721 tmp_then,
1723 tmp_else,
1725 dest,
1726 mode);
1727}
1728
1730 const exprt &expr,
1731 const irep_idt &id,
1732 std::list<exprt> &dest)
1733{
1734 if(expr.id() != id)
1735 {
1736 dest.push_back(expr);
1737 }
1738 else
1739 {
1740 // left-to-right is important
1741 for(const auto &op : expr.operands())
1742 collect_operands(op, id, dest);
1743 }
1744}
1745
1749static inline bool is_size_one(const goto_programt &g)
1750{
1751 return (!g.instructions.empty()) &&
1752 ++g.instructions.begin() == g.instructions.end();
1753}
1754
1757 const exprt &guard,
1758 const source_locationt &source_location,
1759 goto_programt &true_case,
1761 goto_programt &false_case,
1763 goto_programt &dest,
1764 const irep_idt &mode)
1765{
1766 if(is_empty(true_case) && is_empty(false_case))
1767 {
1768 // hmpf. Useless branch.
1771 dest.add(goto_programt::make_goto(z, guard, source_location));
1773 return;
1774 }
1775
1776 // do guarded assertions directly
1777 if(
1778 is_size_one(true_case) && true_case.instructions.back().is_assert() &&
1779 true_case.instructions.back().condition().is_false() &&
1780 true_case.instructions.back().labels.empty())
1781 {
1782 // The above conjunction deliberately excludes the instance
1783 // if(some) { label: assert(false); }
1784 true_case.instructions.back().condition_nonconst() = boolean_negate(guard);
1785 dest.destructive_append(true_case);
1786 true_case.instructions.clear();
1787 if(
1788 is_empty(false_case) ||
1789 (is_size_one(false_case) &&
1790 is_skip(false_case, false_case.instructions.begin())))
1791 return;
1792 }
1793
1794 // similarly, do guarded assertions directly
1795 if(
1796 is_size_one(false_case) && false_case.instructions.back().is_assert() &&
1797 false_case.instructions.back().condition().is_false() &&
1798 false_case.instructions.back().labels.empty())
1799 {
1800 // The above conjunction deliberately excludes the instance
1801 // if(some) ... else { label: assert(false); }
1802 false_case.instructions.back().condition_nonconst() = guard;
1803 dest.destructive_append(false_case);
1804 false_case.instructions.clear();
1805 if(
1806 is_empty(true_case) ||
1807 (is_size_one(true_case) &&
1808 is_skip(true_case, true_case.instructions.begin())))
1809 return;
1810 }
1811
1812 // a special case for C libraries that use
1813 // (void)((cond) || (assert(0),0))
1814 if(
1815 is_empty(false_case) && true_case.instructions.size() == 2 &&
1816 true_case.instructions.front().is_assert() &&
1817 simplify_expr(true_case.instructions.front().condition(), ns).is_false() &&
1818 true_case.instructions.front().labels.empty() &&
1819 true_case.instructions.back().is_other() &&
1820 true_case.instructions.back().get_other().get_statement() ==
1821 ID_expression &&
1822 true_case.instructions.back().labels.empty())
1823 {
1824 true_case.instructions.front().condition_nonconst() = boolean_negate(guard);
1825 true_case.instructions.erase(--true_case.instructions.end());
1826 dest.destructive_append(true_case);
1827 true_case.instructions.clear();
1828
1829 return;
1830 }
1831
1832 // Flip around if no 'true' case code.
1833 if(is_empty(true_case))
1834 {
1835 return generate_ifthenelse(
1837 source_location,
1838 false_case,
1840 true_case,
1842 dest,
1843 mode);
1844 }
1845
1846 bool has_else = !is_empty(false_case);
1847
1848 // if(c) P;
1849 //--------------------
1850 // v: if(!c) goto z;
1851 // w: P;
1852 // z: ;
1853
1854 // if(c) P; else Q;
1855 //--------------------
1856 // v: if(!c) goto y;
1857 // w: P;
1858 // x: goto z;
1859 // y: Q;
1860 // z: ;
1861
1862 // do the x label
1866
1867 // do the z label
1871
1872 // y: Q;
1875 if(has_else)
1876 {
1877 tmp_y.swap(false_case);
1878 y = tmp_y.instructions.begin();
1879 }
1880
1881 // v: if(!c) goto z/y;
1884 boolean_negate(guard), has_else ? y : z, source_location, tmp_v, mode);
1885
1886 // w: P;
1888 tmp_w.swap(true_case);
1889
1890 // x: goto z;
1891 CHECK_RETURN(!tmp_w.instructions.empty());
1892 x->complete_goto(z);
1893
1896
1897 // When the `then` branch of a balanced `if` condition ends with a `return` or
1898 // a `goto` statement, it is not necessary to add the `goto z` and `z:` goto
1899 // elements as they are never used.
1900 // This helps for example when using `--cover location` as such command are
1901 // marked unreachable, but are not part of the user-provided code to analyze.
1902 bool then_branch_returns = dest.instructions.rbegin()->is_goto();
1903
1904 if(has_else)
1905 {
1906 // Don't add the `goto` at the end of the `then` branch if not needed
1908 {
1910 }
1912 }
1913
1914 // Don't add the `z` label at the end of the `if` when not needed.
1916 {
1918 }
1919}
1920
1922static bool has_and_or(const exprt &expr)
1923{
1924 for(const auto &op : expr.operands())
1925 {
1926 if(has_and_or(op))
1927 return true;
1928 }
1929
1930 if(expr.id() == ID_and || expr.id() == ID_or)
1931 return true;
1932
1933 return false;
1934}
1935
1937 const exprt &guard,
1939 const source_locationt &source_location,
1940 goto_programt &dest,
1941 const irep_idt &mode)
1942{
1944 {
1945 // if(guard) goto target;
1946 // becomes
1947 // if(guard) goto target; else goto next;
1948 // next: skip;
1949
1952 tmp.add(goto_programt::make_skip(source_location));
1953
1955 guard, target_true, target_false, source_location, dest, mode);
1956
1957 dest.destructive_append(tmp);
1958 }
1959 else
1960 {
1961 // simple branch
1962 exprt cond = guard;
1963 clean_expr_resultt side_effects = clean_expr(cond, mode);
1964 dest.destructive_append(side_effects.side_effects);
1965
1966 dest.add(goto_programt::make_goto(target_true, cond, source_location));
1970 destruct_locals(side_effects.temporaries, dest, ns);
1971 }
1972}
1973
1976 const exprt &guard,
1979 const source_locationt &source_location,
1980 goto_programt &dest,
1981 const irep_idt &mode)
1982{
1983 if(guard.id() == ID_not)
1984 {
1985 // simply swap targets
1987 to_not_expr(guard).op(),
1990 source_location,
1991 dest,
1992 mode);
1993 return;
1994 }
1995
1996 if(guard.id() == ID_and)
1997 {
1998 // turn
1999 // if(a && b) goto target_true; else goto target_false;
2000 // into
2001 // if(!a) goto target_false;
2002 // if(!b) goto target_false;
2003 // goto target_true;
2004
2005 std::list<exprt> op;
2006 collect_operands(guard, guard.id(), op);
2007
2008 for(const auto &expr : op)
2010 boolean_negate(expr), target_false, source_location, dest, mode);
2011
2012 dest.add(goto_programt::make_goto(target_true, source_location));
2013
2014 return;
2015 }
2016 else if(guard.id() == ID_or)
2017 {
2018 // turn
2019 // if(a || b) goto target_true; else goto target_false;
2020 // into
2021 // if(a) goto target_true;
2022 // if(b) goto target_true;
2023 // goto target_false;
2024
2025 std::list<exprt> op;
2026 collect_operands(guard, guard.id(), op);
2027
2028 // true branch(es)
2029 for(const auto &expr : op)
2031 expr, target_true, source_location, dest, mode);
2032
2033 // false branch
2034 dest.add(goto_programt::make_goto(target_false, guard.source_location()));
2035
2036 return;
2037 }
2038
2039 exprt cond = guard;
2040 clean_expr_resultt side_effects = clean_expr(cond, mode);
2041 dest.destructive_append(side_effects.side_effects);
2042
2043 // true branch
2044 dest.add(goto_programt::make_goto(target_true, cond, source_location));
2048
2049 // false branch
2050 dest.add(goto_programt::make_goto(target_false, source_location));
2053}
2054
2056{
2057 if(expr.id() == ID_typecast)
2058 return get_string_constant(to_typecast_expr(expr).op(), value);
2059
2060 if(
2061 expr.id() == ID_address_of &&
2062 to_address_of_expr(expr).object().id() == ID_index)
2063 {
2064 exprt index_op =
2065 get_constant(to_index_expr(to_address_of_expr(expr).object()).array());
2067
2068 if(index_op.id() == ID_string_constant)
2069 {
2070 value = to_string_constant(index_op).value();
2071 return false;
2072 }
2073 else if(index_op.id() == ID_array)
2074 {
2075 std::string result;
2076 for(const auto &op : as_const(index_op).operands())
2077 {
2078 if(op.is_constant())
2079 {
2080 const auto i = numeric_cast<std::size_t>(op);
2081 if(!i.has_value())
2082 return true;
2083
2084 if(i.value() != 0) // to skip terminating 0
2085 result += static_cast<char>(i.value());
2086 }
2087 }
2088
2089 return value = result, false;
2090 }
2091 }
2092
2093 if(expr.id() == ID_string_constant)
2094 {
2095 value = to_string_constant(expr).value();
2096 return false;
2097 }
2098
2099 return true;
2100}
2101
2103{
2105
2106 const bool res = get_string_constant(expr, result);
2108 !res,
2109 "expected string constant",
2110 expr.find_source_location(),
2111 expr.pretty());
2112
2113 return result;
2114}
2115
2117{
2118 if(expr.id() == ID_symbol)
2119 {
2120 const symbolt &symbol = ns.lookup(to_symbol_expr(expr));
2121
2122 return symbol.value;
2123 }
2124 else if(expr.id() == ID_member)
2125 {
2126 auto tmp = to_member_expr(expr);
2127 tmp.compound() = get_constant(tmp.compound());
2128 return std::move(tmp);
2129 }
2130 else if(expr.id() == ID_index)
2131 {
2132 auto tmp = to_index_expr(expr);
2133 tmp.op0() = get_constant(tmp.op0());
2134 tmp.op1() = get_constant(tmp.op1());
2135 return std::move(tmp);
2136 }
2137 else
2138 return expr;
2139}
2140
2142 const typet &type,
2143 const std::string &suffix,
2144 goto_programt &dest,
2145 const source_locationt &source_location,
2146 const irep_idt &mode)
2147{
2148 PRECONDITION(!mode.empty());
2149 symbolt &new_symbol = get_fresh_aux_symbol(
2150 type,
2152 "tmp_" + suffix,
2153 source_location,
2154 mode,
2155 symbol_table);
2156
2157 if(type.id() != ID_code)
2158 {
2159 dest.add(
2160 goto_programt::make_decl(new_symbol.symbol_expr(), source_location));
2161 }
2162
2163 return new_symbol;
2164}
2165
2167 exprt &expr,
2168 const std::string &suffix,
2169 goto_programt &dest,
2170 const irep_idt &mode)
2171{
2172 const source_locationt source_location = expr.find_source_location();
2173
2174 symbolt &new_symbol =
2175 new_tmp_symbol(expr.type(), suffix, dest, source_location, mode);
2176
2177 code_assignt assignment;
2178 assignment.lhs() = new_symbol.symbol_expr();
2179 assignment.rhs() = expr;
2180 assignment.add_source_location() = source_location;
2181
2182 convert(assignment, dest, mode);
2183
2184 expr = new_symbol.symbol_expr();
2185
2186 return to_symbol_expr(expr).get_identifier();
2187}
2188
2190 const codet &code,
2191 symbol_table_baset &symbol_table,
2192 goto_programt &dest,
2193 message_handlert &message_handler,
2194 const irep_idt &mode)
2195{
2197 symbol_table_buildert::wrap(symbol_table);
2199 goto_convert.goto_convert(code, dest, mode);
2200}
2201
2203 symbol_table_baset &symbol_table,
2204 goto_programt &dest,
2205 message_handlert &message_handler)
2206{
2207 // find main symbol
2208 const symbol_table_baset::symbolst::const_iterator s_it =
2209 symbol_table.symbols.find("main");
2210
2212 s_it != symbol_table.symbols.end(), "failed to find main symbol");
2213
2214 const symbolt &symbol = s_it->second;
2215
2217 to_code(symbol.value), symbol_table, dest, message_handler, symbol.mode);
2218}
2219
2235 const code_blockt &thread_body,
2236 goto_programt &dest,
2237 const irep_idt &mode)
2238{
2239 goto_programt preamble, body, postamble;
2240
2242 convert(thread_body, body, mode);
2243
2245 static_cast<const codet &>(get_nil_irep()),
2246 thread_body.source_location(),
2247 END_THREAD,
2248 nil_exprt(),
2249 {}));
2251
2253 static_cast<const codet &>(get_nil_irep()),
2254 thread_body.source_location(),
2256 nil_exprt(),
2257 {c}));
2258 preamble.add(goto_programt::make_goto(z, thread_body.source_location()));
2259
2260 dest.destructive_append(preamble);
2261 dest.destructive_append(body);
2262 dest.destructive_append(postamble);
2263}
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition as_const.h:14
static exprt guard(const exprt::operandst &guards, exprt cond)
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
Operator to return the address of an object.
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
Result of an attempt to find ancestor information about two nodes.
Definition scope_tree.h:25
Boolean AND.
Definition std_expr.h:2125
A base class for binary expressions.
Definition std_expr.h:638
exprt & op0()
Definition expr.h:133
exprt & op1()
Definition expr.h:136
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition std_expr.h:762
The Boolean type.
Definition std_types.h:36
A non-fatal assertion, which checks a condition then permits execution to continue.
Definition std_code.h:270
const exprt & assertion() const
Definition std_code.h:276
A goto_instruction_codet representing an assignment in the program.
An assumption, which must hold in subsequent code.
Definition std_code.h:217
const exprt & assumption() const
Definition std_code.h:223
A codet representing sequential composition of program statements.
Definition std_code.h:130
code_operandst & statements()
Definition std_code.h:138
source_locationt end_location() const
Definition std_code.h:187
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
A goto_instruction_codet representing the removal of a local variable going out of scope.
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
const exprt & expression() const
Definition std_code.h:1401
codet representation of a for statement.
Definition std_code.h:734
const exprt & cond() const
Definition std_code.h:759
const exprt & iter() const
Definition std_code.h:769
const codet & body() const
Definition std_code.h:779
const exprt & init() const
Definition std_code.h:749
A codet representing the declaration of a local variable.
Definition std_code.h:347
const irep_idt & get_identifier() const
Definition std_code.h:364
codet representation of a "return from a function" statement.
Definition std_code.h:893
const exprt & return_value() const
Definition std_code.h:903
bool has_return_value() const
Definition std_code.h:913
goto_instruction_codet representation of a function call statement.
codet representation of a switch-case, i.e. a case statement within a switch.
Definition std_code.h:1097
const exprt & upper() const
upper bound of range
Definition std_code.h:1119
const exprt & lower() const
lower bound of range
Definition std_code.h:1107
codet & code()
the statement to be executed when the case applies
Definition std_code.h:1131
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
std::vector< exception_list_entryt > exception_listt
Definition std_code.h:1849
codet representation of a switch-case, i.e. a case statement within a switch.
Definition std_code.h:1023
const exprt & case_op() const
Definition std_code.h:1040
bool is_default() const
Definition std_code.h:1030
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
codet representing a while statement.
Definition std_code.h:610
const exprt & cond() const
Definition std_code.h:617
const codet & body() const
Definition std_code.h:627
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 starts_with(const char *s) const
equivalent of as_string().starts_with(s)
Definition dstring.h:95
bool empty() const
Definition dstring.h:89
The empty type.
Definition std_types.h:51
Equality.
Definition std_expr.h:1366
Base class for all expressions.
Definition expr.h:56
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition expr.cpp:147
std::vector< exprt > operandst
Definition expr.h:58
bool is_false() const
Return whether the expression is a constant representing false.
Definition expr.cpp:34
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
void convert_for(const code_fort &code, goto_programt &dest, const irep_idt &mode)
void convert_assume(const code_assumet &code, goto_programt &dest, const irep_idt &mode)
symbol_table_baset & symbol_table
void convert_expression(const code_expressiont &code, goto_programt &dest, const irep_idt &mode)
void convert_while(const code_whilet &code, goto_programt &dest, const irep_idt &mode)
void convert_loop_contracts(const codet &code, goto_programt::targett loop)
void convert_assign(const code_assignt &code, goto_programt &dest, const irep_idt &mode)
void convert_gcc_computed_goto(const codet &code, goto_programt &dest)
void goto_convert_rec(const codet &code, goto_programt &dest, const irep_idt &mode)
void convert_CPROVER_throw(const codet &code, goto_programt &dest, const irep_idt &mode)
void optimize_guarded_gotos(goto_programt &dest)
Rewrite "if(x) goto z; goto y; z:" into "if(!x) goto y;" This only works if the "goto y" is not a bra...
void convert_atomic_begin(const codet &code, goto_programt &dest)
void goto_convert(const codet &code, goto_programt &dest, const irep_idt &mode)
void convert_msc_try_finally(const codet &code, goto_programt &dest, const irep_idt &mode)
void convert_gcc_switch_case_range(const code_gcc_switch_case_ranget &, goto_programt &dest, const irep_idt &mode)
virtual void do_function_call(const exprt &lhs, const exprt &function, const exprt::operandst &arguments, goto_programt &dest, const irep_idt &mode)
irep_idt get_string_constant(const exprt &expr)
void convert_label(const code_labelt &code, goto_programt &dest, const irep_idt &mode)
void copy(const codet &code, goto_program_instruction_typet type, goto_programt &dest)
exprt get_constant(const exprt &expr)
void generate_ifthenelse(const exprt &cond, const source_locationt &, goto_programt &true_case, const source_locationt &, goto_programt &false_case, const source_locationt &, goto_programt &dest, const irep_idt &mode)
if(guard) true_case; else false_case;
void convert_start_thread(const codet &code, goto_programt &dest)
void finish_gotos(goto_programt &dest, const irep_idt &mode)
void generate_conditional_branch(const exprt &guard, goto_programt::targett target_true, goto_programt::targett target_false, const source_locationt &, goto_programt &dest, const irep_idt &mode)
if(guard) goto target_true; else goto target_false;
void convert_ifthenelse(const code_ifthenelset &code, goto_programt &dest, const irep_idt &mode)
void convert_atomic_end(const codet &code, goto_programt &dest)
void unwind_destructor_stack(const source_locationt &source_location, goto_programt &dest, const irep_idt &mode, std::optional< node_indext > destructor_end_point={}, std::optional< node_indext > destructor_start_point={})
Unwinds the destructor stack and creates destructors for each node between destructor_start_point and...
std::string tmp_symbol_prefix
void convert_frontend_decl(const code_frontend_declt &, goto_programt &, const irep_idt &mode)
void convert_gcc_local_label(const codet &code, goto_programt &dest)
struct goto_convertt::targetst targets
void convert_break(const code_breakt &code, goto_programt &dest, const irep_idt &mode)
void convert_function_call(const code_function_callt &code, goto_programt &dest, const irep_idt &mode)
symbolt & new_tmp_symbol(const typet &type, const std::string &suffix, goto_programt &dest, const source_locationt &, const irep_idt &mode)
void convert_goto(const code_gotot &code, goto_programt &dest)
exprt case_guard(const exprt &value, const caset &case_op)
void convert_CPROVER_try_catch(const codet &code, goto_programt &dest, const irep_idt &mode)
void convert_cpp_delete(const codet &code, goto_programt &dest)
void convert_switch(const code_switcht &code, goto_programt &dest, const irep_idt &mode)
static void collect_operands(const exprt &expr, const irep_idt &id, std::list< exprt > &dest)
void convert_decl_type(const codet &code, goto_programt &dest)
void convert_dowhile(const code_dowhilet &code, goto_programt &dest, const irep_idt &mode)
void convert_skip(const codet &code, goto_programt &dest)
void convert_asm(const code_asmt &code, goto_programt &dest)
Definition goto_asm.cpp:14
void convert_switch_case(const code_switch_caset &code, goto_programt &dest, const irep_idt &mode)
void convert_msc_try_except(const codet &code, goto_programt &dest, const irep_idt &mode)
void convert_continue(const code_continuet &code, goto_programt &dest, const irep_idt &mode)
void convert_try_catch(const codet &code, goto_programt &dest, const irep_idt &mode)
irep_idt make_temp_symbol(exprt &expr, const std::string &suffix, goto_programt &, const irep_idt &mode)
void convert_assert(const code_assertt &code, goto_programt &dest, const irep_idt &mode)
static bool needs_cleaning(const exprt &expr)
Returns 'true' for expressions that may change the program state.
void finish_computed_gotos(goto_programt &dest)
void convert(const codet &code, goto_programt &dest, const irep_idt &mode)
converts 'code' and appends the result to 'dest'
void convert_CPROVER_try_finally(const codet &code, goto_programt &dest, const irep_idt &mode)
std::list< std::pair< goto_programt::targett, goto_programt::instructiont > > declaration_hop_instrumentationt
exprt::operandst caset
declaration_hop_instrumentationt build_declaration_hops(goto_programt &dest, std::unordered_map< irep_idt, symbolt, irep_id_hash > &label_flags, const build_declaration_hops_inputst &inputs)
static void replace_new_object(const exprt &object, exprt &dest)
void convert_msc_leave(const codet &code, goto_programt &dest, const irep_idt &mode)
void convert_return(const code_frontend_returnt &, goto_programt &dest, const irep_idt &mode)
virtual void do_cpp_new(const exprt &lhs, const side_effect_exprt &rhs, goto_programt &dest)
clean_expr_resultt clean_expr(exprt &expr, const irep_idt &mode, bool result_is_used=true)
void convert_block(const code_blockt &code, goto_programt &dest, const irep_idt &mode)
void generate_thread_block(const code_blockt &thread_body, goto_programt &dest, const irep_idt &mode)
Generates the necessary goto-instructions to represent a thread-block.
void convert_end_thread(const codet &code, goto_programt &dest)
This class represents an instruction in the GOTO intermediate representation.
void complete_goto(targett _target)
const goto_instruction_codet & code() const
Get the code represented by this instruction.
targetst targets
The list of successor instructions.
static const unsigned nil_target
Uniquely identify an invalid target or location.
const source_locationt & source_location() const
A generic container class for the GOTO intermediate representation of one function.
static instructiont make_assumption(const exprt &g, const source_locationt &l=source_locationt::nil())
instructionst instructions
The list of instructions in the goto program.
static instructiont make_set_return_value(exprt return_value, const source_locationt &l=source_locationt::nil())
void insert_before_swap(targett target)
Insertion that preserves jumps to "target".
void destructive_insert(const_targett target, goto_programt &p)
Inserts the given program p before target.
instructionst::iterator targett
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
static instructiont make_skip(const source_locationt &l=source_locationt::nil())
targett insert_after(const_targett target)
Insertion after the instruction pointed-to by the given instruction iterator target.
static instructiont make_other(const goto_instruction_codet &_code, const source_locationt &l=source_locationt::nil())
static instructiont make_location(const source_locationt &l)
targett add(instructiont &&instruction)
Adds a given instruction at the end.
static instructiont make_goto(targett _target, const source_locationt &l=source_locationt::nil())
bool empty() const
Is the program empty?
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
static instructiont make_incomplete_goto(const exprt &_cond, const source_locationt &l=source_locationt::nil())
The trinary if-then-else operator.
Definition std_expr.h:2497
Thrown when a goto program that's being processed is in an invalid format, for example passing the wr...
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
bool is_not_nil() const
Definition irep.h:372
const irep_idt & id() const
Definition irep.h:388
source_locationt source_location
Definition message.h:239
mstreamt & debug() const
Definition message.h:421
mstreamt & warning() const
Definition message.h:396
mstreamt & result() const
Definition message.h:401
static eomt eom
Definition message.h:289
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
The NIL expression.
Definition std_expr.h:3208
void set_case_number(const irep_idt &number)
Expression to hold a symbol (variable)
Definition std_expr.h:131
The symbol table base class interface.
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Author: Diffblue Ltd.
static symbol_table_buildert wrap(symbol_table_baset &base_symbol_table)
Symbol table entry.
Definition symbol.h:28
bool is_static_lifetime
Definition symbol.h:70
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition symbol.cpp:121
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
irep_idt mode
Language mode.
Definition symbol.h:49
The Boolean constant true.
Definition std_expr.h:3190
Semantic type conversion.
Definition std_expr.h:2073
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2081
The type of an expression, extends irept.
Definition type.h:29
Generic base class for unary expressions.
Definition std_expr.h:361
#define CPROVER_PREFIX
code_function_callt get_destructor(const namespacet &ns, const typet &type)
void destruct_locals(const std::list< irep_idt > &vars, goto_programt &dest, const namespacet &ns)
Destructor Calls.
#define Forall_operands(it, expr)
Definition expr.h:27
exprt boolean_negate(const exprt &src)
negate a Boolean expression, possibly removing a not_exprt, and swapping false and true
Deprecated expression utility functions.
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
void goto_convert(const codet &code, symbol_table_baset &symbol_table, goto_programt &dest, message_handlert &message_handler, const irep_idt &mode)
static bool has_and_or(const exprt &expr)
if(guard) goto target;
static bool is_size_one(const goto_programt &g)
This is (believed to be) faster than using std::list.size.
static void finish_catch_push_targets(goto_programt &dest)
Populate the CATCH instructions with the targets corresponding to their associated labels.
static bool is_empty(const goto_programt &goto_program)
Program Transformation.
Program Transformation.
const code_function_callt & to_code_function_call(const goto_instruction_codet &code)
const code_assignt & to_code_assign(const goto_instruction_codet &code)
#define forall_goto_program_instructions(it, program)
#define Forall_goto_program_instructions(it, program)
goto_program_instruction_typet
The type of an instruction in a GOTO program.
@ ATOMIC_END
@ DEAD
@ ASSIGN
@ ATOMIC_BEGIN
@ CATCH
@ END_THREAD
@ SKIP
@ NO_INSTRUCTION_TYPE
@ START_THREAD
@ DECL
@ OTHER
const irept & get_nil_irep()
Definition irep.cpp:19
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
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 is_skip(const goto_programt &body, goto_programt::const_targett it, bool ignore_labels)
Determine whether the instruction is semantically equivalent to a skip (no-op).
Program Transformation.
std::size_t node_indext
Definition scope_tree.h:19
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_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Same as invariant, with one or more diagnostics attached Diagnostics can be of any type that has a sp...
Definition invariant.h:437
#define DATA_INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Definition invariant.h:535
side_effect_exprt & to_side_effect_expr(exprt &expr)
Definition std_code.h:1506
const code_breakt & to_code_break(const codet &code)
Definition std_code.h:1203
const code_switch_caset & to_code_switch_case(const codet &code)
Definition std_code.h:1077
const code_gotot & to_code_goto(const codet &code)
Definition std_code.h:875
const code_assertt & to_code_assert(const codet &code)
Definition std_code.h:304
static code_push_catcht & to_code_push_catch(codet &code)
Definition std_code.h:1883
const code_frontend_returnt & to_code_frontend_return(const codet &code)
Definition std_code.h:943
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_assumet & to_code_assume(const codet &code)
Definition std_code.h:251
const code_whilet & to_code_while(const codet &code)
Definition std_code.h:654
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 code_gcc_switch_case_ranget & to_code_gcc_switch_case_range(const codet &code)
Definition std_code.h:1161
code_asmt & to_code_asm(codet &code)
Definition std_code.h:1282
const code_fort & to_code_for(const codet &code)
Definition std_code.h:823
const code_switcht & to_code_switch(const codet &code)
Definition std_code.h:592
const code_frontend_declt & to_code_frontend_decl(const codet &code)
Definition std_code.h:429
code_expressiont & to_code_expression(codet &code)
Definition std_code.h:1428
const code_continuet & to_code_continue(const codet &code)
Definition std_code.h:1239
const codet & to_code(const exprt &expr)
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition std_expr.cpp:71
API to expression classes.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1538
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition std_expr.h:715
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition std_expr.h:2577
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3063
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
Definition std_expr.h:2479
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
const string_constantt & to_string_constant(const exprt &expr)
goto_programt::targett goto_instruction
goto_programt::targett label_instruction
std::list< irep_idt > temporaries
Identifiers of temporaries introduced while cleaning an expression.
void add(clean_expr_resultt &&other)
void add_temporary(const irep_idt &id)
goto_programt side_effects
Statements implementing side effects of the expression that was subject to cleaning.