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