CBMC
goto_convert.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Program Transformation
4 
5 Author: 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>
18 #include <util/exception_utils.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>
24 #include <util/string_constant.h>
26 
27 #include "destructor.h"
28 #include "remove_skip.h"
29 
30 static bool is_empty(const goto_programt &goto_program)
31 {
32  forall_goto_program_instructions(it, goto_program)
33  if(!is_skip(goto_program, it))
34  return false;
35 
36  return true;
37 }
38 
42 {
43  std::map<irep_idt, goto_programt::targett> label_targets;
44 
45  // in the first pass collect the labels and the corresponding targets
47  {
48  if(!it->labels.empty())
49  {
50  for(auto label : it->labels)
51  // record the label and the corresponding target
52  label_targets.insert(std::make_pair(label, it));
53  }
54  }
55 
56  // in the second pass set the targets
57  for(auto &instruction : dest.instructions)
58  {
59  if(
60  instruction.is_catch() &&
61  instruction.code().get_statement() == ID_push_catch)
62  {
63  // Populate `targets` with a GOTO instruction target per
64  // exception handler if it isn't already populated.
65  // (Java handlers, for example, need this finish step; C++
66  // handlers will already be populated by now)
67 
68  if(instruction.targets.empty())
69  {
70  bool handler_added=true;
71  const code_push_catcht::exception_listt &handler_list =
72  to_code_push_catch(instruction.code()).exception_list();
73 
74  for(const auto &handler : handler_list)
75  {
76  // some handlers may not have been converted (if there was no
77  // exception to be caught); in such a situation we abort
78  if(label_targets.find(handler.get_label())==label_targets.end())
79  {
80  handler_added=false;
81  break;
82  }
83  }
84 
85  if(!handler_added)
86  continue;
87 
88  for(const auto &handler : handler_list)
89  instruction.targets.push_back(label_targets.at(handler.get_label()));
90  }
91  }
92  }
93 }
94 
96 {
103 };
104 
106  goto_programt &program,
107  std::unordered_map<irep_idt, symbolt, irep_id_hash> &label_flags,
108  const build_declaration_hops_inputst &inputs)
109 {
110  // In the case of a goto jumping into a scope, the declarations (but not the
111  // initialisations) need to be executed. This function performs a
112  // transformation from code that looks like -
113  // {
114  // statement_block_a();
115  // if(...)
116  // goto user_label;
117  // statement_block_b();
118  // int x;
119  // x = 0;
120  // statement_block_c();
121  // int y;
122  // y = 0;
123  // statement_block_d();
124  // user_label:
125  // statement_block_e();
126  // }
127  // to code which looks like -
128  // {
129  // __CPROVER_bool going_to::user_label;
130  // going_to::user_label = false;
131  // statement_block_a();
132  // if(...)
133  // {
134  // going_to::user_label = true;
135  // goto scope_x_label;
136  // }
137  // statement_block_b();
138  // scope_x_label:
139  // int x;
140  // if going_to::user_label goto scope_y_label:
141  // x = 0;
142  // statement_block_c();
143  // scope_y_label:
144  // int y;
145  // if going_to::user_label goto user_label:
146  // y = 0;
147  // statement_block_d();
148  // user_label:
149  // going_to::user_label = false;
150  // statement_block_e();
151  // }
152 
154 
155  const auto flag = [&]() -> symbolt {
156  const auto existing_flag = label_flags.find(inputs.label);
157  if(existing_flag != label_flags.end())
158  return existing_flag->second;
159  source_locationt label_location =
160  inputs.label_instruction->source_location();
161  label_location.set_hide();
162  const symbolt &new_flag = get_fresh_aux_symbol(
163  bool_typet{},
164  "going_to",
165  id2string(inputs.label),
166  label_location,
167  inputs.mode,
168  symbol_table);
169  label_flags.emplace(inputs.label, new_flag);
170 
171  // Create and initialise flag.
172  goto_programt flag_creation;
173  flag_creation.instructions.push_back(
174  goto_programt::make_decl(new_flag.symbol_expr(), label_location));
175  const auto make_clear_flag = [&]() -> goto_programt::instructiont {
177  new_flag.symbol_expr(), false_exprt{}, label_location);
178  };
179  flag_creation.instructions.push_back(make_clear_flag());
180  program.destructive_insert(program.instructions.begin(), flag_creation);
181 
182  // Clear flag on arrival at label.
183  auto clear_on_arrival = make_clear_flag();
184  program.insert_before_swap(inputs.label_instruction, clear_on_arrival);
185  return new_flag;
186  }();
187 
188  auto goto_instruction = inputs.goto_instruction;
189  {
190  // Set flag before the goto.
191  auto goto_location = goto_instruction->source_location();
192  goto_location.set_hide();
193  auto set_flag = goto_programt::make_assignment(
194  flag.symbol_expr(), true_exprt{}, goto_location);
195  program.insert_before_swap(goto_instruction, set_flag);
196  // Keep this iterator referring to the goto instruction, not the assignment.
197  ++goto_instruction;
198  }
199 
200  auto target = inputs.label_instruction;
203  {
205  auto &declaration = targets.scope_stack.get_declaration(current_node);
207  if(!declaration)
208  continue;
209 
210  bool add_if = declaration->accounted_flags.find(flag.name) ==
211  declaration->accounted_flags.end();
212  if(add_if)
213  {
214  auto declaration_location = declaration->instruction->source_location();
215  declaration_location.set_hide();
216  auto if_goto = goto_programt::make_goto(
217  target, flag.symbol_expr(), declaration_location);
218  program.instructions.insert(
219  std::next(declaration->instruction), std::move(if_goto));
220  declaration->accounted_flags.insert(flag.name);
221  }
222  target = declaration->instruction;
223  }
224 
225  // Update the goto so that it goes to the first declaration rather than its
226  // original/final destination.
227  goto_instruction->set_target(target);
228 }
229 
230 /******************************************************************* \
231 
232 Function: goto_convertt::finish_gotos
233 
234  Inputs:
235 
236  Outputs:
237 
238  Purpose:
239 
240 \*******************************************************************/
241 
243 {
244  std::unordered_map<irep_idt, symbolt, irep_id_hash> label_flags;
245 
246  for(const auto &g_it : targets.gotos)
247  {
248  goto_programt::instructiont &i=*(g_it.first);
249 
250  if(i.is_start_thread())
251  {
252  const irep_idt &goto_label = i.code().get(ID_destination);
253  const auto l_it = targets.labels.find(goto_label);
254 
255  if(l_it == targets.labels.end())
256  {
258  "goto label \'" + id2string(goto_label) + "\' not found",
259  i.code().find_source_location());
260  }
261 
262  i.targets.push_back(l_it->second.first);
263  }
264  else if(i.is_incomplete_goto())
265  {
266  const irep_idt &goto_label = i.code().get(ID_destination);
267  const auto l_it = targets.labels.find(goto_label);
268 
269  if(l_it == targets.labels.end())
270  {
272  "goto label \'" + id2string(goto_label) + "\' not found",
273  i.code().find_source_location());
274  }
275 
276  i.complete_goto(l_it->second.first);
277 
278  node_indext label_target = l_it->second.second;
279  node_indext goto_target = g_it.second;
280 
281  // Compare the currently-live variables on the path of the GOTO and label.
282  // We want to work out what variables should die during the jump.
283  ancestry_resultt intersection_result =
285  goto_target, label_target);
286 
287  // If our goto had no variables of note, just skip (0 is the index of the
288  // root of the scope tree)
289  if(goto_target != 0)
290  {
291  // If the goto recorded a destructor stack, execute as much as is
292  // appropriate for however many automatic variables leave scope.
294  debug() << "adding goto-destructor code on jump to '" << goto_label
295  << "'" << eom;
296 
297  node_indext end_destruct = intersection_result.common_ancestor;
298  goto_programt destructor_code;
300  i.source_location(),
301  destructor_code,
302  mode,
303  end_destruct,
304  goto_target);
305  dest.destructive_insert(g_it.first, destructor_code);
306 
307  // This should leave iterators intact, as long as
308  // goto_programt::instructionst is std::list.
309  }
310 
311  // Variables *entering* scope on goto, is illegal for C++ non-pod types
312  // and impossible in Java. However, with the exception of Variable Length
313  // Arrays (VLAs), this is valid C and should be taken into account.
314  const bool variables_added_to_scope =
315  intersection_result.right_depth_below_common_ancestor > 0;
316  if(variables_added_to_scope)
317  {
318  // If the goto recorded a destructor stack, execute as much as is
319  // appropriate for however many automatic variables leave scope.
321  debug() << "encountered goto '" << goto_label
322  << "' that enters one or more lexical blocks; "
323  << "adding declaration code on jump to '" << goto_label << "'"
324  << eom;
325 
327  inputs.mode = mode;
328  inputs.label = l_it->first;
329  inputs.goto_instruction = g_it.first;
330  inputs.label_instruction = l_it->second.first;
331  inputs.label_scope_index = label_target;
332  inputs.end_scope_index = intersection_result.common_ancestor;
333  build_declaration_hops(dest, label_flags, inputs);
334  }
335  }
336  else
337  {
338  UNREACHABLE;
339  }
340  }
341 
342  targets.gotos.clear();
343 }
344 
346 {
347  for(auto &g_it : targets.computed_gotos)
348  {
350  dereference_exprt destination = to_dereference_expr(i.code().op0());
351  const exprt pointer = destination.pointer();
352 
353  // remember the expression for later checks
354  i =
356 
357  // insert huge case-split
358  for(const auto &label : targets.labels)
359  {
360  exprt label_expr(ID_label, empty_typet());
361  label_expr.set(ID_identifier, label.first);
362 
363  const equal_exprt guard(pointer, address_of_exprt(label_expr));
364 
365  goto_program.insert_after(
366  g_it,
368  label.second.first, guard, i.source_location()));
369  }
370  }
371 
372  targets.computed_gotos.clear();
373 }
374 
379 {
380  // We cannot use a set of targets, as target iterators
381  // cannot be compared at this stage.
382 
383  // collect targets: reset marking
384  for(auto &i : dest.instructions)
385  i.target_number = goto_programt::instructiont::nil_target;
386 
387  // mark the goto targets
388  unsigned cnt = 0;
389  for(auto &i : dest.instructions)
390  if(i.is_goto())
391  i.get_target()->target_number = (++cnt);
392 
393  for(auto it = dest.instructions.begin(); it != dest.instructions.end(); it++)
394  {
395  if(!it->is_goto())
396  continue;
397 
398  auto it_goto_y = std::next(it);
399 
400  if(
401  it_goto_y == dest.instructions.end() || !it_goto_y->is_goto() ||
402  !it_goto_y->condition().is_true() || it_goto_y->is_target())
403  {
404  continue;
405  }
406 
407  auto it_z = std::next(it_goto_y);
408 
409  if(it_z == dest.instructions.end())
410  continue;
411 
412  // cannot compare iterators, so compare target number instead
413  if(it->get_target()->target_number == it_z->target_number)
414  {
415  it->set_target(it_goto_y->get_target());
416  it->condition_nonconst() = boolean_negate(it->condition());
417  it_goto_y->turn_into_skip();
418  }
419  }
420 }
421 
423  const codet &code,
424  goto_programt &dest,
425  const irep_idt &mode)
426 {
427  goto_convert_rec(code, dest, mode);
428 }
429 
431  const codet &code,
432  goto_programt &dest,
433  const irep_idt &mode)
434 {
435  convert(code, dest, mode);
436 
437  finish_gotos(dest, mode);
438  finish_computed_gotos(dest);
441 }
442 
444  const codet &code,
446  goto_programt &dest)
447 {
449  code, code.source_location(), type, nil_exprt(), {}));
450 }
451 
453  const code_labelt &code,
454  goto_programt &dest,
455  const irep_idt &mode)
456 {
457  // grab the label
458  const irep_idt &label=code.get_label();
459 
460  goto_programt tmp;
461 
462  // magic thread creation label.
463  // The "__CPROVER_ASYNC_" signals the start of a sequence of instructions
464  // that can be executed in parallel, i.e, a new thread.
465  if(label.starts_with(CPROVER_PREFIX "ASYNC_"))
466  {
467  // the body of the thread is expected to be
468  // in the operand.
470  to_code_label(code).code().is_not_nil(),
471  "code() in magic thread creation label is null");
472 
473  // replace the magic thread creation label with a
474  // thread block (START_THREAD...END_THREAD).
475  code_blockt thread_body;
476  thread_body.add(to_code_label(code).code());
477  thread_body.add_source_location()=code.source_location();
478  generate_thread_block(thread_body, dest, mode);
479  }
480  else
481  {
482  convert(to_code_label(code).code(), tmp, mode);
483 
484  goto_programt::targett target=tmp.instructions.begin();
485  dest.destructive_append(tmp);
486 
487  targets.labels.insert(
488  {label, {target, targets.scope_stack.get_current_node()}});
489  target->labels.push_front(label);
490  }
491 }
492 
494  const codet &,
495  goto_programt &)
496 {
497  // ignore for now
498 }
499 
501  const code_switch_caset &code,
502  goto_programt &dest,
503  const irep_idt &mode)
504 {
505  goto_programt tmp;
506  convert(code.code(), tmp, mode);
507 
508  goto_programt::targett target=tmp.instructions.begin();
509  dest.destructive_append(tmp);
510 
511  // is a default target given?
512 
513  if(code.is_default())
514  targets.set_default(target);
515  else
516  {
517  // cases?
518 
519  cases_mapt::iterator cases_entry=targets.cases_map.find(target);
520  if(cases_entry==targets.cases_map.end())
521  {
522  targets.cases.push_back(std::make_pair(target, caset()));
523  cases_entry=targets.cases_map.insert(std::make_pair(
524  target, --targets.cases.end())).first;
525  }
526 
527  exprt::operandst &case_op_dest=cases_entry->second->second;
528  case_op_dest.push_back(code.case_op());
529  // make sure we have a source location in the case operand as otherwise we
530  // end up with a GOTO instruction without a source location
532  case_op_dest.back().source_location().is_not_nil(),
533  "case operand should have a source location",
534  case_op_dest.back().pretty(),
535  code.pretty());
536  }
537 }
538 
540  const code_gcc_switch_case_ranget &code,
541  goto_programt &dest,
542  const irep_idt &mode)
543 {
544  const auto lb = numeric_cast<mp_integer>(code.lower());
545  const auto ub = numeric_cast<mp_integer>(code.upper());
546 
548  lb.has_value() && ub.has_value(),
549  "GCC's switch-case-range statement requires constant bounds",
550  code.find_source_location());
551 
552  if(*lb > *ub)
553  {
555  warning() << "GCC's switch-case-range statement with empty case range"
556  << eom;
557  }
558 
559  goto_programt tmp;
560  convert(code.code(), tmp, mode);
561 
562  goto_programt::targett target = tmp.instructions.begin();
563  dest.destructive_append(tmp);
564 
565  cases_mapt::iterator cases_entry = targets.cases_map.find(target);
566  if(cases_entry == targets.cases_map.end())
567  {
568  targets.cases.push_back({target, caset()});
569  cases_entry =
570  targets.cases_map.insert({target, --targets.cases.end()}).first;
571  }
572 
573  // create a skeleton for case_guard
574  cases_entry->second->second.push_back(
576  binary_relation_exprt{nil_exprt{}, ID_le, code.upper()}});
577 }
578 
581  const codet &code,
582  goto_programt &dest,
583  const irep_idt &mode)
584 {
585  const irep_idt &statement=code.get_statement();
586 
587  if(statement==ID_block)
588  convert_block(to_code_block(code), dest, mode);
589  else if(statement==ID_decl)
590  convert_frontend_decl(to_code_frontend_decl(code), dest, mode);
591  else if(statement==ID_decl_type)
592  convert_decl_type(code, dest);
593  else if(statement==ID_expression)
594  convert_expression(to_code_expression(code), dest, mode);
595  else if(statement==ID_assign)
596  convert_assign(to_code_assign(code), dest, mode);
597  else if(statement==ID_assert)
598  convert_assert(to_code_assert(code), dest, mode);
599  else if(statement==ID_assume)
600  convert_assume(to_code_assume(code), dest, mode);
601  else if(statement==ID_function_call)
602  convert_function_call(to_code_function_call(code), dest, mode);
603  else if(statement==ID_label)
604  convert_label(to_code_label(code), dest, mode);
605  else if(statement==ID_gcc_local_label)
606  convert_gcc_local_label(code, dest);
607  else if(statement==ID_switch_case)
608  convert_switch_case(to_code_switch_case(code), dest, mode);
609  else if(statement==ID_gcc_switch_case_range)
611  to_code_gcc_switch_case_range(code), dest, mode);
612  else if(statement==ID_for)
613  convert_for(to_code_for(code), dest, mode);
614  else if(statement==ID_while)
615  convert_while(to_code_while(code), dest, mode);
616  else if(statement==ID_dowhile)
617  convert_dowhile(to_code_dowhile(code), dest, mode);
618  else if(statement==ID_switch)
619  convert_switch(to_code_switch(code), dest, mode);
620  else if(statement==ID_break)
621  convert_break(to_code_break(code), dest, mode);
622  else if(statement==ID_return)
623  convert_return(to_code_frontend_return(code), dest, mode);
624  else if(statement==ID_continue)
625  convert_continue(to_code_continue(code), dest, mode);
626  else if(statement==ID_goto)
627  convert_goto(to_code_goto(code), dest);
628  else if(statement==ID_gcc_computed_goto)
629  convert_gcc_computed_goto(code, dest);
630  else if(statement==ID_skip)
631  convert_skip(code, dest);
632  else if(statement==ID_ifthenelse)
633  convert_ifthenelse(to_code_ifthenelse(code), dest, mode);
634  else if(statement==ID_start_thread)
635  convert_start_thread(code, dest);
636  else if(statement==ID_end_thread)
637  convert_end_thread(code, dest);
638  else if(statement==ID_atomic_begin)
639  convert_atomic_begin(code, dest);
640  else if(statement==ID_atomic_end)
641  convert_atomic_end(code, dest);
642  else if(statement==ID_cpp_delete ||
643  statement=="cpp_delete[]")
644  convert_cpp_delete(code, dest);
645  else if(statement==ID_msc_try_except)
646  convert_msc_try_except(code, dest, mode);
647  else if(statement==ID_msc_try_finally)
648  convert_msc_try_finally(code, dest, mode);
649  else if(statement==ID_msc_leave)
650  convert_msc_leave(code, dest, mode);
651  else if(statement==ID_try_catch) // C++ try/catch
652  convert_try_catch(code, dest, mode);
653  else if(statement==ID_CPROVER_try_catch) // CPROVER-homemade
654  convert_CPROVER_try_catch(code, dest, mode);
655  else if(statement==ID_CPROVER_throw) // CPROVER-homemade
656  convert_CPROVER_throw(code, dest, mode);
657  else if(statement==ID_CPROVER_try_finally)
658  convert_CPROVER_try_finally(code, dest, mode);
659  else if(statement==ID_asm)
660  convert_asm(to_code_asm(code), dest);
661  else if(statement==ID_static_assert)
662  {
663  PRECONDITION(code.operands().size() == 2);
664  exprt assertion =
666  simplify(assertion, ns);
668  !assertion.is_false(),
669  "static assertion " + id2string(get_string_constant(code.op1())),
670  code.op0().find_source_location());
671  }
672  else if(statement==ID_dead)
673  copy(code, DEAD, dest);
674  else if(statement==ID_decl_block)
675  {
676  for(const auto &op : code.operands())
677  convert(to_code(op), dest, mode);
678  }
679  else if(statement==ID_push_catch ||
680  statement==ID_pop_catch ||
681  statement==ID_exception_landingpad)
682  copy(code, CATCH, dest);
683  else
684  copy(code, OTHER, dest);
685 
686  // make sure dest is never empty
687  if(dest.instructions.empty())
688  {
690  }
691 }
692 
694  const code_blockt &code,
695  goto_programt &dest,
696  const irep_idt &mode)
697 {
698  const source_locationt &end_location=code.end_location();
699 
700  // this saves the index of the destructor stack
702 
703  // now convert block
704  for(const auto &b_code : code.statements())
705  convert(b_code, dest, mode);
706 
707  // see if we need to do any destructors -- may have been processed
708  // in a prior break/continue/return already, don't create dead code
709  if(
710  !dest.empty() && dest.instructions.back().is_goto() &&
711  dest.instructions.back().condition().is_true())
712  {
713  // don't do destructors when we are unreachable
714  }
715  else
716  unwind_destructor_stack(end_location, dest, mode, old_stack_top);
717 
718  // Set the current node of our destructor stack back to before the block.
719  targets.scope_stack.set_current_node(old_stack_top);
720 }
721 
723  const code_expressiont &code,
724  goto_programt &dest,
725  const irep_idt &mode)
726 {
727  exprt expr = code.expression();
728 
729  if(expr.id()==ID_if)
730  {
731  // We do a special treatment for c?t:f
732  // by compiling to if(c) t; else f;
733  const if_exprt &if_expr=to_if_expr(expr);
734  code_ifthenelset tmp_code(
735  if_expr.cond(),
736  code_expressiont(if_expr.true_case()),
737  code_expressiont(if_expr.false_case()));
738  tmp_code.add_source_location()=expr.source_location();
739  tmp_code.then_case().add_source_location()=expr.source_location();
740  tmp_code.else_case().add_source_location()=expr.source_location();
741  convert_ifthenelse(tmp_code, dest, mode);
742  }
743  else
744  {
745  clean_expr(expr, dest, mode, false); // result _not_ used
746 
747  // Any residual expression?
748  // We keep it to add checks later.
749  if(expr.is_not_nil())
750  {
751  codet tmp=code;
752  tmp.op0()=expr;
754  copy(tmp, OTHER, dest);
755  }
756  }
757 }
758 
760  const code_frontend_declt &code,
761  goto_programt &dest,
762  const irep_idt &mode)
763 {
764  const irep_idt &identifier = code.get_identifier();
765 
766  const symbolt &symbol = ns.lookup(identifier);
767 
768  if(symbol.is_static_lifetime ||
769  symbol.type.id()==ID_code)
770  return; // this is a SKIP!
771 
772  const goto_programt::targett declaration_iterator = [&]() {
773  if(code.operands().size() == 1)
774  {
775  copy(code, DECL, dest);
776  return std::prev(dest.instructions.end());
777  }
778 
779  exprt initializer = code.op1();
780 
781  codet tmp=code;
782  tmp.operands().resize(1);
783  // hide this declaration-without-initializer step in the goto trace
785 
786  // Break up into decl and assignment.
787  // Decl must be visible before initializer.
788  copy(tmp, DECL, dest);
789  const auto declaration_iterator = std::prev(dest.instructions.end());
790 
791  auto initializer_location = initializer.find_source_location();
792  clean_expr(initializer, dest, mode);
793 
794  if(initializer.is_not_nil())
795  {
796  code_assignt assign(code.op0(), initializer);
797  assign.add_source_location() = initializer_location;
798 
799  convert_assign(assign, dest, mode);
800  }
801 
802  return declaration_iterator;
803  }();
804 
805  // now create a 'dead' instruction -- will be added after the
806  // destructor created below as unwind_destructor_stack pops off the
807  // top of the destructor stack
808  const symbol_exprt symbol_expr(symbol.name, symbol.type);
809 
810  {
811  code_deadt code_dead(symbol_expr);
812 
813  targets.scope_stack.add(code_dead, {declaration_iterator});
814  }
815 
816  // do destructor
817  code_function_callt destructor=get_destructor(ns, symbol.type);
818 
819  if(destructor.is_not_nil())
820  {
821  // add "this"
822  address_of_exprt this_expr(symbol_expr, pointer_type(symbol.type));
823  destructor.arguments().push_back(this_expr);
824 
825  targets.scope_stack.add(destructor, {});
826  }
827 }
828 
830  const codet &,
831  goto_programt &)
832 {
833  // we remove these
834 }
835 
837  const code_assignt &code,
838  goto_programt &dest,
839  const irep_idt &mode)
840 {
841  exprt lhs=code.lhs(),
842  rhs=code.rhs();
843 
844  clean_expr(lhs, dest, mode);
845 
846  if(rhs.id()==ID_side_effect &&
847  rhs.get(ID_statement)==ID_function_call)
848  {
849  const auto &rhs_function_call = to_side_effect_expr_function_call(rhs);
850 
852  rhs.operands().size() == 2,
853  "function_call sideeffect takes two operands",
854  rhs.find_source_location());
855 
856  Forall_operands(it, rhs)
857  clean_expr(*it, dest, mode);
858 
860  lhs,
861  rhs_function_call.function(),
862  rhs_function_call.arguments(),
863  dest,
864  mode);
865  }
866  else if(rhs.id()==ID_side_effect &&
867  (rhs.get(ID_statement)==ID_cpp_new ||
868  rhs.get(ID_statement)==ID_cpp_new_array))
869  {
870  Forall_operands(it, rhs)
871  clean_expr(*it, dest, mode);
872 
873  // TODO: This should be done in a separate pass
874  do_cpp_new(lhs, to_side_effect_expr(rhs), dest);
875  }
876  else if(
877  rhs.id() == ID_side_effect &&
878  (rhs.get(ID_statement) == ID_assign ||
879  rhs.get(ID_statement) == ID_postincrement ||
880  rhs.get(ID_statement) == ID_preincrement ||
881  rhs.get(ID_statement) == ID_statement_expression ||
882  rhs.get(ID_statement) == ID_gcc_conditional_expression))
883  {
884  // handle above side effects
885  clean_expr(rhs, dest, mode);
886 
887  code_assignt new_assign(code);
888  new_assign.lhs() = lhs;
889  new_assign.rhs() = rhs;
890 
891  copy(new_assign, ASSIGN, dest);
892  }
893  else if(rhs.id() == ID_side_effect)
894  {
895  // preserve side effects that will be handled at later stages,
896  // such as allocate, new operators of other languages, e.g. java, etc
897  Forall_operands(it, rhs)
898  clean_expr(*it, dest, mode);
899 
900  code_assignt new_assign(code);
901  new_assign.lhs()=lhs;
902  new_assign.rhs()=rhs;
903 
904  copy(new_assign, ASSIGN, dest);
905  }
906  else
907  {
908  // do everything else
909  clean_expr(rhs, dest, mode);
910 
911  code_assignt new_assign(code);
912  new_assign.lhs()=lhs;
913  new_assign.rhs()=rhs;
914 
915  copy(new_assign, ASSIGN, dest);
916  }
917 }
918 
920  const codet &code,
921  goto_programt &dest)
922 {
924  code.operands().size() == 1,
925  "cpp_delete statement takes one operand",
926  code.find_source_location());
927 
928  exprt tmp_op=code.op0();
929 
930  clean_expr(tmp_op, dest, ID_cpp);
931 
932  // we call the destructor, and then free
933  const exprt &destructor=
934  static_cast<const exprt &>(code.find(ID_destructor));
935 
936  irep_idt delete_identifier;
937 
938  if(code.get_statement()==ID_cpp_delete_array)
939  delete_identifier="__delete_array";
940  else if(code.get_statement()==ID_cpp_delete)
941  delete_identifier="__delete";
942  else
943  UNREACHABLE;
944 
945  if(destructor.is_not_nil())
946  {
947  if(code.get_statement()==ID_cpp_delete_array)
948  {
949  // build loop
950  }
951  else if(code.get_statement()==ID_cpp_delete)
952  {
953  // just one object
954  const dereference_exprt deref_op(tmp_op);
955 
956  codet tmp_code=to_code(destructor);
957  replace_new_object(deref_op, tmp_code);
958  convert(tmp_code, dest, ID_cpp);
959  }
960  else
961  UNREACHABLE;
962  }
963 
964  // now do "free"
965  exprt delete_symbol=ns.lookup(delete_identifier).symbol_expr();
966 
968  to_code_type(delete_symbol.type()).parameters().size() == 1,
969  "delete statement takes 1 parameter");
970 
971  typet arg_type=
972  to_code_type(delete_symbol.type()).parameters().front().type();
973 
974  code_function_callt delete_call(
975  delete_symbol, {typecast_exprt(tmp_op, arg_type)});
976  delete_call.add_source_location()=code.source_location();
977 
978  convert(delete_call, dest, ID_cpp);
979 }
980 
982  const code_assertt &code,
983  goto_programt &dest,
984  const irep_idt &mode)
985 {
986  exprt cond=code.assertion();
987 
988  clean_expr(cond, dest, mode);
989 
990  source_locationt annotated_location = code.source_location();
991  annotated_location.set("user-provided", true);
992  dest.add(goto_programt::make_assertion(cond, annotated_location));
993 }
994 
996  const codet &code,
997  goto_programt &dest)
998 {
1000  code, code.source_location(), SKIP, nil_exprt(), {}));
1001 }
1002 
1004  const code_assumet &code,
1005  goto_programt &dest,
1006  const irep_idt &mode)
1007 {
1008  exprt op=code.assumption();
1009 
1010  clean_expr(op, dest, mode);
1011 
1013 }
1014 
1016  const codet &code,
1018  const irep_idt &mode)
1019 {
1020  auto assigns = static_cast<const unary_exprt &>(code.find(ID_C_spec_assigns));
1021  if(assigns.is_not_nil())
1022  {
1023  PRECONDITION(loop->is_goto());
1024  loop->condition_nonconst().add(ID_C_spec_assigns).swap(assigns.op());
1025  }
1026 
1027  auto invariant =
1028  static_cast<const exprt &>(code.find(ID_C_spec_loop_invariant));
1029  if(!invariant.is_nil())
1030  {
1031  if(has_subexpr(invariant, ID_side_effect))
1032  {
1034  "Loop invariant is not side-effect free.", code.find_source_location());
1035  }
1036 
1037  PRECONDITION(loop->is_goto());
1038  loop->condition_nonconst().add(ID_C_spec_loop_invariant).swap(invariant);
1039  }
1040 
1041  auto decreases_clause =
1042  static_cast<const exprt &>(code.find(ID_C_spec_decreases));
1043  if(!decreases_clause.is_nil())
1044  {
1045  if(has_subexpr(decreases_clause, ID_side_effect))
1046  {
1048  "Decreases clause is not side-effect free.",
1049  code.find_source_location());
1050  }
1051 
1052  PRECONDITION(loop->is_goto());
1053  loop->condition_nonconst().add(ID_C_spec_decreases).swap(decreases_clause);
1054  }
1055 }
1056 
1058  const code_fort &code,
1059  goto_programt &dest,
1060  const irep_idt &mode)
1061 {
1062  // turn for(A; c; B) { P } into
1063  // A; while(c) { P; B; }
1064  //-----------------------------
1065  // A;
1066  // u: sideeffects in c
1067  // v: if(!c) goto z;
1068  // w: P;
1069  // x: B; <-- continue target
1070  // y: goto u;
1071  // z: ; <-- break target
1072 
1073  // A;
1074  if(code.init().is_not_nil())
1075  convert(to_code(code.init()), dest, mode);
1076 
1077  exprt cond=code.cond();
1078 
1079  goto_programt sideeffects;
1080  clean_expr(cond, sideeffects, mode);
1081 
1082  // save break/continue targets
1083  break_continue_targetst old_targets(targets);
1084 
1085  // do the u label
1086  goto_programt::targett u=sideeffects.instructions.begin();
1087 
1088  // do the v label
1089  goto_programt tmp_v;
1091 
1092  // do the z label
1093  goto_programt tmp_z;
1096 
1097  // do the x label
1098  goto_programt tmp_x;
1099 
1100  if(code.iter().is_nil())
1101  {
1103  }
1104  else
1105  {
1106  exprt tmp_B=code.iter();
1107 
1108  clean_expr(tmp_B, tmp_x, mode, false);
1109 
1110  if(tmp_x.instructions.empty())
1112  }
1113 
1114  // optimize the v label
1115  if(sideeffects.instructions.empty())
1116  u=v;
1117 
1118  // set the targets
1119  targets.set_break(z);
1120  targets.set_continue(tmp_x.instructions.begin());
1121 
1122  // v: if(!c) goto z;
1123  *v =
1125 
1126  // do the w label
1127  goto_programt tmp_w;
1128  convert(code.body(), tmp_w, mode);
1129 
1130  // y: goto u;
1131  goto_programt tmp_y;
1132  goto_programt::targett y = tmp_y.add(
1134 
1135  // assigns clause, loop invariant and decreases clause
1136  convert_loop_contracts(code, y, mode);
1137 
1138  dest.destructive_append(sideeffects);
1139  dest.destructive_append(tmp_v);
1140  dest.destructive_append(tmp_w);
1141  dest.destructive_append(tmp_x);
1142  dest.destructive_append(tmp_y);
1143  dest.destructive_append(tmp_z);
1144 
1145  // restore break/continue
1146  old_targets.restore(targets);
1147 }
1148 
1150  const code_whilet &code,
1151  goto_programt &dest,
1152  const irep_idt &mode)
1153 {
1154  const exprt &cond=code.cond();
1155  const source_locationt &source_location=code.source_location();
1156 
1157  // while(c) P;
1158  //--------------------
1159  // v: sideeffects in c
1160  // if(!c) goto z;
1161  // x: P;
1162  // y: goto v; <-- continue target
1163  // z: ; <-- break target
1164 
1165  // save break/continue targets
1166  break_continue_targetst old_targets(targets);
1167 
1168  // do the z label
1169  goto_programt tmp_z;
1171  tmp_z.add(goto_programt::make_skip(source_location));
1172 
1173  goto_programt tmp_branch;
1175  boolean_negate(cond), z, source_location, tmp_branch, mode);
1176 
1177  // do the v label
1178  goto_programt::targett v=tmp_branch.instructions.begin();
1179 
1180  // y: goto v;
1181  goto_programt tmp_y;
1182  goto_programt::targett y = tmp_y.add(
1184 
1185  // set the targets
1186  targets.set_break(z);
1187  targets.set_continue(y);
1188 
1189  // do the x label
1190  goto_programt tmp_x;
1191  convert(code.body(), tmp_x, mode);
1192 
1193  // assigns clause, loop invariant and decreases clause
1194  convert_loop_contracts(code, y, mode);
1195 
1196  dest.destructive_append(tmp_branch);
1197  dest.destructive_append(tmp_x);
1198  dest.destructive_append(tmp_y);
1199  dest.destructive_append(tmp_z);
1200 
1201  // restore break/continue
1202  old_targets.restore(targets);
1203 }
1204 
1206  const code_dowhilet &code,
1207  goto_programt &dest,
1208  const irep_idt &mode)
1209 {
1211  code.operands().size() == 2,
1212  "dowhile takes two operands",
1213  code.find_source_location());
1214 
1215  // save source location
1216  source_locationt condition_location=code.cond().find_source_location();
1217 
1218  exprt cond=code.cond();
1219 
1220  goto_programt sideeffects;
1221  clean_expr(cond, sideeffects, mode);
1222 
1223  // do P while(c);
1224  //--------------------
1225  // w: P;
1226  // x: sideeffects in c <-- continue target
1227  // y: if(c) goto w;
1228  // z: ; <-- break target
1229 
1230  // save break/continue targets
1231  break_continue_targetst old_targets(targets);
1232 
1233  // do the y label
1234  goto_programt tmp_y;
1236  tmp_y.add(goto_programt::make_incomplete_goto(cond, condition_location));
1237 
1238  // do the z label
1239  goto_programt tmp_z;
1242 
1243  // do the x label
1245  if(sideeffects.instructions.empty())
1246  x=y;
1247  else
1248  x=sideeffects.instructions.begin();
1249 
1250  // set the targets
1251  targets.set_break(z);
1252  targets.set_continue(x);
1253 
1254  // do the w label
1255  goto_programt tmp_w;
1256  convert(code.body(), tmp_w, mode);
1257  goto_programt::targett w=tmp_w.instructions.begin();
1258 
1259  // y: if(c) goto w;
1260  y->complete_goto(w);
1261 
1262  // assigns_clause, loop invariant and decreases clause
1263  convert_loop_contracts(code, y, mode);
1264 
1265  dest.destructive_append(tmp_w);
1266  dest.destructive_append(sideeffects);
1267  dest.destructive_append(tmp_y);
1268  dest.destructive_append(tmp_z);
1269 
1270  // restore break/continue targets
1271  old_targets.restore(targets);
1272 }
1273 
1275  const exprt &value,
1276  const exprt::operandst &case_op)
1277 {
1278  PRECONDITION(!case_op.empty());
1279 
1280  exprt::operandst disjuncts;
1281  disjuncts.reserve(case_op.size());
1282 
1283  for(const auto &op : case_op)
1284  {
1285  // could be a skeleton generated by convert_gcc_switch_case_range
1286  if(op.id() == ID_and)
1287  {
1288  const binary_exprt &and_expr = to_binary_expr(op);
1289  PRECONDITION(to_binary_expr(and_expr.op0()).op1().is_nil());
1290  PRECONDITION(to_binary_expr(and_expr.op1()).op0().is_nil());
1291  binary_exprt skeleton = and_expr;
1292  to_binary_expr(skeleton.op0()).op1() = value;
1293  to_binary_expr(skeleton.op1()).op0() = value;
1294  disjuncts.push_back(skeleton);
1295  }
1296  else
1297  disjuncts.push_back(equal_exprt(value, op));
1298  }
1299 
1300  return disjunction(disjuncts);
1301 }
1302 
1304  const code_switcht &code,
1305  goto_programt &dest,
1306  const irep_idt &mode)
1307 {
1308  // switch(v) {
1309  // case x: Px;
1310  // case y: Py;
1311  // ...
1312  // default: Pd;
1313  // }
1314  // --------------------
1315  // location
1316  // x: if(v==x) goto X;
1317  // y: if(v==y) goto Y;
1318  // goto d;
1319  // X: Px;
1320  // Y: Py;
1321  // d: Pd;
1322  // z: ;
1323 
1324  // we first add a 'location' node for the switch statement,
1325  // which would otherwise not be recorded
1327 
1328  // get the location of the end of the body, but
1329  // default to location of switch, if none
1330  source_locationt body_end_location=
1331  code.body().get_statement()==ID_block?
1332  to_code_block(code.body()).end_location():
1333  code.source_location();
1334 
1335  // do the value we switch over
1336  exprt argument=code.value();
1337 
1338  goto_programt sideeffects;
1339  clean_expr(argument, sideeffects, mode);
1340 
1341  // Avoid potential performance penalties caused by evaluating the value
1342  // multiple times (as the below chain-of-ifs does). "needs_cleaning" isn't
1343  // necessarily the right check here, and we may need to introduce a different
1344  // way of identifying the class of non-trivial expressions that warrant
1345  // introduction of a temporary.
1346  if(needs_cleaning(argument))
1347  {
1348  symbolt &new_symbol = new_tmp_symbol(
1349  argument.type(),
1350  "switch_value",
1351  sideeffects,
1352  code.source_location(),
1353  mode);
1354 
1355  code_assignt copy_value{
1356  new_symbol.symbol_expr(), argument, code.source_location()};
1357  convert(copy_value, sideeffects, mode);
1358 
1359  argument = new_symbol.symbol_expr();
1360  }
1361 
1362  // save break/default/cases targets
1363  break_switch_targetst old_targets(targets);
1364 
1365  // do the z label
1366  goto_programt tmp_z;
1368  tmp_z.add(goto_programt::make_skip(body_end_location));
1369 
1370  // set the new targets -- continue stays as is
1371  targets.set_break(z);
1372  targets.set_default(z);
1373  targets.cases.clear();
1374  targets.cases_map.clear();
1375 
1376  goto_programt tmp;
1377  convert(code.body(), tmp, mode);
1378 
1379  goto_programt tmp_cases;
1380 
1381  // The case number represents which case this corresponds to in the sequence
1382  // of case statements.
1383  //
1384  // switch (x)
1385  // {
1386  // case 2: // case_number 1
1387  // ...;
1388  // case 3: // case_number 2
1389  // ...;
1390  // case 10: // case_number 3
1391  // ...;
1392  // }
1393  size_t case_number=1;
1394  for(auto &case_pair : targets.cases)
1395  {
1396  const caset &case_ops=case_pair.second;
1397 
1398  if (case_ops.empty())
1399  continue;
1400 
1401  exprt guard_expr=case_guard(argument, case_ops);
1402 
1403  source_locationt source_location=case_ops.front().find_source_location();
1404  source_location.set_case_number(std::to_string(case_number));
1405  case_number++;
1406  guard_expr.add_source_location()=source_location;
1407 
1408  tmp_cases.add(goto_programt::make_goto(
1409  case_pair.first, std::move(guard_expr), source_location));
1410  }
1411 
1412  tmp_cases.add(goto_programt::make_goto(
1413  targets.default_target, targets.default_target->source_location()));
1414 
1415  dest.destructive_append(sideeffects);
1416  dest.destructive_append(tmp_cases);
1417  dest.destructive_append(tmp);
1418  dest.destructive_append(tmp_z);
1419 
1420  // restore old targets
1421  old_targets.restore(targets);
1422 }
1423 
1425  const code_breakt &code,
1426  goto_programt &dest,
1427  const irep_idt &mode)
1428 {
1430  targets.break_set, "break without target", code.find_source_location());
1431 
1432  // need to process destructor stack
1434  code.source_location(), dest, mode, targets.break_stack_node);
1435 
1436  // add goto
1437  dest.add(
1439 }
1440 
1442  const code_frontend_returnt &code,
1443  goto_programt &dest,
1444  const irep_idt &mode)
1445 {
1446  if(!targets.return_set)
1447  {
1449  "return without target", code.find_source_location());
1450  }
1451 
1453  code.operands().empty() || code.operands().size() == 1,
1454  "return takes none or one operand",
1455  code.find_source_location());
1456 
1457  code_frontend_returnt new_code(code);
1458 
1459  if(new_code.has_return_value())
1460  {
1461  bool result_is_used=
1462  new_code.return_value().type().id()!=ID_empty;
1463 
1464  goto_programt sideeffects;
1465  clean_expr(new_code.return_value(), sideeffects, mode, result_is_used);
1466  dest.destructive_append(sideeffects);
1467 
1468  // remove void-typed return value
1469  if(!result_is_used)
1470  new_code.return_value().make_nil();
1471  }
1472 
1474  {
1476  new_code.has_return_value(),
1477  "function must return value",
1478  new_code.find_source_location());
1479 
1480  // Now add a 'set return value' instruction to set the return value.
1482  new_code.return_value(), new_code.source_location()));
1483  }
1484  else
1485  {
1487  !new_code.has_return_value() ||
1488  new_code.return_value().type().id() == ID_empty,
1489  "function must not return value",
1490  code.find_source_location());
1491  }
1492 
1493  // Need to process _entire_ destructor stack.
1494  unwind_destructor_stack(code.source_location(), dest, mode);
1495 
1496  // add goto to end-of-function
1498  targets.return_target, new_code.source_location()));
1499 }
1500 
1502  const code_continuet &code,
1503  goto_programt &dest,
1504  const irep_idt &mode)
1505 {
1508  "continue without target",
1509  code.find_source_location());
1510 
1511  // need to process destructor stack
1513  code.source_location(), dest, mode, targets.continue_stack_node);
1514 
1515  // add goto
1516  dest.add(
1518 }
1519 
1521 {
1522  // this instruction will be completed during post-processing
1525 
1526  // remember it to do the target later
1527  targets.gotos.emplace_back(t, targets.scope_stack.get_current_node());
1528 }
1529 
1531  const codet &code,
1532  goto_programt &dest)
1533 {
1534  // this instruction will turn into OTHER during post-processing
1536  code, code.source_location(), NO_INSTRUCTION_TYPE, nil_exprt(), {}));
1537 
1538  // remember it to do this later
1539  targets.computed_gotos.push_back(t);
1540 }
1541 
1543  const codet &code,
1544  goto_programt &dest)
1545 {
1547  code, code.source_location(), START_THREAD, nil_exprt(), {}));
1548 
1549  // remember it to do target later
1550  targets.gotos.emplace_back(
1551  start_thread, targets.scope_stack.get_current_node());
1552 }
1553 
1555  const codet &code,
1556  goto_programt &dest)
1557 {
1559  code.operands().empty(),
1560  "end_thread expects no operands",
1561  code.find_source_location());
1562 
1563  copy(code, END_THREAD, dest);
1564 }
1565 
1567  const codet &code,
1568  goto_programt &dest)
1569 {
1571  code.operands().empty(),
1572  "atomic_begin expects no operands",
1573  code.find_source_location());
1574 
1575  copy(code, ATOMIC_BEGIN, dest);
1576 }
1577 
1579  const codet &code,
1580  goto_programt &dest)
1581 {
1583  code.operands().empty(),
1584  ": atomic_end expects no operands",
1585  code.find_source_location());
1586 
1587  copy(code, ATOMIC_END, dest);
1588 }
1589 
1591  const code_ifthenelset &code,
1592  goto_programt &dest,
1593  const irep_idt &mode)
1594 {
1595  DATA_INVARIANT(code.then_case().is_not_nil(), "cannot accept an empty body");
1596 
1597  bool has_else=
1598  !code.else_case().is_nil();
1599 
1600  const source_locationt &source_location=code.source_location();
1601 
1602  // We do a bit of special treatment for && in the condition
1603  // in case cleaning would be needed otherwise.
1604  if(
1605  code.cond().id() == ID_and && code.cond().operands().size() == 2 &&
1606  (needs_cleaning(to_binary_expr(code.cond()).op0()) ||
1607  needs_cleaning(to_binary_expr(code.cond()).op1())) &&
1608  !has_else)
1609  {
1610  // if(a && b) XX --> if(a) if(b) XX
1611  code_ifthenelset new_if1(
1612  to_binary_expr(code.cond()).op1(), code.then_case());
1613  new_if1.add_source_location() = source_location;
1614  code_ifthenelset new_if0(
1615  to_binary_expr(code.cond()).op0(), std::move(new_if1));
1616  new_if0.add_source_location() = source_location;
1617  return convert_ifthenelse(new_if0, dest, mode);
1618  }
1619 
1620  // convert 'then'-branch
1621  goto_programt tmp_then;
1622  convert(code.then_case(), tmp_then, mode);
1623  source_locationt then_end_location =
1624  code.then_case().get_statement() == ID_block
1626  : code.then_case().source_location();
1627 
1628  goto_programt tmp_else;
1629  source_locationt else_end_location;
1630 
1631  if(has_else)
1632  {
1633  convert(code.else_case(), tmp_else, mode);
1634  else_end_location = code.else_case().get_statement() == ID_block
1636  : code.else_case().source_location();
1637  }
1638 
1639  exprt tmp_guard=code.cond();
1640  clean_expr(tmp_guard, dest, mode);
1641 
1643  tmp_guard,
1644  source_location,
1645  tmp_then,
1646  then_end_location,
1647  tmp_else,
1648  else_end_location,
1649  dest,
1650  mode);
1651 }
1652 
1654  const exprt &expr,
1655  const irep_idt &id,
1656  std::list<exprt> &dest)
1657 {
1658  if(expr.id()!=id)
1659  {
1660  dest.push_back(expr);
1661  }
1662  else
1663  {
1664  // left-to-right is important
1665  for(const auto &op : expr.operands())
1666  collect_operands(op, id, dest);
1667  }
1668 }
1669 
1673 static inline bool is_size_one(const goto_programt &g)
1674 {
1675  return (!g.instructions.empty()) &&
1676  ++g.instructions.begin()==g.instructions.end();
1677 }
1678 
1681  const exprt &guard,
1682  const source_locationt &source_location,
1683  goto_programt &true_case,
1684  const source_locationt &then_end_location,
1685  goto_programt &false_case,
1686  const source_locationt &else_end_location,
1687  goto_programt &dest,
1688  const irep_idt &mode)
1689 {
1690  if(is_empty(true_case) &&
1691  is_empty(false_case))
1692  {
1693  // hmpf. Useless branch.
1694  goto_programt tmp_z;
1696  dest.add(goto_programt::make_goto(z, guard, source_location));
1697  dest.destructive_append(tmp_z);
1698  return;
1699  }
1700 
1701  // do guarded assertions directly
1702  if(
1703  is_size_one(true_case) && true_case.instructions.back().is_assert() &&
1704  true_case.instructions.back().condition().is_false() &&
1705  true_case.instructions.back().labels.empty())
1706  {
1707  // The above conjunction deliberately excludes the instance
1708  // if(some) { label: assert(false); }
1709  true_case.instructions.back().condition_nonconst() = boolean_negate(guard);
1710  dest.destructive_append(true_case);
1711  true_case.instructions.clear();
1712  if(
1713  is_empty(false_case) ||
1714  (is_size_one(false_case) &&
1715  is_skip(false_case, false_case.instructions.begin())))
1716  return;
1717  }
1718 
1719  // similarly, do guarded assertions directly
1720  if(
1721  is_size_one(false_case) && false_case.instructions.back().is_assert() &&
1722  false_case.instructions.back().condition().is_false() &&
1723  false_case.instructions.back().labels.empty())
1724  {
1725  // The above conjunction deliberately excludes the instance
1726  // if(some) ... else { label: assert(false); }
1727  false_case.instructions.back().condition_nonconst() = guard;
1728  dest.destructive_append(false_case);
1729  false_case.instructions.clear();
1730  if(
1731  is_empty(true_case) ||
1732  (is_size_one(true_case) &&
1733  is_skip(true_case, true_case.instructions.begin())))
1734  return;
1735  }
1736 
1737  // a special case for C libraries that use
1738  // (void)((cond) || (assert(0),0))
1739  if(
1740  is_empty(false_case) && true_case.instructions.size() == 2 &&
1741  true_case.instructions.front().is_assert() &&
1742  true_case.instructions.front().condition().is_false() &&
1743  true_case.instructions.front().labels.empty() &&
1744  true_case.instructions.back().labels.empty())
1745  {
1746  true_case.instructions.front().condition_nonconst() = boolean_negate(guard);
1747  true_case.instructions.erase(--true_case.instructions.end());
1748  dest.destructive_append(true_case);
1749  true_case.instructions.clear();
1750 
1751  return;
1752  }
1753 
1754  // Flip around if no 'true' case code.
1755  if(is_empty(true_case))
1756  {
1757  return generate_ifthenelse(
1759  source_location,
1760  false_case,
1761  else_end_location,
1762  true_case,
1763  then_end_location,
1764  dest,
1765  mode);
1766  }
1767 
1768  bool has_else=!is_empty(false_case);
1769 
1770  // if(c) P;
1771  //--------------------
1772  // v: if(!c) goto z;
1773  // w: P;
1774  // z: ;
1775 
1776  // if(c) P; else Q;
1777  //--------------------
1778  // v: if(!c) goto y;
1779  // w: P;
1780  // x: goto z;
1781  // y: Q;
1782  // z: ;
1783 
1784  // do the x label
1785  goto_programt tmp_x;
1786  goto_programt::targett x = tmp_x.add(
1787  goto_programt::make_incomplete_goto(true_exprt(), then_end_location));
1788 
1789  // do the z label
1790  goto_programt tmp_z;
1791  goto_programt::targett z = tmp_z.add(
1792  goto_programt::make_skip(has_else ? else_end_location : then_end_location));
1793 
1794  // y: Q;
1795  goto_programt tmp_y;
1797  if(has_else)
1798  {
1799  tmp_y.swap(false_case);
1800  y=tmp_y.instructions.begin();
1801  }
1802 
1803  // v: if(!c) goto z/y;
1804  goto_programt tmp_v;
1806  boolean_negate(guard), has_else ? y : z, source_location, tmp_v, mode);
1807 
1808  // w: P;
1809  goto_programt tmp_w;
1810  tmp_w.swap(true_case);
1811 
1812  // x: goto z;
1813  CHECK_RETURN(!tmp_w.instructions.empty());
1814  x->complete_goto(z);
1815 
1816  dest.destructive_append(tmp_v);
1817  dest.destructive_append(tmp_w);
1818 
1819  // When the `then` branch of a balanced `if` condition ends with a `return` or
1820  // a `goto` statement, it is not necessary to add the `goto z` and `z:` goto
1821  // elements as they are never used.
1822  // This helps for example when using `--cover location` as such command are
1823  // marked unreachable, but are not part of the user-provided code to analyze.
1824  bool then_branch_returns = dest.instructions.rbegin()->is_goto();
1825 
1826  if(has_else)
1827  {
1828  // Don't add the `goto` at the end of the `then` branch if not needed
1829  if(!then_branch_returns)
1830  {
1831  dest.destructive_append(tmp_x);
1832  }
1833  dest.destructive_append(tmp_y);
1834  }
1835 
1836  // Don't add the `z` label at the end of the `if` when not needed.
1837  if(!has_else || !then_branch_returns)
1838  {
1839  dest.destructive_append(tmp_z);
1840  }
1841 }
1842 
1844 static bool has_and_or(const exprt &expr)
1845 {
1846  for(const auto &op : expr.operands())
1847  {
1848  if(has_and_or(op))
1849  return true;
1850  }
1851 
1852  if(expr.id()==ID_and || expr.id()==ID_or)
1853  return true;
1854 
1855  return false;
1856 }
1857 
1859  const exprt &guard,
1860  goto_programt::targett target_true,
1861  const source_locationt &source_location,
1862  goto_programt &dest,
1863  const irep_idt &mode)
1864 {
1866  {
1867  // if(guard) goto target;
1868  // becomes
1869  // if(guard) goto target; else goto next;
1870  // next: skip;
1871 
1872  goto_programt tmp;
1873  goto_programt::targett target_false =
1874  tmp.add(goto_programt::make_skip(source_location));
1875 
1877  guard, target_true, target_false, source_location, dest, mode);
1878 
1879  dest.destructive_append(tmp);
1880  }
1881  else
1882  {
1883  // simple branch
1884  exprt cond=guard;
1885  clean_expr(cond, dest, mode);
1886 
1887  dest.add(goto_programt::make_goto(target_true, cond, source_location));
1888  }
1889 }
1890 
1893  const exprt &guard,
1894  goto_programt::targett target_true,
1895  goto_programt::targett target_false,
1896  const source_locationt &source_location,
1897  goto_programt &dest,
1898  const irep_idt &mode)
1899 {
1900  if(guard.id()==ID_not)
1901  {
1902  // simply swap targets
1904  to_not_expr(guard).op(),
1905  target_false,
1906  target_true,
1907  source_location,
1908  dest,
1909  mode);
1910  return;
1911  }
1912 
1913  if(guard.id()==ID_and)
1914  {
1915  // turn
1916  // if(a && b) goto target_true; else goto target_false;
1917  // into
1918  // if(!a) goto target_false;
1919  // if(!b) goto target_false;
1920  // goto target_true;
1921 
1922  std::list<exprt> op;
1923  collect_operands(guard, guard.id(), op);
1924 
1925  for(const auto &expr : op)
1927  boolean_negate(expr), target_false, source_location, dest, mode);
1928 
1929  dest.add(goto_programt::make_goto(target_true, source_location));
1930 
1931  return;
1932  }
1933  else if(guard.id()==ID_or)
1934  {
1935  // turn
1936  // if(a || b) goto target_true; else goto target_false;
1937  // into
1938  // if(a) goto target_true;
1939  // if(b) goto target_true;
1940  // goto target_false;
1941 
1942  std::list<exprt> op;
1943  collect_operands(guard, guard.id(), op);
1944 
1945  // true branch(es)
1946  for(const auto &expr : op)
1948  expr, target_true, source_location, dest, mode);
1949 
1950  // false branch
1951  dest.add(goto_programt::make_goto(target_false, guard.source_location()));
1952 
1953  return;
1954  }
1955 
1956  exprt cond=guard;
1957  clean_expr(cond, dest, mode);
1958 
1959  // true branch
1960  dest.add(goto_programt::make_goto(target_true, cond, source_location));
1961 
1962  // false branch
1963  dest.add(goto_programt::make_goto(target_false, source_location));
1964 }
1965 
1967  const exprt &expr,
1968  irep_idt &value)
1969 {
1970  if(expr.id() == ID_typecast)
1971  return get_string_constant(to_typecast_expr(expr).op(), value);
1972 
1973  if(
1974  expr.id() == ID_address_of &&
1975  to_address_of_expr(expr).object().id() == ID_index)
1976  {
1977  exprt index_op =
1978  get_constant(to_index_expr(to_address_of_expr(expr).object()).array());
1979  simplify(index_op, ns);
1980 
1981  if(index_op.id()==ID_string_constant)
1982  {
1983  value = to_string_constant(index_op).value();
1984  return false;
1985  }
1986  else if(index_op.id()==ID_array)
1987  {
1988  std::string result;
1989  for(const auto &op : as_const(index_op).operands())
1990  {
1991  if(op.is_constant())
1992  {
1993  const auto i = numeric_cast<std::size_t>(op);
1994  if(!i.has_value())
1995  return true;
1996 
1997  if(i.value() != 0) // to skip terminating 0
1998  result += static_cast<char>(i.value());
1999  }
2000  }
2001 
2002  return value=result, false;
2003  }
2004  }
2005 
2006  if(expr.id()==ID_string_constant)
2007  {
2008  value = to_string_constant(expr).value();
2009  return false;
2010  }
2011 
2012  return true;
2013 }
2014 
2016 {
2017  irep_idt result;
2018 
2019  const bool res = get_string_constant(expr, result);
2021  !res,
2022  "expected string constant",
2023  expr.find_source_location(),
2024  expr.pretty());
2025 
2026  return result;
2027 }
2028 
2030 {
2031  if(expr.id()==ID_symbol)
2032  {
2033  const symbolt &symbol=
2034  ns.lookup(to_symbol_expr(expr));
2035 
2036  return symbol.value;
2037  }
2038  else if(expr.id()==ID_member)
2039  {
2040  auto tmp = to_member_expr(expr);
2041  tmp.compound() = get_constant(tmp.compound());
2042  return std::move(tmp);
2043  }
2044  else if(expr.id()==ID_index)
2045  {
2046  auto tmp = to_index_expr(expr);
2047  tmp.op0() = get_constant(tmp.op0());
2048  tmp.op1() = get_constant(tmp.op1());
2049  return std::move(tmp);
2050  }
2051  else
2052  return expr;
2053 }
2054 
2056  const typet &type,
2057  const std::string &suffix,
2058  goto_programt &dest,
2059  const source_locationt &source_location,
2060  const irep_idt &mode)
2061 {
2062  PRECONDITION(!mode.empty());
2063  symbolt &new_symbol = get_fresh_aux_symbol(
2064  type,
2066  "tmp_" + suffix,
2067  source_location,
2068  mode,
2069  symbol_table);
2070 
2071  code_frontend_declt decl(new_symbol.symbol_expr());
2072  decl.add_source_location()=source_location;
2073  convert_frontend_decl(decl, dest, mode);
2074 
2075  return new_symbol;
2076 }
2077 
2079  exprt &expr,
2080  const std::string &suffix,
2081  goto_programt &dest,
2082  const irep_idt &mode)
2083 {
2084  const source_locationt source_location=expr.find_source_location();
2085 
2086  symbolt &new_symbol =
2087  new_tmp_symbol(expr.type(), suffix, dest, source_location, mode);
2088 
2089  code_assignt assignment;
2090  assignment.lhs()=new_symbol.symbol_expr();
2091  assignment.rhs()=expr;
2092  assignment.add_source_location()=source_location;
2093 
2094  convert(assignment, dest, mode);
2095 
2096  expr=new_symbol.symbol_expr();
2097 }
2098 
2100  const codet &code,
2101  symbol_table_baset &symbol_table,
2102  goto_programt &dest,
2103  message_handlert &message_handler,
2104  const irep_idt &mode)
2105 {
2106  symbol_table_buildert symbol_table_builder =
2107  symbol_table_buildert::wrap(symbol_table);
2108  goto_convertt goto_convert(symbol_table_builder, message_handler);
2109  goto_convert.goto_convert(code, dest, mode);
2110 }
2111 
2113  symbol_table_baset &symbol_table,
2114  goto_programt &dest,
2115  message_handlert &message_handler)
2116 {
2117  // find main symbol
2118  const symbol_table_baset::symbolst::const_iterator s_it =
2119  symbol_table.symbols.find("main");
2120 
2122  s_it != symbol_table.symbols.end(), "failed to find main symbol");
2123 
2124  const symbolt &symbol=s_it->second;
2125 
2127  to_code(symbol.value), symbol_table, dest, message_handler, symbol.mode);
2128 }
2129 
2145  const code_blockt &thread_body,
2146  goto_programt &dest,
2147  const irep_idt &mode)
2148 {
2149  goto_programt preamble, body, postamble;
2150 
2152  convert(thread_body, body, mode);
2153 
2154  postamble.add(goto_programt::instructiont(
2155  static_cast<const codet &>(get_nil_irep()),
2156  thread_body.source_location(),
2157  END_THREAD,
2158  nil_exprt(),
2159  {}));
2161 
2163  static_cast<const codet &>(get_nil_irep()),
2164  thread_body.source_location(),
2165  START_THREAD,
2166  nil_exprt(),
2167  {c}));
2168  preamble.add(goto_programt::make_goto(z, thread_body.source_location()));
2169 
2170  dest.destructive_append(preamble);
2171  dest.destructive_append(body);
2172  dest.destructive_append(postamble);
2173 }
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.
Definition: pointer_expr.h:540
Result of an attempt to find ancestor information about two nodes.
Definition: scope_tree.h:25
std::size_t right_depth_below_common_ancestor
Definition: scope_tree.h:44
node_indext common_ancestor
Definition: scope_tree.h:42
Boolean AND.
Definition: std_expr.h:2120
A base class for binary expressions.
Definition: std_expr.h:638
exprt & op1()
Definition: expr.h:136
exprt & op0()
Definition: expr.h:133
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
source_locationt end_location() const
Definition: std_code.h:187
void add(const codet &code)
Definition: std_code.h:168
code_operandst & statements()
Definition: std_code.h:138
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 exprt & cond() const
Definition: std_code.h:679
const codet & body() const
Definition: std_code.h:689
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 & init() const
Definition: std_code.h:749
const exprt & iter() const
Definition: std_code.h:769
const exprt & cond() const
Definition: std_code.h:759
const codet & body() const
Definition: std_code.h:779
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
codet & code()
the statement to be executed when the case applies
Definition: std_code.h:1131
const exprt & lower() const
lower bound of range
Definition: std_code.h:1107
const exprt & upper() const
upper bound of range
Definition: std_code.h:1119
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 codet & then_case() const
Definition: std_code.h:488
const exprt & cond() const
Definition: std_code.h:478
const codet & else_case() const
Definition: std_code.h:498
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
exception_listt & exception_list()
Definition: std_code.h:1860
codet representation of a switch-case, i.e. a case statement within a switch.
Definition: std_code.h:1023
codet & code()
Definition: std_code.h:1050
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 exprt & value() const
Definition: std_code.h:555
const codet & body() const
Definition: std_code.h:565
const parameterst & parameters() const
Definition: std_types.h:699
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.
Definition: std_code_base.h:29
exprt & op1()
Definition: expr.h:136
exprt & op0()
Definition: expr.h:133
const irep_idt & get_statement() const
Definition: std_code_base.h:65
Operator to dereference a pointer.
Definition: pointer_expr.h:834
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:1361
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
source_locationt & add_source_location()
Definition: expr.h:236
const source_locationt & source_location() const
Definition: expr.h:231
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
The Boolean constant false.
Definition: std_expr.h:3064
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_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 clean_expr(exprt &expr, goto_programt &dest, const irep_idt &mode, bool result_is_used=true)
void convert_loop_contracts(const codet &code, goto_programt::targett loop, 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)
void build_declaration_hops(goto_programt &dest, std::unordered_map< irep_idt, symbolt, irep_id_hash > &label_flags, const build_declaration_hops_inputst &inputs)
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)
exprt::operandst caset
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 make_temp_symbol(exprt &expr, const std::string &suffix, goto_programt &, 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)
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.
Definition: goto_program.h:181
void complete_goto(targett _target)
Definition: goto_program.h:482
targetst targets
The list of successor instructions.
Definition: goto_program.h:414
const goto_instruction_codet & code() const
Get the code represented by this instruction.
Definition: goto_program.h:188
static const unsigned nil_target
Uniquely identify an invalid target or location.
Definition: goto_program.h:553
const source_locationt & source_location() const
Definition: goto_program.h:333
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
static instructiont make_assumption(const exprt &g, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:945
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:622
static instructiont make_set_return_value(exprt return_value, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:874
void insert_before_swap(targett target)
Insertion that preserves jumps to "target".
Definition: goto_program.h:643
void destructive_insert(const_targett target, goto_programt &p)
Inserts the given program p before target.
Definition: goto_program.h:730
instructionst::iterator targett
Definition: goto_program.h:614
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
Definition: goto_program.h:722
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())
Definition: goto_program.h:891
targett insert_after(const_targett target)
Insertion after the instruction pointed-to by the given instruction iterator target.
Definition: goto_program.h:708
static instructiont make_other(const goto_instruction_codet &_code, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:957
void swap(goto_programt &program)
Swap the goto program.
Definition: goto_program.h:814
static instructiont make_location(const source_locationt &l)
Definition: goto_program.h:901
targett add(instructiont &&instruction)
Adds a given instruction at the end.
Definition: goto_program.h:739
static instructiont make_goto(targett _target, const source_locationt &l=source_locationt::nil())
bool empty() const
Is the program empty?
Definition: goto_program.h:799
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:964
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:933
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:2370
exprt & true_case()
Definition: std_expr.h:2397
exprt & false_case()
Definition: std_expr.h:2407
exprt & cond()
Definition: std_expr.h:2387
Thrown when a goto program that's being processed is in an invalid format, for example passing the wr...
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
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:44
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:408
bool is_not_nil() const
Definition: irep.h:368
const irep_idt & id() const
Definition: irep.h:384
void make_nil()
Definition: irep.h:442
bool is_nil() const
Definition: irep.h:364
source_locationt source_location
Definition: message.h:247
mstreamt & warning() const
Definition: message.h:404
mstreamt & result() const
Definition: message.h:409
mstreamt & debug() const
Definition: message.h:429
static eomt eom
Definition: message.h:297
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
The NIL expression.
Definition: std_expr.h:3073
std::optional< declaration_statet > & get_declaration(node_indext index)
Fetches the declaration value for the passed-in node index.
Definition: scope_tree.cpp:31
void add(const codet &destructor, std::optional< goto_programt::targett > declaration)
Adds a destructor/declaration pair to the current stack, attaching it to the current node.
Definition: scope_tree.cpp:11
void descend_tree()
Walks the current node down to its child.
Definition: scope_tree.cpp:100
void set_current_node(std::optional< node_indext > val)
Sets the current node.
Definition: scope_tree.cpp:89
node_indext get_current_node() const
Gets the node that the next addition will be added to as a child.
Definition: scope_tree.cpp:109
const ancestry_resultt get_nearest_common_ancestor_info(node_indext left_index, node_indext right_index)
Finds the nearest common ancestor of two nodes and then returns it.
Definition: scope_tree.cpp:37
void set_case_number(const irep_idt &number)
void value(const irep_idt &)
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:3055
Semantic type conversion.
Definition: std_expr.h:2068
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
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)
Definition: destructor.cpp:18
Destructor Calls.
#define Forall_operands(it, expr)
Definition: expr.h:27
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
Definition: expr_util.cpp:141
exprt boolean_negate(const exprt &src)
negate a Boolean expression, possibly removing a not_exprt, and swapping false and true
Definition: expr_util.cpp:129
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_assignt & to_code_assign(const goto_instruction_codet &code)
const code_function_callt & to_code_function_call(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.
Definition: goto_program.h:32
@ ATOMIC_END
Definition: goto_program.h:44
@ DEAD
Definition: goto_program.h:48
@ ASSIGN
Definition: goto_program.h:46
@ ATOMIC_BEGIN
Definition: goto_program.h:43
@ CATCH
Definition: goto_program.h:51
@ END_THREAD
Definition: goto_program.h:40
@ SKIP
Definition: goto_program.h:38
@ NO_INSTRUCTION_TYPE
Definition: goto_program.h:33
@ START_THREAD
Definition: goto_program.h:39
@ DECL
Definition: goto_program.h:47
@ OTHER
Definition: goto_program.h:37
const irept & get_nil_irep()
Definition: irep.cpp:19
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
API to expression classes for Pointers.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:890
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:577
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).
Definition: remove_skip.cpp:27
Program Transformation.
std::size_t node_indext
Definition: scope_tree.h:19
bool simplify(exprt &expr, 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
const code_ifthenelset & to_code_ifthenelse(const codet &code)
Definition: std_code.h:530
const code_gotot & to_code_goto(const codet &code)
Definition: std_code.h:875
const code_whilet & to_code_while(const codet &code)
Definition: std_code.h:654
const code_continuet & to_code_continue(const codet &code)
Definition: std_code.h:1239
side_effect_exprt & to_side_effect_expr(exprt &expr)
Definition: std_code.h:1506
const code_assumet & to_code_assume(const codet &code)
Definition: std_code.h:251
const code_switch_caset & to_code_switch_case(const codet &code)
Definition: std_code.h:1077
const code_labelt & to_code_label(const codet &code)
Definition: std_code.h:1004
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_switcht & to_code_switch(const codet &code)
Definition: std_code.h:592
code_expressiont & to_code_expression(codet &code)
Definition: std_code.h:1428
const code_frontend_declt & to_code_frontend_decl(const codet &code)
Definition: std_code.h:429
const code_breakt & to_code_break(const codet &code)
Definition: std_code.h:1203
static code_push_catcht & to_code_push_catch(codet &code)
Definition: std_code.h:1883
const code_blockt & to_code_block(const codet &code)
Definition: std_code.h:203
const code_frontend_returnt & to_code_frontend_return(const codet &code)
Definition: std_code.h:943
const code_assertt & to_code_assert(const codet &code)
Definition: std_code.h:304
const code_gcc_switch_case_ranget & to_code_gcc_switch_case_range(const codet &code)
Definition: std_code.h:1161
const code_fort & to_code_for(const codet &code)
Definition: std_code.h:823
code_asmt & to_code_asm(codet &code)
Definition: std_code.h:1282
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:54
API to expression classes.
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2450
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2102
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
Definition: std_expr.h:2352
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:715
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2933
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1533
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)
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
goto_programt::targett goto_instruction
goto_programt::targett label_instruction
computed_gotost computed_gotos
goto_programt::targett continue_target
void set_break(goto_programt::targett _break_target)
goto_programt::targett default_target
goto_programt::targett return_target
void set_default(goto_programt::targett _default_target)
void set_continue(goto_programt::targett _continue_target)
goto_programt::targett break_target