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 
28 
29 #include "destructor.h"
30 
31 static 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;
72  const code_push_catcht::exception_listt &handler_list =
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 
97 {
104 };
105 
107  goto_programt &program,
108  std::unordered_map<irep_idt, symbolt, irep_id_hash> &label_flags,
109  const build_declaration_hops_inputst &inputs)
110 {
111  // In the case of a goto jumping into a scope, the declarations (but not the
112  // initialisations) need to be executed. This function performs a
113  // transformation from code that looks like -
114  // {
115  // statement_block_a();
116  // if(...)
117  // goto user_label;
118  // statement_block_b();
119  // int x;
120  // x = 0;
121  // statement_block_c();
122  // int y;
123  // y = 0;
124  // statement_block_d();
125  // user_label:
126  // statement_block_e();
127  // }
128  // to code which looks like -
129  // {
130  // __CPROVER_bool going_to::user_label;
131  // going_to::user_label = false;
132  // statement_block_a();
133  // if(...)
134  // {
135  // going_to::user_label = true;
136  // goto scope_x_label;
137  // }
138  // statement_block_b();
139  // scope_x_label:
140  // int x;
141  // if going_to::user_label goto scope_y_label:
142  // x = 0;
143  // statement_block_c();
144  // scope_y_label:
145  // int y;
146  // if going_to::user_label goto user_label:
147  // y = 0;
148  // statement_block_d();
149  // user_label:
150  // going_to::user_label = false;
151  // statement_block_e();
152  // }
153 
155 
156  const auto flag = [&]() -> symbolt {
157  const auto existing_flag = label_flags.find(inputs.label);
158  if(existing_flag != label_flags.end())
159  return existing_flag->second;
160  source_locationt label_location =
161  inputs.label_instruction->source_location();
162  label_location.set_hide();
163  const symbolt &new_flag = get_fresh_aux_symbol(
164  bool_typet{},
165  "going_to",
166  id2string(inputs.label),
167  label_location,
168  inputs.mode,
169  symbol_table);
170  label_flags.emplace(inputs.label, new_flag);
171 
172  // Create and initialise flag.
173  goto_programt flag_creation;
174  flag_creation.instructions.push_back(
175  goto_programt::make_decl(new_flag.symbol_expr(), label_location));
176  const auto make_clear_flag = [&]() -> goto_programt::instructiont {
178  new_flag.symbol_expr(), false_exprt{}, label_location);
179  };
180  flag_creation.instructions.push_back(make_clear_flag());
181  program.destructive_insert(program.instructions.begin(), flag_creation);
182 
183  // Clear flag on arrival at label.
184  auto clear_on_arrival = make_clear_flag();
185  program.insert_before_swap(inputs.label_instruction, clear_on_arrival);
186  return new_flag;
187  }();
188 
189  auto goto_instruction = inputs.goto_instruction;
190  {
191  // Set flag before the goto.
192  auto goto_location = goto_instruction->source_location();
193  goto_location.set_hide();
194  auto set_flag = goto_programt::make_assignment(
195  flag.symbol_expr(), true_exprt{}, goto_location);
196  program.insert_before_swap(goto_instruction, set_flag);
197  // Keep this iterator referring to the goto instruction, not the assignment.
198  ++goto_instruction;
199  }
200 
201  auto target = inputs.label_instruction;
204  {
206  auto &declaration = targets.scope_stack.get_declaration(current_node);
208  if(!declaration)
209  continue;
210 
211  bool add_if = declaration->accounted_flags.find(flag.name) ==
212  declaration->accounted_flags.end();
213  if(add_if)
214  {
215  auto declaration_location = declaration->instruction->source_location();
216  declaration_location.set_hide();
217  auto if_goto = goto_programt::make_goto(
218  target, flag.symbol_expr(), declaration_location);
219  program.instructions.insert(
220  std::next(declaration->instruction), std::move(if_goto));
221  declaration->accounted_flags.insert(flag.name);
222  }
223  target = declaration->instruction;
224  }
225 
226  // Update the goto so that it goes to the first declaration rather than its
227  // original/final destination.
228  goto_instruction->set_target(target);
229 }
230 
231 /******************************************************************* \
232 
233 Function: goto_convertt::finish_gotos
234 
235  Inputs:
236 
237  Outputs:
238 
239  Purpose:
240 
241 \*******************************************************************/
242 
244 {
245  std::unordered_map<irep_idt, symbolt, irep_id_hash> label_flags;
246 
247  for(const auto &g_it : targets.gotos)
248  {
249  goto_programt::instructiont &i = *(g_it.first);
250 
251  if(i.is_start_thread())
252  {
253  const irep_idt &goto_label = i.code().get(ID_destination);
254  const auto l_it = targets.labels.find(goto_label);
255 
256  if(l_it == targets.labels.end())
257  {
259  "goto label \'" + id2string(goto_label) + "\' not found",
260  i.code().find_source_location());
261  }
262 
263  i.targets.push_back(l_it->second.first);
264  }
265  else if(i.is_incomplete_goto())
266  {
267  const irep_idt &goto_label = i.code().get(ID_destination);
268  const auto l_it = targets.labels.find(goto_label);
269 
270  if(l_it == targets.labels.end())
271  {
273  "goto label \'" + id2string(goto_label) + "\' not found",
274  i.code().find_source_location());
275  }
276 
277  i.complete_goto(l_it->second.first);
278 
279  node_indext label_target = l_it->second.second;
280  node_indext goto_target = g_it.second;
281 
282  // Compare the currently-live variables on the path of the GOTO and label.
283  // We want to work out what variables should die during the jump.
284  ancestry_resultt intersection_result =
286  goto_target, label_target);
287 
288  // If our goto had no variables of note, just skip (0 is the index of the
289  // root of the scope tree)
290  if(goto_target != 0)
291  {
292  // If the goto recorded a destructor stack, execute as much as is
293  // appropriate for however many automatic variables leave scope.
295  debug() << "adding goto-destructor code on jump to '" << goto_label
296  << "'" << eom;
297 
298  node_indext end_destruct = intersection_result.common_ancestor;
299  goto_programt destructor_code;
301  i.source_location(),
302  destructor_code,
303  mode,
304  end_destruct,
305  goto_target);
306  dest.destructive_insert(g_it.first, destructor_code);
307 
308  // This should leave iterators intact, as long as
309  // goto_programt::instructionst is std::list.
310  }
311 
312  // Variables *entering* scope on goto, is illegal for C++ non-pod types
313  // and impossible in Java. However, with the exception of Variable Length
314  // Arrays (VLAs), this is valid C and should be taken into account.
315  const bool variables_added_to_scope =
316  intersection_result.right_depth_below_common_ancestor > 0;
317  if(variables_added_to_scope)
318  {
319  // If the goto recorded a destructor stack, execute as much as is
320  // appropriate for however many automatic variables leave scope.
322  debug() << "encountered goto '" << goto_label
323  << "' that enters one or more lexical blocks; "
324  << "adding declaration code on jump to '" << goto_label << "'"
325  << eom;
326 
328  inputs.mode = mode;
329  inputs.label = l_it->first;
330  inputs.goto_instruction = g_it.first;
331  inputs.label_instruction = l_it->second.first;
332  inputs.label_scope_index = label_target;
333  inputs.end_scope_index = intersection_result.common_ancestor;
334  build_declaration_hops(dest, label_flags, inputs);
335  }
336  }
337  else
338  {
339  UNREACHABLE;
340  }
341  }
342 
343  targets.gotos.clear();
344 }
345 
347 {
348  for(auto &g_it : targets.computed_gotos)
349  {
350  goto_programt::instructiont &i = *g_it;
351  dereference_exprt destination = to_dereference_expr(i.code().op0());
352  const exprt pointer = destination.pointer();
353 
354  // remember the expression for later checks
355  i =
357 
358  // insert huge case-split
359  for(const auto &label : targets.labels)
360  {
361  exprt label_expr(ID_label, empty_typet());
362  label_expr.set(ID_identifier, label.first);
363 
364  const equal_exprt guard(pointer, address_of_exprt(label_expr));
365 
366  goto_program.insert_after(
367  g_it,
369  label.second.first, guard, i.source_location()));
370  }
371  }
372 
373  targets.computed_gotos.clear();
374 }
375 
380 {
381  // We cannot use a set of targets, as target iterators
382  // cannot be compared at this stage.
383 
384  // collect targets: reset marking
385  for(auto &i : dest.instructions)
386  i.target_number = goto_programt::instructiont::nil_target;
387 
388  // mark the goto targets
389  unsigned cnt = 0;
390  for(auto &i : dest.instructions)
391  if(i.is_goto())
392  i.get_target()->target_number = (++cnt);
393 
394  for(auto it = dest.instructions.begin(); it != dest.instructions.end(); it++)
395  {
396  if(!it->is_goto())
397  continue;
398 
399  auto it_goto_y = std::next(it);
400 
401  if(
402  it_goto_y == dest.instructions.end() || !it_goto_y->is_goto() ||
403  !it_goto_y->condition().is_true() || it_goto_y->is_target())
404  {
405  continue;
406  }
407 
408  auto it_z = std::next(it_goto_y);
409 
410  if(it_z == dest.instructions.end())
411  continue;
412 
413  // cannot compare iterators, so compare target number instead
414  if(it->get_target()->target_number == it_z->target_number)
415  {
416  it->set_target(it_goto_y->get_target());
417  it->condition_nonconst() = boolean_negate(it->condition());
418  it_goto_y->turn_into_skip();
419  }
420  }
421 }
422 
424  const codet &code,
425  goto_programt &dest,
426  const irep_idt &mode)
427 {
428  goto_convert_rec(code, dest, mode);
429 }
430 
432  const codet &code,
433  goto_programt &dest,
434  const irep_idt &mode)
435 {
436  convert(code, dest, mode);
437 
438  finish_gotos(dest, mode);
439  finish_computed_gotos(dest);
442 }
443 
445  const codet &code,
447  goto_programt &dest)
448 {
450  code, code.source_location(), type, nil_exprt(), {}));
451 }
452 
454  const code_labelt &code,
455  goto_programt &dest,
456  const irep_idt &mode)
457 {
458  // grab the label
459  const irep_idt &label = code.get_label();
460 
461  goto_programt tmp;
462 
463  // magic thread creation label.
464  // The "__CPROVER_ASYNC_" signals the start of a sequence of instructions
465  // that can be executed in parallel, i.e, a new thread.
466  if(label.starts_with(CPROVER_PREFIX "ASYNC_"))
467  {
468  // the body of the thread is expected to be
469  // in the operand.
471  to_code_label(code).code().is_not_nil(),
472  "code() in magic thread creation label is null");
473 
474  // replace the magic thread creation label with a
475  // thread block (START_THREAD...END_THREAD).
476  code_blockt thread_body;
477  thread_body.add(to_code_label(code).code());
478  thread_body.add_source_location() = code.source_location();
479  generate_thread_block(thread_body, dest, mode);
480  }
481  else
482  {
483  convert(to_code_label(code).code(), tmp, mode);
484 
485  goto_programt::targett target = tmp.instructions.begin();
486  dest.destructive_append(tmp);
487 
488  targets.labels.insert(
489  {label, {target, targets.scope_stack.get_current_node()}});
490  target->labels.push_front(label);
491  }
492 }
493 
495 {
496  // ignore for now
497 }
498 
500  const code_switch_caset &code,
501  goto_programt &dest,
502  const irep_idt &mode)
503 {
504  goto_programt tmp;
505  convert(code.code(), tmp, mode);
506 
507  goto_programt::targett target = tmp.instructions.begin();
508  dest.destructive_append(tmp);
509 
510  // is a default target given?
511 
512  if(code.is_default())
513  targets.set_default(target);
514  else
515  {
516  // cases?
517 
518  cases_mapt::iterator cases_entry = targets.cases_map.find(target);
519  if(cases_entry == targets.cases_map.end())
520  {
521  targets.cases.push_back(std::make_pair(target, caset()));
522  cases_entry =
523  targets.cases_map.insert(std::make_pair(target, --targets.cases.end()))
524  .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(and_exprt{
575  binary_relation_exprt{code.lower(), ID_le, nil_exprt{}},
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 || statement == "cpp_delete[]")
643  convert_cpp_delete(code, dest);
644  else if(statement == ID_msc_try_except)
645  convert_msc_try_except(code, dest, mode);
646  else if(statement == ID_msc_try_finally)
647  convert_msc_try_finally(code, dest, mode);
648  else if(statement == ID_msc_leave)
649  convert_msc_leave(code, dest, mode);
650  else if(statement == ID_try_catch) // C++ try/catch
651  convert_try_catch(code, dest, mode);
652  else if(statement == ID_CPROVER_try_catch) // CPROVER-homemade
653  convert_CPROVER_try_catch(code, dest, mode);
654  else if(statement == ID_CPROVER_throw) // CPROVER-homemade
655  convert_CPROVER_throw(code, dest, mode);
656  else if(statement == ID_CPROVER_try_finally)
657  convert_CPROVER_try_finally(code, dest, mode);
658  else if(statement == ID_asm)
659  convert_asm(to_code_asm(code), dest);
660  else if(statement == ID_static_assert)
661  {
662  PRECONDITION(code.operands().size() == 2);
663  exprt assertion =
665  simplify(assertion, ns);
667  !assertion.is_false(),
668  "static assertion " + id2string(get_string_constant(code.op1())),
669  code.op0().find_source_location());
670  }
671  else if(statement == ID_dead)
672  copy(code, DEAD, dest);
673  else if(statement == ID_decl_block)
674  {
675  for(const auto &op : code.operands())
676  convert(to_code(op), dest, mode);
677  }
678  else if(
679  statement == ID_push_catch || statement == ID_pop_catch ||
680  statement == ID_exception_landingpad)
681  copy(code, CATCH, dest);
682  else
683  copy(code, OTHER, dest);
684 
685  // make sure dest is never empty
686  if(dest.instructions.empty())
687  {
689  }
690 }
691 
693  const code_blockt &code,
694  goto_programt &dest,
695  const irep_idt &mode)
696 {
697  const source_locationt &end_location = code.end_location();
698 
699  // this saves the index of the destructor stack
701 
702  // now convert block
703  for(const auto &b_code : code.statements())
704  convert(b_code, dest, mode);
705 
706  // see if we need to do any destructors -- may have been processed
707  // in a prior break/continue/return already, don't create dead code
708  if(
709  !dest.empty() && dest.instructions.back().is_goto() &&
710  dest.instructions.back().condition().is_true())
711  {
712  // don't do destructors when we are unreachable
713  }
714  else
715  unwind_destructor_stack(end_location, dest, mode, old_stack_top);
716 
717  // Set the current node of our destructor stack back to before the block.
718  targets.scope_stack.set_current_node(old_stack_top);
719 }
720 
722  const code_expressiont &code,
723  goto_programt &dest,
724  const irep_idt &mode)
725 {
726  exprt expr = code.expression();
727 
728  if(expr.id() == ID_if)
729  {
730  // We do a special treatment for c?t:f
731  // by compiling to if(c) t; else f;
732  const if_exprt &if_expr = to_if_expr(expr);
733  code_ifthenelset tmp_code(
734  if_expr.cond(),
735  code_expressiont(if_expr.true_case()),
736  code_expressiont(if_expr.false_case()));
737  tmp_code.add_source_location() = expr.source_location();
738  tmp_code.then_case().add_source_location() = expr.source_location();
739  tmp_code.else_case().add_source_location() = expr.source_location();
740  convert_ifthenelse(tmp_code, dest, mode);
741  }
742  else
743  {
744  clean_expr(expr, dest, mode, false); // result _not_ used
745 
746  // Any residual expression?
747  // We keep it to add checks later.
748  if(expr.is_not_nil())
749  {
750  codet tmp = code;
751  tmp.op0() = expr;
752  tmp.add_source_location() = expr.source_location();
753  copy(tmp, OTHER, dest);
754  }
755  }
756 }
757 
759  const code_frontend_declt &code,
760  goto_programt &dest,
761  const irep_idt &mode)
762 {
763  const irep_idt &identifier = code.get_identifier();
764 
765  const symbolt &symbol = ns.lookup(identifier);
766 
767  if(symbol.is_static_lifetime || symbol.type.id() == ID_code)
768  return; // this is a SKIP!
769 
770  const goto_programt::targett declaration_iterator = [&]() {
771  if(code.operands().size() == 1)
772  {
773  copy(code, DECL, dest);
774  return std::prev(dest.instructions.end());
775  }
776 
777  exprt initializer = code.op1();
778 
779  codet tmp = code;
780  tmp.operands().resize(1);
781  // hide this declaration-without-initializer step in the goto trace
783 
784  // Break up into decl and assignment.
785  // Decl must be visible before initializer.
786  copy(tmp, DECL, dest);
787  const auto declaration_iterator = std::prev(dest.instructions.end());
788 
789  auto initializer_location = initializer.find_source_location();
790  clean_expr(initializer, dest, mode);
791 
792  if(initializer.is_not_nil())
793  {
794  code_assignt assign(code.op0(), initializer);
795  assign.add_source_location() = initializer_location;
796 
797  convert_assign(assign, dest, mode);
798  }
799 
800  return declaration_iterator;
801  }();
802 
803  // now create a 'dead' instruction -- will be added after the
804  // destructor created below as unwind_destructor_stack pops off the
805  // top of the destructor stack
806  const symbol_exprt symbol_expr(symbol.name, symbol.type);
807 
808  {
809  code_deadt code_dead(symbol_expr);
810 
811  targets.scope_stack.add(code_dead, {declaration_iterator});
812  }
813 
814  // do destructor
815  code_function_callt destructor = get_destructor(ns, symbol.type);
816 
817  if(destructor.is_not_nil())
818  {
819  // add "this"
820  address_of_exprt this_expr(symbol_expr, pointer_type(symbol.type));
821  destructor.arguments().push_back(this_expr);
822 
823  targets.scope_stack.add(destructor, {});
824  }
825 }
826 
828 {
829  // we remove these
830 }
831 
833  const code_assignt &code,
834  goto_programt &dest,
835  const irep_idt &mode)
836 {
837  exprt lhs = code.lhs(), rhs = code.rhs();
838 
839  clean_expr(lhs, dest, mode);
840 
841  if(rhs.id() == ID_side_effect && rhs.get(ID_statement) == ID_function_call)
842  {
843  const auto &rhs_function_call = to_side_effect_expr_function_call(rhs);
844 
846  rhs.operands().size() == 2,
847  "function_call sideeffect takes two operands",
848  rhs.find_source_location());
849 
850  Forall_operands(it, rhs)
851  clean_expr(*it, dest, mode);
852 
854  lhs,
855  rhs_function_call.function(),
856  rhs_function_call.arguments(),
857  dest,
858  mode);
859  }
860  else if(
861  rhs.id() == ID_side_effect && (rhs.get(ID_statement) == ID_cpp_new ||
862  rhs.get(ID_statement) == ID_cpp_new_array))
863  {
864  Forall_operands(it, rhs)
865  clean_expr(*it, dest, mode);
866 
867  // TODO: This should be done in a separate pass
868  do_cpp_new(lhs, to_side_effect_expr(rhs), dest);
869  }
870  else if(
871  rhs.id() == ID_side_effect &&
872  (rhs.get(ID_statement) == ID_assign ||
873  rhs.get(ID_statement) == ID_postincrement ||
874  rhs.get(ID_statement) == ID_preincrement ||
875  rhs.get(ID_statement) == ID_statement_expression ||
876  rhs.get(ID_statement) == ID_gcc_conditional_expression))
877  {
878  // handle above side effects
879  clean_expr(rhs, dest, mode);
880 
881  code_assignt new_assign(code);
882  new_assign.lhs() = lhs;
883  new_assign.rhs() = rhs;
884 
885  copy(new_assign, ASSIGN, dest);
886  }
887  else if(rhs.id() == ID_side_effect)
888  {
889  // preserve side effects that will be handled at later stages,
890  // such as allocate, new operators of other languages, e.g. java, etc
891  Forall_operands(it, rhs)
892  clean_expr(*it, dest, mode);
893 
894  code_assignt new_assign(code);
895  new_assign.lhs() = lhs;
896  new_assign.rhs() = rhs;
897 
898  copy(new_assign, ASSIGN, dest);
899  }
900  else
901  {
902  // do everything else
903  clean_expr(rhs, dest, mode);
904 
905  code_assignt new_assign(code);
906  new_assign.lhs() = lhs;
907  new_assign.rhs() = rhs;
908 
909  copy(new_assign, ASSIGN, dest);
910  }
911 }
912 
914 {
916  code.operands().size() == 1,
917  "cpp_delete statement takes one operand",
918  code.find_source_location());
919 
920  exprt tmp_op = code.op0();
921 
922  clean_expr(tmp_op, dest, ID_cpp);
923 
924  // we call the destructor, and then free
925  const exprt &destructor =
926  static_cast<const exprt &>(code.find(ID_destructor));
927 
928  irep_idt delete_identifier;
929 
930  if(code.get_statement() == ID_cpp_delete_array)
931  delete_identifier = "__delete_array";
932  else if(code.get_statement() == ID_cpp_delete)
933  delete_identifier = "__delete";
934  else
935  UNREACHABLE;
936 
937  if(destructor.is_not_nil())
938  {
939  if(code.get_statement() == ID_cpp_delete_array)
940  {
941  // build loop
942  }
943  else if(code.get_statement() == ID_cpp_delete)
944  {
945  // just one object
946  const dereference_exprt deref_op(tmp_op);
947 
948  codet tmp_code = to_code(destructor);
949  replace_new_object(deref_op, tmp_code);
950  convert(tmp_code, dest, ID_cpp);
951  }
952  else
953  UNREACHABLE;
954  }
955 
956  // now do "free"
957  exprt delete_symbol = ns.lookup(delete_identifier).symbol_expr();
958 
960  to_code_type(delete_symbol.type()).parameters().size() == 1,
961  "delete statement takes 1 parameter");
962 
963  typet arg_type =
964  to_code_type(delete_symbol.type()).parameters().front().type();
965 
966  code_function_callt delete_call(
967  delete_symbol, {typecast_exprt(tmp_op, arg_type)});
968  delete_call.add_source_location() = code.source_location();
969 
970  convert(delete_call, dest, ID_cpp);
971 }
972 
974  const code_assertt &code,
975  goto_programt &dest,
976  const irep_idt &mode)
977 {
978  exprt cond = code.assertion();
979 
980  clean_expr(cond, dest, mode);
981 
982  source_locationt annotated_location = code.source_location();
983  annotated_location.set("user-provided", true);
984  dest.add(goto_programt::make_assertion(cond, annotated_location));
985 }
986 
988 {
990  code, code.source_location(), SKIP, nil_exprt(), {}));
991 }
992 
994  const code_assumet &code,
995  goto_programt &dest,
996  const irep_idt &mode)
997 {
998  exprt op = code.assumption();
999 
1000  clean_expr(op, dest, mode);
1001 
1003 }
1004 
1006  const codet &code,
1008  const irep_idt &mode)
1009 {
1010  auto assigns = static_cast<const unary_exprt &>(code.find(ID_C_spec_assigns));
1011  if(assigns.is_not_nil())
1012  {
1013  PRECONDITION(loop->is_goto());
1014  loop->condition_nonconst().add(ID_C_spec_assigns).swap(assigns.op());
1015  }
1016 
1017  auto invariant =
1018  static_cast<const exprt &>(code.find(ID_C_spec_loop_invariant));
1019  if(!invariant.is_nil())
1020  {
1021  if(has_subexpr(invariant, ID_side_effect))
1022  {
1024  "Loop invariant is not side-effect free.", code.find_source_location());
1025  }
1026 
1027  PRECONDITION(loop->is_goto());
1028  loop->condition_nonconst().add(ID_C_spec_loop_invariant).swap(invariant);
1029  }
1030 
1031  auto decreases_clause =
1032  static_cast<const exprt &>(code.find(ID_C_spec_decreases));
1033  if(!decreases_clause.is_nil())
1034  {
1035  if(has_subexpr(decreases_clause, ID_side_effect))
1036  {
1038  "Decreases clause is not side-effect free.",
1039  code.find_source_location());
1040  }
1041 
1042  PRECONDITION(loop->is_goto());
1043  loop->condition_nonconst().add(ID_C_spec_decreases).swap(decreases_clause);
1044  }
1045 }
1046 
1048  const code_fort &code,
1049  goto_programt &dest,
1050  const irep_idt &mode)
1051 {
1052  // turn for(A; c; B) { P } into
1053  // A; while(c) { P; B; }
1054  //-----------------------------
1055  // A;
1056  // u: sideeffects in c
1057  // v: if(!c) goto z;
1058  // w: P;
1059  // x: B; <-- continue target
1060  // y: goto u;
1061  // z: ; <-- break target
1062 
1063  // A;
1064  if(code.init().is_not_nil())
1065  convert(to_code(code.init()), dest, mode);
1066 
1067  exprt cond = code.cond();
1068 
1069  goto_programt sideeffects;
1070  clean_expr(cond, sideeffects, mode);
1071 
1072  // save break/continue targets
1073  break_continue_targetst old_targets(targets);
1074 
1075  // do the u label
1076  goto_programt::targett u = sideeffects.instructions.begin();
1077 
1078  // do the v label
1079  goto_programt tmp_v;
1081 
1082  // do the z label
1083  goto_programt tmp_z;
1086 
1087  // do the x label
1088  goto_programt tmp_x;
1089 
1090  if(code.iter().is_nil())
1091  {
1093  }
1094  else
1095  {
1096  exprt tmp_B = code.iter();
1097 
1098  clean_expr(tmp_B, tmp_x, mode, false);
1099 
1100  if(tmp_x.instructions.empty())
1102  }
1103 
1104  // optimize the v label
1105  if(sideeffects.instructions.empty())
1106  u = v;
1107 
1108  // set the targets
1109  targets.set_break(z);
1110  targets.set_continue(tmp_x.instructions.begin());
1111 
1112  // v: if(!c) goto z;
1113  *v =
1115 
1116  // do the w label
1117  goto_programt tmp_w;
1118  convert(code.body(), tmp_w, mode);
1119 
1120  // y: goto u;
1121  goto_programt tmp_y;
1122  goto_programt::targett y = tmp_y.add(
1124 
1125  // assigns clause, loop invariant and decreases clause
1126  convert_loop_contracts(code, y, mode);
1127 
1128  dest.destructive_append(sideeffects);
1129  dest.destructive_append(tmp_v);
1130  dest.destructive_append(tmp_w);
1131  dest.destructive_append(tmp_x);
1132  dest.destructive_append(tmp_y);
1133  dest.destructive_append(tmp_z);
1134 
1135  // restore break/continue
1136  old_targets.restore(targets);
1137 }
1138 
1140  const code_whilet &code,
1141  goto_programt &dest,
1142  const irep_idt &mode)
1143 {
1144  const exprt &cond = code.cond();
1145  const source_locationt &source_location = code.source_location();
1146 
1147  // while(c) P;
1148  //--------------------
1149  // v: sideeffects in c
1150  // if(!c) goto z;
1151  // x: P;
1152  // y: goto v; <-- continue target
1153  // z: ; <-- break target
1154 
1155  // save break/continue targets
1156  break_continue_targetst old_targets(targets);
1157 
1158  // do the z label
1159  goto_programt tmp_z;
1161  tmp_z.add(goto_programt::make_skip(source_location));
1162 
1163  goto_programt tmp_branch;
1165  boolean_negate(cond), z, source_location, tmp_branch, mode);
1166 
1167  // do the v label
1168  goto_programt::targett v = tmp_branch.instructions.begin();
1169 
1170  // y: goto v;
1171  goto_programt tmp_y;
1172  goto_programt::targett y = tmp_y.add(
1174 
1175  // set the targets
1176  targets.set_break(z);
1177  targets.set_continue(y);
1178 
1179  // do the x label
1180  goto_programt tmp_x;
1181  convert(code.body(), tmp_x, mode);
1182 
1183  // assigns clause, loop invariant and decreases clause
1184  convert_loop_contracts(code, y, mode);
1185 
1186  dest.destructive_append(tmp_branch);
1187  dest.destructive_append(tmp_x);
1188  dest.destructive_append(tmp_y);
1189  dest.destructive_append(tmp_z);
1190 
1191  // restore break/continue
1192  old_targets.restore(targets);
1193 }
1194 
1196  const code_dowhilet &code,
1197  goto_programt &dest,
1198  const irep_idt &mode)
1199 {
1201  code.operands().size() == 2,
1202  "dowhile takes two operands",
1203  code.find_source_location());
1204 
1205  // save source location
1206  source_locationt condition_location = code.cond().find_source_location();
1207 
1208  exprt cond = code.cond();
1209 
1210  goto_programt sideeffects;
1211  clean_expr(cond, sideeffects, mode);
1212 
1213  // do P while(c);
1214  //--------------------
1215  // w: P;
1216  // x: sideeffects in c <-- continue target
1217  // y: if(c) goto w;
1218  // z: ; <-- break target
1219 
1220  // save break/continue targets
1221  break_continue_targetst old_targets(targets);
1222 
1223  // do the y label
1224  goto_programt tmp_y;
1226  tmp_y.add(goto_programt::make_incomplete_goto(cond, condition_location));
1227 
1228  // do the z label
1229  goto_programt tmp_z;
1232 
1233  // do the x label
1235  if(sideeffects.instructions.empty())
1236  x = y;
1237  else
1238  x = sideeffects.instructions.begin();
1239 
1240  // set the targets
1241  targets.set_break(z);
1242  targets.set_continue(x);
1243 
1244  // do the w label
1245  goto_programt tmp_w;
1246  convert(code.body(), tmp_w, mode);
1247  goto_programt::targett w = tmp_w.instructions.begin();
1248 
1249  // y: if(c) goto w;
1250  y->complete_goto(w);
1251 
1252  // assigns_clause, loop invariant and decreases clause
1253  convert_loop_contracts(code, y, mode);
1254 
1255  dest.destructive_append(tmp_w);
1256  dest.destructive_append(sideeffects);
1257  dest.destructive_append(tmp_y);
1258  dest.destructive_append(tmp_z);
1259 
1260  // restore break/continue targets
1261  old_targets.restore(targets);
1262 }
1263 
1265  const exprt &value,
1266  const exprt::operandst &case_op)
1267 {
1268  PRECONDITION(!case_op.empty());
1269 
1270  exprt::operandst disjuncts;
1271  disjuncts.reserve(case_op.size());
1272 
1273  for(const auto &op : case_op)
1274  {
1275  // could be a skeleton generated by convert_gcc_switch_case_range
1276  if(op.id() == ID_and)
1277  {
1278  const binary_exprt &and_expr = to_binary_expr(op);
1279  PRECONDITION(to_binary_expr(and_expr.op0()).op1().is_nil());
1280  PRECONDITION(to_binary_expr(and_expr.op1()).op0().is_nil());
1281  binary_exprt skeleton = and_expr;
1282  to_binary_expr(skeleton.op0()).op1() = value;
1283  to_binary_expr(skeleton.op1()).op0() = value;
1284  disjuncts.push_back(skeleton);
1285  }
1286  else
1287  disjuncts.push_back(equal_exprt(value, op));
1288  }
1289 
1290  return disjunction(disjuncts);
1291 }
1292 
1294  const code_switcht &code,
1295  goto_programt &dest,
1296  const irep_idt &mode)
1297 {
1298  // switch(v) {
1299  // case x: Px;
1300  // case y: Py;
1301  // ...
1302  // default: Pd;
1303  // }
1304  // --------------------
1305  // location
1306  // x: if(v==x) goto X;
1307  // y: if(v==y) goto Y;
1308  // goto d;
1309  // X: Px;
1310  // Y: Py;
1311  // d: Pd;
1312  // z: ;
1313 
1314  // we first add a 'location' node for the switch statement,
1315  // which would otherwise not be recorded
1317 
1318  // get the location of the end of the body, but
1319  // default to location of switch, if none
1320  source_locationt body_end_location =
1321  code.body().get_statement() == ID_block
1322  ? to_code_block(code.body()).end_location()
1323  : code.source_location();
1324 
1325  // do the value we switch over
1326  exprt argument = code.value();
1327 
1328  goto_programt sideeffects;
1329  clean_expr(argument, sideeffects, mode);
1330 
1331  // Avoid potential performance penalties caused by evaluating the value
1332  // multiple times (as the below chain-of-ifs does). "needs_cleaning" isn't
1333  // necessarily the right check here, and we may need to introduce a different
1334  // way of identifying the class of non-trivial expressions that warrant
1335  // introduction of a temporary.
1336  if(needs_cleaning(argument))
1337  {
1338  symbolt &new_symbol = new_tmp_symbol(
1339  argument.type(),
1340  "switch_value",
1341  sideeffects,
1342  code.source_location(),
1343  mode);
1344 
1345  code_assignt copy_value{
1346  new_symbol.symbol_expr(), argument, code.source_location()};
1347  convert(copy_value, sideeffects, mode);
1348 
1349  argument = new_symbol.symbol_expr();
1350  }
1351 
1352  // save break/default/cases targets
1353  break_switch_targetst old_targets(targets);
1354 
1355  // do the z label
1356  goto_programt tmp_z;
1358  tmp_z.add(goto_programt::make_skip(body_end_location));
1359 
1360  // set the new targets -- continue stays as is
1361  targets.set_break(z);
1362  targets.set_default(z);
1363  targets.cases.clear();
1364  targets.cases_map.clear();
1365 
1366  goto_programt tmp;
1367  convert(code.body(), tmp, mode);
1368 
1369  goto_programt tmp_cases;
1370 
1371  // The case number represents which case this corresponds to in the sequence
1372  // of case statements.
1373  //
1374  // switch (x)
1375  // {
1376  // case 2: // case_number 1
1377  // ...;
1378  // case 3: // case_number 2
1379  // ...;
1380  // case 10: // case_number 3
1381  // ...;
1382  // }
1383  size_t case_number = 1;
1384  for(auto &case_pair : targets.cases)
1385  {
1386  const caset &case_ops = case_pair.second;
1387 
1388  if(case_ops.empty())
1389  continue;
1390 
1391  exprt guard_expr = case_guard(argument, case_ops);
1392 
1393  source_locationt source_location = case_ops.front().find_source_location();
1394  source_location.set_case_number(std::to_string(case_number));
1395  case_number++;
1396  guard_expr.add_source_location() = source_location;
1397 
1398  tmp_cases.add(goto_programt::make_goto(
1399  case_pair.first, std::move(guard_expr), source_location));
1400  }
1401 
1402  tmp_cases.add(goto_programt::make_goto(
1403  targets.default_target, targets.default_target->source_location()));
1404 
1405  dest.destructive_append(sideeffects);
1406  dest.destructive_append(tmp_cases);
1407  dest.destructive_append(tmp);
1408  dest.destructive_append(tmp_z);
1409 
1410  // restore old targets
1411  old_targets.restore(targets);
1412 }
1413 
1415  const code_breakt &code,
1416  goto_programt &dest,
1417  const irep_idt &mode)
1418 {
1420  targets.break_set, "break without target", code.find_source_location());
1421 
1422  // need to process destructor stack
1424  code.source_location(), dest, mode, targets.break_stack_node);
1425 
1426  // add goto
1427  dest.add(
1429 }
1430 
1432  const code_frontend_returnt &code,
1433  goto_programt &dest,
1434  const irep_idt &mode)
1435 {
1436  if(!targets.return_set)
1437  {
1439  "return without target", code.find_source_location());
1440  }
1441 
1443  code.operands().empty() || code.operands().size() == 1,
1444  "return takes none or one operand",
1445  code.find_source_location());
1446 
1447  code_frontend_returnt new_code(code);
1448 
1449  if(new_code.has_return_value())
1450  {
1451  bool result_is_used = new_code.return_value().type().id() != ID_empty;
1452 
1453  goto_programt sideeffects;
1454  clean_expr(new_code.return_value(), sideeffects, mode, result_is_used);
1455  dest.destructive_append(sideeffects);
1456 
1457  // remove void-typed return value
1458  if(!result_is_used)
1459  new_code.return_value().make_nil();
1460  }
1461 
1463  {
1465  new_code.has_return_value(),
1466  "function must return value",
1467  new_code.find_source_location());
1468 
1469  // Now add a 'set return value' instruction to set the return value.
1471  new_code.return_value(), new_code.source_location()));
1472  }
1473  else
1474  {
1476  !new_code.has_return_value() ||
1477  new_code.return_value().type().id() == ID_empty,
1478  "function must not return value",
1479  code.find_source_location());
1480  }
1481 
1482  // Need to process _entire_ destructor stack.
1483  unwind_destructor_stack(code.source_location(), dest, mode);
1484 
1485  // add goto to end-of-function
1487  targets.return_target, new_code.source_location()));
1488 }
1489 
1491  const code_continuet &code,
1492  goto_programt &dest,
1493  const irep_idt &mode)
1494 {
1497  "continue without target",
1498  code.find_source_location());
1499 
1500  // need to process destructor stack
1502  code.source_location(), dest, mode, targets.continue_stack_node);
1503 
1504  // add goto
1505  dest.add(
1507 }
1508 
1510 {
1511  // this instruction will be completed during post-processing
1514 
1515  // remember it to do the target later
1516  targets.gotos.emplace_back(t, targets.scope_stack.get_current_node());
1517 }
1518 
1520  const codet &code,
1521  goto_programt &dest)
1522 {
1523  // this instruction will turn into OTHER during post-processing
1525  code, code.source_location(), NO_INSTRUCTION_TYPE, nil_exprt(), {}));
1526 
1527  // remember it to do this later
1528  targets.computed_gotos.push_back(t);
1529 }
1530 
1532 {
1534  code, code.source_location(), START_THREAD, nil_exprt(), {}));
1535 
1536  // remember it to do target later
1537  targets.gotos.emplace_back(
1538  start_thread, targets.scope_stack.get_current_node());
1539 }
1540 
1542 {
1544  code.operands().empty(),
1545  "end_thread expects no operands",
1546  code.find_source_location());
1547 
1548  copy(code, END_THREAD, dest);
1549 }
1550 
1552 {
1554  code.operands().empty(),
1555  "atomic_begin expects no operands",
1556  code.find_source_location());
1557 
1558  copy(code, ATOMIC_BEGIN, dest);
1559 }
1560 
1562 {
1564  code.operands().empty(),
1565  ": atomic_end expects no operands",
1566  code.find_source_location());
1567 
1568  copy(code, ATOMIC_END, dest);
1569 }
1570 
1572  const code_ifthenelset &code,
1573  goto_programt &dest,
1574  const irep_idt &mode)
1575 {
1576  DATA_INVARIANT(code.then_case().is_not_nil(), "cannot accept an empty body");
1577 
1578  bool has_else = !code.else_case().is_nil();
1579 
1580  const source_locationt &source_location = code.source_location();
1581 
1582  // We do a bit of special treatment for && in the condition
1583  // in case cleaning would be needed otherwise.
1584  if(
1585  code.cond().id() == ID_and && code.cond().operands().size() == 2 &&
1586  (needs_cleaning(to_binary_expr(code.cond()).op0()) ||
1587  needs_cleaning(to_binary_expr(code.cond()).op1())) &&
1588  !has_else)
1589  {
1590  // if(a && b) XX --> if(a) if(b) XX
1591  code_ifthenelset new_if1(
1592  to_binary_expr(code.cond()).op1(), code.then_case());
1593  new_if1.add_source_location() = source_location;
1594  code_ifthenelset new_if0(
1595  to_binary_expr(code.cond()).op0(), std::move(new_if1));
1596  new_if0.add_source_location() = source_location;
1597  return convert_ifthenelse(new_if0, dest, mode);
1598  }
1599 
1600  // convert 'then'-branch
1601  goto_programt tmp_then;
1602  convert(code.then_case(), tmp_then, mode);
1603  source_locationt then_end_location =
1604  code.then_case().get_statement() == ID_block
1606  : code.then_case().source_location();
1607 
1608  goto_programt tmp_else;
1609  source_locationt else_end_location;
1610 
1611  if(has_else)
1612  {
1613  convert(code.else_case(), tmp_else, mode);
1614  else_end_location = code.else_case().get_statement() == ID_block
1616  : code.else_case().source_location();
1617  }
1618 
1619  exprt tmp_guard = code.cond();
1620  clean_expr(tmp_guard, dest, mode);
1621 
1623  tmp_guard,
1624  source_location,
1625  tmp_then,
1626  then_end_location,
1627  tmp_else,
1628  else_end_location,
1629  dest,
1630  mode);
1631 }
1632 
1634  const exprt &expr,
1635  const irep_idt &id,
1636  std::list<exprt> &dest)
1637 {
1638  if(expr.id() != id)
1639  {
1640  dest.push_back(expr);
1641  }
1642  else
1643  {
1644  // left-to-right is important
1645  for(const auto &op : expr.operands())
1646  collect_operands(op, id, dest);
1647  }
1648 }
1649 
1653 static inline bool is_size_one(const goto_programt &g)
1654 {
1655  return (!g.instructions.empty()) &&
1656  ++g.instructions.begin() == g.instructions.end();
1657 }
1658 
1661  const exprt &guard,
1662  const source_locationt &source_location,
1663  goto_programt &true_case,
1664  const source_locationt &then_end_location,
1665  goto_programt &false_case,
1666  const source_locationt &else_end_location,
1667  goto_programt &dest,
1668  const irep_idt &mode)
1669 {
1670  if(is_empty(true_case) && is_empty(false_case))
1671  {
1672  // hmpf. Useless branch.
1673  goto_programt tmp_z;
1675  dest.add(goto_programt::make_goto(z, guard, source_location));
1676  dest.destructive_append(tmp_z);
1677  return;
1678  }
1679 
1680  // do guarded assertions directly
1681  if(
1682  is_size_one(true_case) && true_case.instructions.back().is_assert() &&
1683  true_case.instructions.back().condition().is_false() &&
1684  true_case.instructions.back().labels.empty())
1685  {
1686  // The above conjunction deliberately excludes the instance
1687  // if(some) { label: assert(false); }
1688  true_case.instructions.back().condition_nonconst() = boolean_negate(guard);
1689  dest.destructive_append(true_case);
1690  true_case.instructions.clear();
1691  if(
1692  is_empty(false_case) ||
1693  (is_size_one(false_case) &&
1694  is_skip(false_case, false_case.instructions.begin())))
1695  return;
1696  }
1697 
1698  // similarly, do guarded assertions directly
1699  if(
1700  is_size_one(false_case) && false_case.instructions.back().is_assert() &&
1701  false_case.instructions.back().condition().is_false() &&
1702  false_case.instructions.back().labels.empty())
1703  {
1704  // The above conjunction deliberately excludes the instance
1705  // if(some) ... else { label: assert(false); }
1706  false_case.instructions.back().condition_nonconst() = guard;
1707  dest.destructive_append(false_case);
1708  false_case.instructions.clear();
1709  if(
1710  is_empty(true_case) ||
1711  (is_size_one(true_case) &&
1712  is_skip(true_case, true_case.instructions.begin())))
1713  return;
1714  }
1715 
1716  // a special case for C libraries that use
1717  // (void)((cond) || (assert(0),0))
1718  if(
1719  is_empty(false_case) && true_case.instructions.size() == 2 &&
1720  true_case.instructions.front().is_assert() &&
1721  true_case.instructions.front().condition().is_false() &&
1722  true_case.instructions.front().labels.empty() &&
1723  true_case.instructions.back().labels.empty())
1724  {
1725  true_case.instructions.front().condition_nonconst() = boolean_negate(guard);
1726  true_case.instructions.erase(--true_case.instructions.end());
1727  dest.destructive_append(true_case);
1728  true_case.instructions.clear();
1729 
1730  return;
1731  }
1732 
1733  // Flip around if no 'true' case code.
1734  if(is_empty(true_case))
1735  {
1736  return generate_ifthenelse(
1738  source_location,
1739  false_case,
1740  else_end_location,
1741  true_case,
1742  then_end_location,
1743  dest,
1744  mode);
1745  }
1746 
1747  bool has_else = !is_empty(false_case);
1748 
1749  // if(c) P;
1750  //--------------------
1751  // v: if(!c) goto z;
1752  // w: P;
1753  // z: ;
1754 
1755  // if(c) P; else Q;
1756  //--------------------
1757  // v: if(!c) goto y;
1758  // w: P;
1759  // x: goto z;
1760  // y: Q;
1761  // z: ;
1762 
1763  // do the x label
1764  goto_programt tmp_x;
1765  goto_programt::targett x = tmp_x.add(
1766  goto_programt::make_incomplete_goto(true_exprt(), then_end_location));
1767 
1768  // do the z label
1769  goto_programt tmp_z;
1770  goto_programt::targett z = tmp_z.add(
1771  goto_programt::make_skip(has_else ? else_end_location : then_end_location));
1772 
1773  // y: Q;
1774  goto_programt tmp_y;
1776  if(has_else)
1777  {
1778  tmp_y.swap(false_case);
1779  y = tmp_y.instructions.begin();
1780  }
1781 
1782  // v: if(!c) goto z/y;
1783  goto_programt tmp_v;
1785  boolean_negate(guard), has_else ? y : z, source_location, tmp_v, mode);
1786 
1787  // w: P;
1788  goto_programt tmp_w;
1789  tmp_w.swap(true_case);
1790 
1791  // x: goto z;
1792  CHECK_RETURN(!tmp_w.instructions.empty());
1793  x->complete_goto(z);
1794 
1795  dest.destructive_append(tmp_v);
1796  dest.destructive_append(tmp_w);
1797 
1798  // When the `then` branch of a balanced `if` condition ends with a `return` or
1799  // a `goto` statement, it is not necessary to add the `goto z` and `z:` goto
1800  // elements as they are never used.
1801  // This helps for example when using `--cover location` as such command are
1802  // marked unreachable, but are not part of the user-provided code to analyze.
1803  bool then_branch_returns = dest.instructions.rbegin()->is_goto();
1804 
1805  if(has_else)
1806  {
1807  // Don't add the `goto` at the end of the `then` branch if not needed
1808  if(!then_branch_returns)
1809  {
1810  dest.destructive_append(tmp_x);
1811  }
1812  dest.destructive_append(tmp_y);
1813  }
1814 
1815  // Don't add the `z` label at the end of the `if` when not needed.
1816  if(!has_else || !then_branch_returns)
1817  {
1818  dest.destructive_append(tmp_z);
1819  }
1820 }
1821 
1823 static bool has_and_or(const exprt &expr)
1824 {
1825  for(const auto &op : expr.operands())
1826  {
1827  if(has_and_or(op))
1828  return true;
1829  }
1830 
1831  if(expr.id() == ID_and || expr.id() == ID_or)
1832  return true;
1833 
1834  return false;
1835 }
1836 
1838  const exprt &guard,
1839  goto_programt::targett target_true,
1840  const source_locationt &source_location,
1841  goto_programt &dest,
1842  const irep_idt &mode)
1843 {
1845  {
1846  // if(guard) goto target;
1847  // becomes
1848  // if(guard) goto target; else goto next;
1849  // next: skip;
1850 
1851  goto_programt tmp;
1852  goto_programt::targett target_false =
1853  tmp.add(goto_programt::make_skip(source_location));
1854 
1856  guard, target_true, target_false, source_location, dest, mode);
1857 
1858  dest.destructive_append(tmp);
1859  }
1860  else
1861  {
1862  // simple branch
1863  exprt cond = guard;
1864  clean_expr(cond, dest, mode);
1865 
1866  dest.add(goto_programt::make_goto(target_true, cond, source_location));
1867  }
1868 }
1869 
1872  const exprt &guard,
1873  goto_programt::targett target_true,
1874  goto_programt::targett target_false,
1875  const source_locationt &source_location,
1876  goto_programt &dest,
1877  const irep_idt &mode)
1878 {
1879  if(guard.id() == ID_not)
1880  {
1881  // simply swap targets
1883  to_not_expr(guard).op(),
1884  target_false,
1885  target_true,
1886  source_location,
1887  dest,
1888  mode);
1889  return;
1890  }
1891 
1892  if(guard.id() == ID_and)
1893  {
1894  // turn
1895  // if(a && b) goto target_true; else goto target_false;
1896  // into
1897  // if(!a) goto target_false;
1898  // if(!b) goto target_false;
1899  // goto target_true;
1900 
1901  std::list<exprt> op;
1902  collect_operands(guard, guard.id(), op);
1903 
1904  for(const auto &expr : op)
1906  boolean_negate(expr), target_false, source_location, dest, mode);
1907 
1908  dest.add(goto_programt::make_goto(target_true, source_location));
1909 
1910  return;
1911  }
1912  else if(guard.id() == ID_or)
1913  {
1914  // turn
1915  // if(a || b) goto target_true; else goto target_false;
1916  // into
1917  // if(a) goto target_true;
1918  // if(b) goto target_true;
1919  // goto target_false;
1920 
1921  std::list<exprt> op;
1922  collect_operands(guard, guard.id(), op);
1923 
1924  // true branch(es)
1925  for(const auto &expr : op)
1927  expr, target_true, source_location, dest, mode);
1928 
1929  // false branch
1930  dest.add(goto_programt::make_goto(target_false, guard.source_location()));
1931 
1932  return;
1933  }
1934 
1935  exprt cond = guard;
1936  clean_expr(cond, dest, mode);
1937 
1938  // true branch
1939  dest.add(goto_programt::make_goto(target_true, cond, source_location));
1940 
1941  // false branch
1942  dest.add(goto_programt::make_goto(target_false, source_location));
1943 }
1944 
1946 {
1947  if(expr.id() == ID_typecast)
1948  return get_string_constant(to_typecast_expr(expr).op(), value);
1949 
1950  if(
1951  expr.id() == ID_address_of &&
1952  to_address_of_expr(expr).object().id() == ID_index)
1953  {
1954  exprt index_op =
1955  get_constant(to_index_expr(to_address_of_expr(expr).object()).array());
1956  simplify(index_op, ns);
1957 
1958  if(index_op.id() == ID_string_constant)
1959  {
1960  value = to_string_constant(index_op).value();
1961  return false;
1962  }
1963  else if(index_op.id() == ID_array)
1964  {
1965  std::string result;
1966  for(const auto &op : as_const(index_op).operands())
1967  {
1968  if(op.is_constant())
1969  {
1970  const auto i = numeric_cast<std::size_t>(op);
1971  if(!i.has_value())
1972  return true;
1973 
1974  if(i.value() != 0) // to skip terminating 0
1975  result += static_cast<char>(i.value());
1976  }
1977  }
1978 
1979  return value = result, false;
1980  }
1981  }
1982 
1983  if(expr.id() == ID_string_constant)
1984  {
1985  value = to_string_constant(expr).value();
1986  return false;
1987  }
1988 
1989  return true;
1990 }
1991 
1993 {
1994  irep_idt result;
1995 
1996  const bool res = get_string_constant(expr, result);
1998  !res,
1999  "expected string constant",
2000  expr.find_source_location(),
2001  expr.pretty());
2002 
2003  return result;
2004 }
2005 
2007 {
2008  if(expr.id() == ID_symbol)
2009  {
2010  const symbolt &symbol = ns.lookup(to_symbol_expr(expr));
2011 
2012  return symbol.value;
2013  }
2014  else if(expr.id() == ID_member)
2015  {
2016  auto tmp = to_member_expr(expr);
2017  tmp.compound() = get_constant(tmp.compound());
2018  return std::move(tmp);
2019  }
2020  else if(expr.id() == ID_index)
2021  {
2022  auto tmp = to_index_expr(expr);
2023  tmp.op0() = get_constant(tmp.op0());
2024  tmp.op1() = get_constant(tmp.op1());
2025  return std::move(tmp);
2026  }
2027  else
2028  return expr;
2029 }
2030 
2032  const typet &type,
2033  const std::string &suffix,
2034  goto_programt &dest,
2035  const source_locationt &source_location,
2036  const irep_idt &mode)
2037 {
2038  PRECONDITION(!mode.empty());
2039  symbolt &new_symbol = get_fresh_aux_symbol(
2040  type,
2042  "tmp_" + suffix,
2043  source_location,
2044  mode,
2045  symbol_table);
2046 
2047  code_frontend_declt decl(new_symbol.symbol_expr());
2048  decl.add_source_location() = source_location;
2049  convert_frontend_decl(decl, dest, mode);
2050 
2051  return new_symbol;
2052 }
2053 
2055  exprt &expr,
2056  const std::string &suffix,
2057  goto_programt &dest,
2058  const irep_idt &mode)
2059 {
2060  const source_locationt source_location = expr.find_source_location();
2061 
2062  symbolt &new_symbol =
2063  new_tmp_symbol(expr.type(), suffix, dest, source_location, mode);
2064 
2065  code_assignt assignment;
2066  assignment.lhs() = new_symbol.symbol_expr();
2067  assignment.rhs() = expr;
2068  assignment.add_source_location() = source_location;
2069 
2070  convert(assignment, dest, mode);
2071 
2072  expr = new_symbol.symbol_expr();
2073 }
2074 
2076  const codet &code,
2077  symbol_table_baset &symbol_table,
2078  goto_programt &dest,
2079  message_handlert &message_handler,
2080  const irep_idt &mode)
2081 {
2082  symbol_table_buildert symbol_table_builder =
2083  symbol_table_buildert::wrap(symbol_table);
2084  goto_convertt goto_convert(symbol_table_builder, message_handler);
2085  goto_convert.goto_convert(code, dest, mode);
2086 }
2087 
2089  symbol_table_baset &symbol_table,
2090  goto_programt &dest,
2091  message_handlert &message_handler)
2092 {
2093  // find main symbol
2094  const symbol_table_baset::symbolst::const_iterator s_it =
2095  symbol_table.symbols.find("main");
2096 
2098  s_it != symbol_table.symbols.end(), "failed to find main symbol");
2099 
2100  const symbolt &symbol = s_it->second;
2101 
2103  to_code(symbol.value), symbol_table, dest, message_handler, symbol.mode);
2104 }
2105 
2121  const code_blockt &thread_body,
2122  goto_programt &dest,
2123  const irep_idt &mode)
2124 {
2125  goto_programt preamble, body, postamble;
2126 
2128  convert(thread_body, body, mode);
2129 
2130  postamble.add(goto_programt::instructiont(
2131  static_cast<const codet &>(get_nil_irep()),
2132  thread_body.source_location(),
2133  END_THREAD,
2134  nil_exprt(),
2135  {}));
2137 
2139  static_cast<const codet &>(get_nil_irep()),
2140  thread_body.source_location(),
2141  START_THREAD,
2142  nil_exprt(),
2143  {c}));
2144  preamble.add(goto_programt::make_goto(z, thread_body.source_location()));
2145 
2146  dest.destructive_append(preamble);
2147  dest.destructive_append(body);
2148  dest.destructive_append(postamble);
2149 }
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:19
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