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