CBMC
goto_program.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Program Transformation
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "goto_program.h"
13 
14 #include "validate_code.h"
15 
16 #include <iomanip>
17 
18 #include <util/expr_iterator.h>
19 #include <util/find_symbols.h>
20 #include <util/format_expr.h>
21 #include <util/format_type.h>
22 #include <util/invariant.h>
23 #include <util/pointer_expr.h>
24 #include <util/std_code.h>
25 #include <util/std_expr.h>
26 #include <util/symbol_table.h>
27 #include <util/validate.h>
28 
29 #include <langapi/language_util.h>
30 
32  const code_gotot &_code,
33  const source_locationt &l)
34 {
35  return instructiont(_code, l, INCOMPLETE_GOTO, true_exprt(), {});
36 }
37 
47 std::ostream &goto_programt::instructiont::output(std::ostream &out) const
48 {
49  out << " // " << location_number << " ";
50 
51  if(!source_location().is_nil())
52  out << source_location().as_string();
53  else
54  out << "no location";
55 
56  out << "\n";
57 
58  if(!labels.empty())
59  {
60  out << " // Labels:";
61  for(const auto &label : labels)
62  out << " " << label;
63 
64  out << '\n';
65  }
66 
67  if(is_target())
68  out << std::setw(6) << target_number << ": ";
69  else
70  out << " ";
71 
72  switch(type())
73  {
75  out << "NO INSTRUCTION TYPE SET" << '\n';
76  break;
77 
78  case GOTO:
79  case INCOMPLETE_GOTO:
80  if(!condition().is_true())
81  {
82  out << "IF " << format(condition()) << " THEN ";
83  }
84 
85  out << "GOTO ";
86 
87  if(is_incomplete_goto())
88  {
89  out << "(incomplete)";
90  }
91  else
92  {
93  for(auto gt_it = targets.begin(); gt_it != targets.end(); gt_it++)
94  {
95  if(gt_it != targets.begin())
96  out << ", ";
97  out << (*gt_it)->target_number;
98  }
99  }
100 
101  out << '\n';
102  break;
103 
104  case OTHER:
105  if(get_other().id() == ID_code)
106  {
107  const auto &code = get_other();
108  if(code.get_statement() == ID_array_copy)
109  {
110  out << "ARRAY_COPY " << format(code.op0()) << ' ' << format(code.op1())
111  << '\n';
112  break;
113  }
114  else if(code.get_statement() == ID_array_replace)
115  {
116  out << "ARRAY_REPLACE " << format(code.op0()) << ' '
117  << format(code.op1()) << '\n';
118  break;
119  }
120  else if(code.get_statement() == ID_array_set)
121  {
122  out << "ARRAY_SET " << format(code.op0()) << ' ' << format(code.op1())
123  << '\n';
124  break;
125  }
126  else if(code.get_statement() == ID_expression)
127  {
128  out << "EXPRESSION " << format(code.op0()) << '\n';
129  break;
130  }
131  else if(code.get_statement() == ID_havoc_object)
132  {
133  out << "HAVOC_OBJECT " << format(code.op0()) << '\n';
134  break;
135  }
136  else if(code.get_statement() == ID_fence)
137  {
138  out << "FENCE";
139  if(code.get_bool(ID_WWfence))
140  out << " WW";
141  if(code.get_bool(ID_RRfence))
142  out << " RR";
143  if(code.get_bool(ID_RWfence))
144  out << " RW";
145  if(code.get_bool(ID_WRfence))
146  out << " WR";
147  out << '\n';
148  break;
149  }
150  else if(code.get_statement() == ID_input)
151  {
152  out << "INPUT";
153  for(const auto &op : code.operands())
154  out << ' ' << format(op);
155  out << '\n';
156  break;
157  }
158  else if(code.get_statement() == ID_output)
159  {
160  out << "OUTPUT " << format(code.op0()) << '\n';
161  break;
162  }
163  // fallthrough
164  }
165 
166  out << "OTHER " << format(get_other()) << '\n';
167  break;
168 
169  case SET_RETURN_VALUE:
170  out << "SET RETURN VALUE " << format(return_value()) << '\n';
171  break;
172 
173  case DECL:
174  out << "DECL " << format(decl_symbol()) << " : "
175  << format(decl_symbol().type()) << '\n';
176  break;
177 
178  case DEAD:
179  out << "DEAD " << format(dead_symbol()) << '\n';
180  break;
181 
182  case FUNCTION_CALL:
183  out << "CALL ";
184  {
185  if(call_lhs().is_not_nil())
186  out << format(call_lhs()) << " := ";
187  out << format(call_function());
188  out << '(';
189  bool first = true;
190  for(const auto &argument : call_arguments())
191  {
192  if(first)
193  first = false;
194  else
195  out << ", ";
196  out << format(argument);
197  }
198  out << ')';
199  out << '\n';
200  }
201  break;
202 
203  case ASSIGN:
204  out << "ASSIGN " << format(assign_lhs()) << " := " << format(assign_rhs())
205  << '\n';
206  break;
207 
208  case ASSUME:
209  case ASSERT:
210  if(is_assume())
211  out << "ASSUME ";
212  else
213  out << "ASSERT ";
214 
215  {
216  out << format(condition());
217 
219  if(!comment.empty())
220  out << " // " << comment;
221  }
222 
223  out << '\n';
224  break;
225 
226  case SKIP:
227  out << "SKIP" << '\n';
228  break;
229 
230  case END_FUNCTION:
231  out << "END_FUNCTION" << '\n';
232  break;
233 
234  case LOCATION:
235  out << "LOCATION" << '\n';
236  break;
237 
238  case THROW:
239  out << "THROW";
240 
241  {
242  const irept::subt &exception_list =
243  code().find(ID_exception_list).get_sub();
244 
245  for(const auto &ex : exception_list)
246  out << " " << ex.id();
247  }
248 
249  if(code().operands().size() == 1)
250  out << ": " << format(code().op0());
251 
252  out << '\n';
253  break;
254 
255  case CATCH:
256  {
257  if(code().get_statement() == ID_exception_landingpad)
258  {
259  const auto &landingpad = to_code_landingpad(code());
260  out << "EXCEPTION LANDING PAD (" << format(landingpad.catch_expr().type())
261  << ' ' << format(landingpad.catch_expr()) << ")";
262  }
263  else if(code().get_statement() == ID_push_catch)
264  {
265  out << "CATCH-PUSH ";
266 
267  unsigned i=0;
268  const irept::subt &exception_list =
269  code().find(ID_exception_list).get_sub();
271  targets.size() == exception_list.size(),
272  "unexpected discrepancy between sizes of instruction"
273  "targets and exception list");
274  for(instructiont::targetst::const_iterator gt_it = targets.begin();
275  gt_it != targets.end();
276  gt_it++, i++)
277  {
278  if(gt_it != targets.begin())
279  out << ", ";
280  out << exception_list[i].id() << "->"
281  << (*gt_it)->target_number;
282  }
283  }
284  else if(code().get_statement() == ID_pop_catch)
285  {
286  out << "CATCH-POP";
287  }
288  else
289  {
290  UNREACHABLE;
291  }
292 
293  out << '\n';
294  break;
295  }
296 
297  case ATOMIC_BEGIN:
298  out << "ATOMIC_BEGIN" << '\n';
299  break;
300 
301  case ATOMIC_END:
302  out << "ATOMIC_END" << '\n';
303  break;
304 
305  case START_THREAD:
306  out << "START THREAD " << get_target()->target_number << '\n';
307  break;
308 
309  case END_THREAD:
310  out << "END THREAD" << '\n';
311  break;
312  }
313 
314  return out;
315 }
316 
318  decl_identifierst &decl_identifiers) const
319 {
320  for(const auto &instruction : instructions)
321  {
322  if(instruction.is_decl())
323  {
325  instruction.code().get_statement() == ID_decl,
326  "expected statement to be declaration statement");
328  instruction.code().operands().size() == 1,
329  "declaration statement expects one operand");
330  decl_identifiers.insert(instruction.decl_symbol().get_identifier());
331  }
332  }
333 }
334 
335 void parse_lhs_read(const exprt &src, std::list<exprt> &dest)
336 {
337  if(src.id()==ID_dereference)
338  {
339  dest.push_back(to_dereference_expr(src).pointer());
340  }
341  else if(src.id()==ID_index)
342  {
343  auto &index_expr = to_index_expr(src);
344  dest.push_back(index_expr.index());
345  parse_lhs_read(index_expr.array(), dest);
346  }
347  else if(src.id()==ID_member)
348  {
349  parse_lhs_read(to_member_expr(src).compound(), dest);
350  }
351  else if(src.id()==ID_if)
352  {
353  auto &if_expr = to_if_expr(src);
354  dest.push_back(if_expr.cond());
355  parse_lhs_read(if_expr.true_case(), dest);
356  parse_lhs_read(if_expr.false_case(), dest);
357  }
358 }
359 
360 std::list<exprt> expressions_read(
361  const goto_programt::instructiont &instruction)
362 {
363  std::list<exprt> dest;
364 
365  switch(instruction.type())
366  {
367  case ASSUME:
368  case ASSERT:
369  case GOTO:
370  dest.push_back(instruction.condition());
371  break;
372 
373  case SET_RETURN_VALUE:
374  dest.push_back(instruction.return_value());
375  break;
376 
377  case FUNCTION_CALL:
378  for(const auto &argument : instruction.call_arguments())
379  dest.push_back(argument);
380  if(instruction.call_lhs().is_not_nil())
381  parse_lhs_read(instruction.call_lhs(), dest);
382  break;
383 
384  case ASSIGN:
385  dest.push_back(instruction.assign_rhs());
386  parse_lhs_read(instruction.assign_lhs(), dest);
387  break;
388 
389  case CATCH:
390  case THROW:
391  case DEAD:
392  case DECL:
393  case ATOMIC_BEGIN:
394  case ATOMIC_END:
395  case START_THREAD:
396  case END_THREAD:
397  case END_FUNCTION:
398  case LOCATION:
399  case SKIP:
400  case OTHER:
401  case INCOMPLETE_GOTO:
402  case NO_INSTRUCTION_TYPE:
403  break;
404  }
405 
406  return dest;
407 }
408 
409 std::list<exprt> expressions_written(
410  const goto_programt::instructiont &instruction)
411 {
412  std::list<exprt> dest;
413 
414  switch(instruction.type())
415  {
416  case FUNCTION_CALL:
417  if(instruction.call_lhs().is_not_nil())
418  dest.push_back(instruction.call_lhs());
419  break;
420 
421  case ASSIGN:
422  dest.push_back(instruction.assign_lhs());
423  break;
424 
425  case CATCH:
426  case THROW:
427  case GOTO:
428  case SET_RETURN_VALUE:
429  case DEAD:
430  case DECL:
431  case ATOMIC_BEGIN:
432  case ATOMIC_END:
433  case START_THREAD:
434  case END_THREAD:
435  case END_FUNCTION:
436  case ASSERT:
437  case ASSUME:
438  case LOCATION:
439  case SKIP:
440  case OTHER:
441  case INCOMPLETE_GOTO:
442  case NO_INSTRUCTION_TYPE:
443  break;
444  }
445 
446  return dest;
447 }
448 
450  const exprt &src,
451  std::list<exprt> &dest)
452 {
453  if(src.id()==ID_symbol)
454  dest.push_back(src);
455  else if(src.id()==ID_address_of)
456  {
457  // don't traverse!
458  }
459  else if(src.id()==ID_dereference)
460  {
461  // this reads what is pointed to plus the pointer
462  auto &deref = to_dereference_expr(src);
463  dest.push_back(deref);
464  objects_read(deref.pointer(), dest);
465  }
466  else
467  {
468  forall_operands(it, src)
469  objects_read(*it, dest);
470  }
471 }
472 
473 std::list<exprt> objects_read(
474  const goto_programt::instructiont &instruction)
475 {
476  std::list<exprt> expressions=expressions_read(instruction);
477 
478  std::list<exprt> dest;
479 
480  for(const auto &expr : expressions)
481  objects_read(expr, dest);
482 
483  return dest;
484 }
485 
487  const exprt &src,
488  std::list<exprt> &dest)
489 {
490  if(src.id()==ID_if)
491  {
492  auto &if_expr = to_if_expr(src);
493  objects_written(if_expr.true_case(), dest);
494  objects_written(if_expr.false_case(), dest);
495  }
496  else
497  dest.push_back(src);
498 }
499 
500 std::list<exprt> objects_written(
501  const goto_programt::instructiont &instruction)
502 {
503  std::list<exprt> expressions=expressions_written(instruction);
504 
505  std::list<exprt> dest;
506 
507  for(const auto &expr : expressions)
508  objects_written(expr, dest);
509 
510  return dest;
511 }
512 
513 std::string as_string(
514  const class namespacet &ns,
515  const irep_idt &function,
517 {
518  std::string result;
519 
520  switch(i.type())
521  {
522  case NO_INSTRUCTION_TYPE:
523  return "(NO INSTRUCTION TYPE)";
524 
525  case GOTO:
526  if(!i.condition().is_true())
527  {
528  result += "IF " + from_expr(ns, function, i.condition()) + " THEN ";
529  }
530 
531  result+="GOTO ";
532 
533  for(goto_programt::instructiont::targetst::const_iterator
534  gt_it=i.targets.begin();
535  gt_it!=i.targets.end();
536  gt_it++)
537  {
538  if(gt_it!=i.targets.begin())
539  result+=", ";
540  result+=std::to_string((*gt_it)->target_number);
541  }
542  return result;
543 
544  case SET_RETURN_VALUE:
545  case OTHER:
546  case DECL:
547  case DEAD:
548  case FUNCTION_CALL:
549  case ASSIGN:
550  return from_expr(ns, function, i.code());
551 
552  case ASSUME:
553  case ASSERT:
554  if(i.is_assume())
555  result+="ASSUME ";
556  else
557  result+="ASSERT ";
558 
559  result += from_expr(ns, function, i.condition());
560 
561  {
563  if(!comment.empty())
564  result+=" /* "+id2string(comment)+" */";
565  }
566  return result;
567 
568  case SKIP:
569  return "SKIP";
570 
571  case END_FUNCTION:
572  return "END_FUNCTION";
573 
574  case LOCATION:
575  return "LOCATION";
576 
577  case THROW:
578  return "THROW";
579 
580  case CATCH:
581  return "CATCH";
582 
583  case ATOMIC_BEGIN:
584  return "ATOMIC_BEGIN";
585 
586  case ATOMIC_END:
587  return "ATOMIC_END";
588 
589  case START_THREAD:
590  result+="START THREAD ";
591 
592  if(i.targets.size()==1)
593  result+=std::to_string(i.targets.front()->target_number);
594  return result;
595 
596  case END_THREAD:
597  return "END THREAD";
598 
599  case INCOMPLETE_GOTO:
600  UNREACHABLE;
601  }
602 
603  UNREACHABLE;
604 }
605 
610 {
611  unsigned nr=0;
612  for(auto &i : instructions)
613  if(i.is_backwards_goto())
614  i.loop_number=nr++;
615 }
616 
618 {
623 }
624 
625 std::ostream &goto_programt::output(std::ostream &out) const
626 {
627  // output the program
628 
629  for(const auto &instruction : instructions)
630  instruction.output(out);
631 
632  return out;
633 }
634 
646 {
647  // reset marking
648 
649  for(auto &i : instructions)
650  i.target_number=instructiont::nil_target;
651 
652  // mark the goto targets
653 
654  for(const auto &i : instructions)
655  {
656  for(const auto &t : i.targets)
657  {
658  if(t!=instructions.end())
659  t->target_number=0;
660  }
661  }
662 
663  // number the targets properly
664  unsigned cnt=0;
665 
666  for(auto &i : instructions)
667  {
668  if(i.is_target())
669  {
670  i.target_number=++cnt;
672  i.target_number != 0, "GOTO instruction target cannot be zero");
673  }
674  }
675 
676  // check the targets!
677  // (this is a consistency check only)
678 
679  for(const auto &i : instructions)
680  {
681  for(const auto &t : i.targets)
682  {
683  if(t!=instructions.end())
684  {
686  t->target_number != 0, "instruction's number cannot be zero");
688  t->target_number != instructiont::nil_target,
689  "GOTO instruction target cannot be nil_target");
690  }
691  }
692  }
693 }
694 
700 {
701  // Definitions for mapping between the two programs
702  typedef std::map<const_targett, targett> targets_mappingt;
703  targets_mappingt targets_mapping;
704 
705  clear();
706 
707  // Loop over program - 1st time collects targets and copy
708 
709  for(instructionst::const_iterator
710  it=src.instructions.begin();
711  it!=src.instructions.end();
712  ++it)
713  {
714  auto new_instruction=add_instruction();
715  targets_mapping[it]=new_instruction;
716  *new_instruction=*it;
717  }
718 
719  // Loop over program - 2nd time updates targets
720 
721  for(auto &i : instructions)
722  {
723  for(auto &t : i.targets)
724  {
725  targets_mappingt::iterator
726  m_target_it=targets_mapping.find(t);
727 
728  CHECK_RETURN(m_target_it != targets_mapping.end());
729 
730  t=m_target_it->second;
731  }
732  }
733 
736 }
737 
741 {
742  for(const auto &i : instructions)
743  if(i.is_assert() && !i.condition().is_true())
744  return true;
745 
746  return false;
747 }
748 
751 {
752  for(auto &i : instructions)
753  {
754  i.incoming_edges.clear();
755  }
756 
757  for(instructionst::iterator
758  it=instructions.begin();
759  it!=instructions.end();
760  ++it)
761  {
762  for(const auto &s : get_successors(it))
763  {
764  if(s!=instructions.end())
765  s->incoming_edges.insert(it);
766  }
767  }
768 }
769 
771 {
772  // clang-format off
773  return
774  _type == other._type &&
775  _code == other._code &&
776  guard == other.guard &&
777  targets.size() == other.targets.size() &&
778  labels == other.labels;
779  // clang-format on
780 }
781 
783  const namespacet &ns,
784  const validation_modet vm) const
785 {
786  validate_full_code(_code, ns, vm);
787  validate_full_expr(guard, ns, vm);
788 
789  auto expr_symbol_finder = [&](const exprt &e) {
790  find_symbols_sett typetags;
791  find_type_and_expr_symbols(e, typetags);
792  const symbolt *symbol;
793  for(const auto &identifier : typetags)
794  {
796  vm,
797  !ns.lookup(identifier, symbol),
798  id2string(identifier) + " not found",
799  source_location());
800  }
801  };
802 
803  auto &current_source_location = source_location();
804  auto type_finder =
805  [&ns, vm, &current_source_location](const exprt &e) {
806  if(e.id() == ID_symbol)
807  {
808  const auto &goto_symbol_expr = to_symbol_expr(e);
809  const auto &goto_id = goto_symbol_expr.get_identifier();
810 
811  const symbolt *table_symbol;
812  if(!ns.lookup(goto_id, table_symbol))
813  {
814  bool symbol_expr_type_matches_symbol_table =
815  goto_symbol_expr.type() == table_symbol->type;
816 
817  if(
818  !symbol_expr_type_matches_symbol_table &&
819  table_symbol->type.id() == ID_code)
820  {
821  // If a function declaration and its definition are in different
822  // translation units they may have different return types.
823  // Thus, the return type in the symbol table may differ
824  // from the return type in the symbol expr.
825  if(
826  goto_symbol_expr.type().source_location().get_file() !=
827  table_symbol->type.source_location().get_file())
828  {
829  // temporarily fixup the return types
830  auto goto_symbol_expr_type =
831  to_code_type(goto_symbol_expr.type());
832  auto table_symbol_type = to_code_type(table_symbol->type);
833 
834  goto_symbol_expr_type.return_type() =
835  table_symbol_type.return_type();
836 
837  symbol_expr_type_matches_symbol_table =
838  goto_symbol_expr_type == table_symbol_type;
839  }
840  }
841 
842  if(
843  !symbol_expr_type_matches_symbol_table &&
844  goto_symbol_expr.type().id() == ID_array &&
845  to_array_type(goto_symbol_expr.type()).is_incomplete())
846  {
847  // If the symbol expr has an incomplete array type, it may not have
848  // a constant size value, whereas the symbol table entry may have
849  // an (assumed) constant size of 1 (which mimics gcc behaviour)
850  if(table_symbol->type.id() == ID_array)
851  {
852  auto symbol_table_array_type = to_array_type(table_symbol->type);
853  symbol_table_array_type.size() = nil_exprt();
854 
855  symbol_expr_type_matches_symbol_table =
856  goto_symbol_expr.type() == symbol_table_array_type;
857  }
858  }
859 
861  vm,
862  symbol_expr_type_matches_symbol_table,
863  id2string(goto_id) + " type inconsistency\n" +
864  "goto program type: " + goto_symbol_expr.type().id_string() +
865  "\n" + "symbol table type: " + table_symbol->type.id_string(),
866  current_source_location);
867  }
868  }
869  };
870 
871  const symbolt *table_symbol;
872  switch(_type)
873  {
874  case NO_INSTRUCTION_TYPE:
875  break;
876  case GOTO:
878  vm,
879  has_target(),
880  "goto instruction expects at least one target",
881  source_location());
882  // get_target checks that targets.size()==1
884  vm,
885  get_target()->is_target() && get_target()->target_number != 0,
886  "goto target has to be a target",
887  source_location());
888  break;
889  case ASSUME:
891  vm,
892  targets.empty(),
893  "assume instruction should not have a target",
894  source_location());
895  break;
896  case ASSERT:
898  vm,
899  targets.empty(),
900  "assert instruction should not have a target",
901  source_location());
902 
903  expr_symbol_finder(guard);
904  std::for_each(guard.depth_begin(), guard.depth_end(), type_finder);
905  break;
906  case OTHER:
907  break;
908  case SKIP:
909  break;
910  case START_THREAD:
911  break;
912  case END_THREAD:
913  break;
914  case LOCATION:
915  break;
916  case END_FUNCTION:
917  break;
918  case ATOMIC_BEGIN:
919  break;
920  case ATOMIC_END:
921  break;
922  case SET_RETURN_VALUE:
924  vm,
925  _code.get_statement() == ID_return,
926  "SET_RETURN_VALUE instruction should contain a return statement",
927  source_location());
928  break;
929  case ASSIGN:
930  DATA_CHECK(
931  vm,
932  _code.get_statement() == ID_assign,
933  "assign instruction should contain an assign statement");
934  DATA_CHECK(
935  vm, targets.empty(), "assign instruction should not have a target");
936  break;
937  case DECL:
939  vm,
940  _code.get_statement() == ID_decl,
941  "declaration instructions should contain a declaration statement",
942  source_location());
944  vm,
945  !ns.lookup(decl_symbol().get_identifier(), table_symbol),
946  "declared symbols should be known",
947  id2string(decl_symbol().get_identifier()),
948  source_location());
949  break;
950  case DEAD:
952  vm,
953  _code.get_statement() == ID_dead,
954  "dead instructions should contain a dead statement",
955  source_location());
957  vm,
958  !ns.lookup(dead_symbol().get_identifier(), table_symbol),
959  "removed symbols should be known",
960  id2string(dead_symbol().get_identifier()),
961  source_location());
962  break;
963  case FUNCTION_CALL:
965  vm,
966  _code.get_statement() == ID_function_call,
967  "function call instruction should contain a call statement",
968  source_location());
969 
970  expr_symbol_finder(_code);
971  std::for_each(_code.depth_begin(), _code.depth_end(), type_finder);
972  break;
973  case THROW:
974  break;
975  case CATCH:
976  break;
977  case INCOMPLETE_GOTO:
978  break;
979  }
980 }
981 
983  std::function<optionalt<exprt>(exprt)> f)
984 {
985  switch(_type)
986  {
987  case OTHER:
988  if(get_other().get_statement() == ID_expression)
989  {
990  auto new_expression = f(to_code_expression(get_other()).expression());
991  if(new_expression.has_value())
992  {
993  auto new_other = to_code_expression(get_other());
994  new_other.expression() = *new_expression;
995  set_other(new_other);
996  }
997  }
998  break;
999 
1000  case SET_RETURN_VALUE:
1001  {
1002  auto new_return_value = f(return_value());
1003  if(new_return_value.has_value())
1004  return_value() = *new_return_value;
1005  }
1006  break;
1007 
1008  case ASSIGN:
1009  {
1010  auto new_assign_lhs = f(assign_lhs());
1011  auto new_assign_rhs = f(assign_rhs());
1012  if(new_assign_lhs.has_value())
1013  assign_lhs_nonconst() = new_assign_lhs.value();
1014  if(new_assign_rhs.has_value())
1015  assign_rhs_nonconst() = new_assign_rhs.value();
1016  }
1017  break;
1018 
1019  case DECL:
1020  {
1021  auto new_symbol = f(decl_symbol());
1022  if(new_symbol.has_value())
1023  decl_symbol() = to_symbol_expr(*new_symbol);
1024  }
1025  break;
1026 
1027  case DEAD:
1028  {
1029  auto new_symbol = f(dead_symbol());
1030  if(new_symbol.has_value())
1031  dead_symbol() = to_symbol_expr(*new_symbol);
1032  }
1033  break;
1034 
1035  case FUNCTION_CALL:
1036  {
1037  auto new_lhs = f(as_const(*this).call_lhs());
1038  if(new_lhs.has_value())
1039  call_lhs() = *new_lhs;
1040 
1041  auto new_call_function = f(as_const(*this).call_function());
1042  if(new_call_function.has_value())
1043  call_function() = *new_call_function;
1044 
1045  exprt::operandst new_arguments = as_const(*this).call_arguments();
1046  bool argument_changed = false;
1047 
1048  for(auto &a : new_arguments)
1049  {
1050  auto new_a = f(a);
1051  if(new_a.has_value())
1052  {
1053  a = *new_a;
1054  argument_changed = true;
1055  }
1056  }
1057 
1058  if(argument_changed)
1059  call_arguments() = std::move(new_arguments);
1060  }
1061  break;
1062 
1063  case GOTO:
1064  case ASSUME:
1065  case ASSERT:
1066  case SKIP:
1067  case START_THREAD:
1068  case END_THREAD:
1069  case LOCATION:
1070  case END_FUNCTION:
1071  case ATOMIC_BEGIN:
1072  case ATOMIC_END:
1073  case THROW:
1074  case CATCH:
1075  case INCOMPLETE_GOTO:
1076  case NO_INSTRUCTION_TYPE:
1077  if(has_condition())
1078  {
1079  auto new_condition = f(condition());
1080  if(new_condition.has_value())
1081  condition_nonconst() = new_condition.value();
1082  }
1083  }
1084 }
1085 
1087  std::function<void(const exprt &)> f) const
1088 {
1089  switch(_type)
1090  {
1091  case OTHER:
1092  if(get_other().get_statement() == ID_expression)
1093  f(to_code_expression(get_other()).expression());
1094  break;
1095 
1096  case SET_RETURN_VALUE:
1097  f(return_value());
1098  break;
1099 
1100  case ASSIGN:
1101  f(assign_lhs());
1102  f(assign_rhs());
1103  break;
1104 
1105  case DECL:
1106  f(decl_symbol());
1107  break;
1108 
1109  case DEAD:
1110  f(dead_symbol());
1111  break;
1112 
1113  case FUNCTION_CALL:
1114  f(call_lhs());
1115  for(auto &a : call_arguments())
1116  f(a);
1117  break;
1118 
1119  case GOTO:
1120  case ASSUME:
1121  case ASSERT:
1122  case SKIP:
1123  case START_THREAD:
1124  case END_THREAD:
1125  case LOCATION:
1126  case END_FUNCTION:
1127  case ATOMIC_BEGIN:
1128  case ATOMIC_END:
1129  case THROW:
1130  case CATCH:
1131  case INCOMPLETE_GOTO:
1132  case NO_INSTRUCTION_TYPE:
1133  if(has_condition())
1134  f(condition());
1135  }
1136 }
1137 
1138 bool goto_programt::equals(const goto_programt &other) const
1139 {
1140  if(instructions.size() != other.instructions.size())
1141  return false;
1142 
1143  goto_programt::const_targett other_it = other.instructions.begin();
1144  for(const auto &ins : instructions)
1145  {
1146  if(!ins.equals(*other_it))
1147  return false;
1148 
1149  // the number of targets is the same as instructiont::equals returned "true"
1150  auto other_target_it = other_it->targets.begin();
1151  for(const auto &t : ins.targets)
1152  {
1153  if(
1154  t->location_number - ins.location_number !=
1155  (*other_target_it)->location_number - other_it->location_number)
1156  {
1157  return false;
1158  }
1159 
1160  ++other_target_it;
1161  }
1162 
1163  ++other_it;
1164  }
1165 
1166  return true;
1167 }
1168 
1170 std::ostream &operator<<(std::ostream &out, goto_program_instruction_typet t)
1171 {
1172  switch(t)
1173  {
1174  case NO_INSTRUCTION_TYPE:
1175  out << "NO_INSTRUCTION_TYPE";
1176  break;
1177  case GOTO:
1178  out << "GOTO";
1179  break;
1180  case ASSUME:
1181  out << "ASSUME";
1182  break;
1183  case ASSERT:
1184  out << "ASSERT";
1185  break;
1186  case OTHER:
1187  out << "OTHER";
1188  break;
1189  case DECL:
1190  out << "DECL";
1191  break;
1192  case DEAD:
1193  out << "DEAD";
1194  break;
1195  case SKIP:
1196  out << "SKIP";
1197  break;
1198  case START_THREAD:
1199  out << "START_THREAD";
1200  break;
1201  case END_THREAD:
1202  out << "END_THREAD";
1203  break;
1204  case LOCATION:
1205  out << "LOCATION";
1206  break;
1207  case END_FUNCTION:
1208  out << "END_FUNCTION";
1209  break;
1210  case ATOMIC_BEGIN:
1211  out << "ATOMIC_BEGIN";
1212  break;
1213  case ATOMIC_END:
1214  out << "ATOMIC_END";
1215  break;
1216  case SET_RETURN_VALUE:
1217  out << "SET_RETURN_VALUE";
1218  break;
1219  case ASSIGN:
1220  out << "ASSIGN";
1221  break;
1222  case FUNCTION_CALL:
1223  out << "FUNCTION_CALL";
1224  break;
1225  case THROW:
1226  out << "THROW";
1227  break;
1228  case CATCH:
1229  out << "CATCH";
1230  break;
1231  case INCOMPLETE_GOTO:
1232  out << "INCOMPLETE_GOTO";
1233  break;
1234  }
1235 
1236  return out;
1237 }
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
source_locationt::get_comment
const irep_idt & get_comment() const
Definition: source_location.h:70
format
static format_containert< T > format(const T &o)
Definition: format.h:37
DATA_CHECK
#define DATA_CHECK(vm, condition, message)
This macro takes a condition which denotes a well-formedness criterion on goto programs,...
Definition: validate.h:22
to_code_expression
code_expressiont & to_code_expression(codet &code)
Definition: std_code.h:1428
array_typet::is_incomplete
bool is_incomplete() const
Definition: std_types.h:817
source_locationt::as_string
std::string as_string() const
Definition: source_location.h:25
SET_RETURN_VALUE
@ SET_RETURN_VALUE
Definition: goto_program.h:45
goto_programt::instructiont::code
const goto_instruction_codet & code() const
Get the code represented by this instruction.
Definition: goto_program.h:195
find_type_and_expr_symbols
void find_type_and_expr_symbols(const exprt &src, find_symbols_sett &dest)
Find identifiers of the sub expressions with id ID_symbol, considering both free and bound variables,...
Definition: find_symbols.cpp:283
codet::op0
exprt & op0()
Definition: expr.h:125
goto_programt::instructiont::output
std::ostream & output(std::ostream &) const
Output this instruction to the given stream.
Definition: goto_program.cpp:47
goto_programt::instructiont::get_other
const goto_instruction_codet & get_other() const
Get the statement for OTHER.
Definition: goto_program.h:321
to_dereference_expr
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:716
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
goto_programt::compute_loop_numbers
void compute_loop_numbers()
Compute loop numbers.
Definition: goto_program.cpp:609
to_index_expr
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1478
to_if_expr
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2403
irept::find
const irept & find(const irep_idt &name) const
Definition: irep.cpp:106
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
goto_programt::update
void update()
Update all indices.
Definition: goto_program.cpp:617
goto_programt::instructiont::_code
goto_instruction_codet _code
Do not read or modify directly – use code() and code_nonconst() instead.
Definition: goto_program.h:184
goto_programt::copy_from
void copy_from(const goto_programt &src)
Copy a full goto program, preserving targets.
Definition: goto_program.cpp:699
goto_programt::instructiont::apply
void apply(std::function< void(const exprt &)>) const
Apply given function to all expressions.
Definition: goto_program.cpp:1086
invariant.h
goto_programt::instructiont::transform
void transform(std::function< optionalt< exprt >(exprt)>)
Apply given transformer to all expressions; no return value means no change needed.
Definition: goto_program.cpp:982
exprt
Base class for all expressions.
Definition: expr.h:55
goto_programt::get_decl_identifiers
void get_decl_identifiers(decl_identifierst &decl_identifiers) const
get the variables in decl statements
Definition: goto_program.cpp:317
goto_programt::has_assertion
bool has_assertion() const
Does the goto program have an assertion?
Definition: goto_program.cpp:740
as_string
std::string as_string(const class namespacet &ns, const irep_idt &function, const goto_programt::instructiont &i)
Definition: goto_program.cpp:513
DATA_CHECK_WITH_DIAGNOSTICS
#define DATA_CHECK_WITH_DIAGNOSTICS(vm, condition, message,...)
Definition: validate.h:37
to_string
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Definition: string_constraint.cpp:58
goto_programt::instructiont::targets
targetst targets
The list of successor instructions.
Definition: goto_program.h:394
goto_programt::instructiont::is_incomplete_goto
bool is_incomplete_goto() const
Definition: goto_program.h:481
goto_programt::get_successors
std::list< Target > get_successors(Target target) const
Get control-flow successors of a given instruction.
Definition: goto_program.h:1117
exprt::is_true
bool is_true() const
Return whether the expression is a constant representing true.
Definition: expr.cpp:34
expressions_written
std::list< exprt > expressions_written(const goto_programt::instructiont &instruction)
Definition: goto_program.cpp:409
goto_programt::instructiont::decl_symbol
const symbol_exprt & decl_symbol() const
Get the declared symbol for DECL.
Definition: goto_program.h:235
goto_programt::instructiont::call_arguments
const exprt::operandst & call_arguments() const
Get the arguments of a FUNCTION_CALL.
Definition: goto_program.h:307
coverage_criteriont::ASSUME
@ ASSUME
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
goto_programt::add_instruction
targett add_instruction()
Adds an instruction at the end.
Definition: goto_program.h:717
THROW
@ THROW
Definition: goto_program.h:50
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
coverage_criteriont::LOCATION
@ LOCATION
GOTO
@ GOTO
Definition: goto_program.h:34
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
goto_programt::equals
bool equals(const goto_programt &other) const
Syntactic equality: two goto_programt are equal if, and only if, they have the same number of instruc...
Definition: goto_program.cpp:1138
goto_programt::instructiont::validate
void validate(const namespacet &ns, const validation_modet vm) const
Check that the instruction is well-formed.
Definition: goto_program.cpp:782
as_const
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition: as_const.h:14
find_symbols.h
goto_programt::compute_target_numbers
void compute_target_numbers()
Compute the target numbers.
Definition: goto_program.cpp:645
goto_programt::instructiont::type
goto_program_instruction_typet type() const
What kind of instruction?
Definition: goto_program.h:351
validate_full_code
void validate_full_code(const codet &code, const namespacet &ns, const validation_modet vm)
Check that the given code statement is well-formed (full check, including checks of all subexpression...
Definition: validate_code.cpp:100
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
goto_programt::instructiont::dead_symbol
const symbol_exprt & dead_symbol() const
Get the symbol for DEAD.
Definition: goto_program.h:251
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
goto_programt::instructiont::source_location
const source_locationt & source_location() const
Definition: goto_program.h:340
operator<<
std::ostream & operator<<(std::ostream &out, goto_program_instruction_typet t)
Outputs a string representation of a goto_program_instruction_typet
Definition: goto_program.cpp:1170
get_identifier
static optionalt< smt_termt > get_identifier(const exprt &expr, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_handle_identifiers, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_identifiers)
Definition: smt2_incremental_decision_procedure.cpp:328
forall_operands
#define forall_operands(it, expr)
Definition: expr.h:20
language_util.h
code_gotot
codet representation of a goto statement.
Definition: std_code.h:840
typet::source_location
const source_locationt & source_location() const
Definition: type.h:90
objects_read
void objects_read(const exprt &src, std::list< exprt > &dest)
Definition: goto_program.cpp:449
goto_programt::instructiont::_type
goto_program_instruction_typet _type
Definition: goto_program.h:359
nil_exprt
The NIL expression.
Definition: std_expr.h:3025
pointer_expr.h
goto_programt::instructiont::labels
labelst labels
Definition: goto_program.h:419
goto_programt::instructiont::equals
bool equals(const instructiont &other) const
Syntactic equality: two instructiont are equal if they have the same type, code, guard,...
Definition: goto_program.cpp:770
goto_programt::output
std::ostream & output(const namespacet &ns, const irep_idt &identifier, std::ostream &out) const
Output goto program to given stream.
Definition: goto_program.h:731
irept::id_string
const std::string & id_string() const
Definition: irep.h:399
NO_INSTRUCTION_TYPE
@ NO_INSTRUCTION_TYPE
Definition: goto_program.h:33
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
OTHER
@ OTHER
Definition: goto_program.h:37
validation_modet
validation_modet
Definition: validation_mode.h:12
irept::id
const irep_idt & id() const
Definition: irep.h:396
objects_written
void objects_written(const exprt &src, std::list< exprt > &dest)
Definition: goto_program.cpp:486
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
goto_programt::instructiont::assign_rhs
const exprt & assign_rhs() const
Get the rhs of the assignment for ASSIGN.
Definition: goto_program.h:221
goto_programt::instructiont::call_lhs
const exprt & call_lhs() const
Get the lhs of a FUNCTION_CALL (may be nil)
Definition: goto_program.h:293
END_FUNCTION
@ END_FUNCTION
Definition: goto_program.h:42
SKIP
@ SKIP
Definition: goto_program.h:38
goto_programt::compute_incoming_edges
void compute_incoming_edges()
Compute for each instruction the set of instructions it is a successor of.
Definition: goto_program.cpp:750
std_code.h
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
sharing_treet< irept, forward_list_as_mapt< irep_idt, irept > >::subt
typename dt::subt subt
Definition: irep.h:160
goto_programt::clear
void clear()
Clear the goto program.
Definition: goto_program.h:811
goto_programt::instructiont::return_value
const exprt & return_value() const
Get the return value of a SET_RETURN_VALUE instruction.
Definition: goto_program.h:265
goto_program.h
goto_program_instruction_typet
goto_program_instruction_typet
The type of an instruction in a GOTO program.
Definition: goto_program.h:31
source_locationt
Definition: source_location.h:18
goto_programt::compute_location_numbers
void compute_location_numbers()
Compute location numbers.
Definition: goto_program.h:769
goto_programt::instructions
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:592
ASSIGN
@ ASSIGN
Definition: goto_program.h:46
format_expr.h
to_code_landingpad
static code_landingpadt & to_code_landingpad(codet &code)
Definition: std_code.h:1972
goto_programt::instructiont::target_number
unsigned target_number
A number to identify branch targets.
Definition: goto_program.h:538
CATCH
@ CATCH
Definition: goto_program.h:51
expr_iterator.h
find_symbols_sett
std::unordered_set< irep_idt > find_symbols_sett
Definition: find_symbols.h:21
DECL
@ DECL
Definition: goto_program.h:47
goto_programt::instructiont::assign_lhs
const exprt & assign_lhs() const
Get the lhs of the assignment for ASSIGN.
Definition: goto_program.h:207
goto_programt::instructiont::location_number
unsigned location_number
A globally unique number to identify a program location.
Definition: goto_program.h:531
symbolt
Symbol table entry.
Definition: symbol.h:27
expressions_read
std::list< exprt > expressions_read(const goto_programt::instructiont &instruction)
Definition: goto_program.cpp:360
goto_programt::instructiont::guard
exprt guard
Guard for gotos, assume, assert Use condition() method to access.
Definition: goto_program.h:363
irept::get_sub
subt & get_sub()
Definition: irep.h:456
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
START_THREAD
@ START_THREAD
Definition: goto_program.h:39
validate.h
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
validate_full_expr
void validate_full_expr(const exprt &expr, const namespacet &ns, const validation_modet vm)
Check that the given expression is well-formed (full check, including checks of all subexpressions an...
Definition: validate_expressions.cpp:114
source_locationt::get_file
const irep_idt & get_file() const
Definition: source_location.h:35
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
ATOMIC_END
@ ATOMIC_END
Definition: goto_program.h:44
goto_programt::const_targett
instructionst::const_iterator const_targett
Definition: goto_program.h:587
goto_programt::instructiont::condition
const exprt & condition() const
Get the condition of gotos, assume, assert.
Definition: goto_program.h:373
DEAD
@ DEAD
Definition: goto_program.h:48
exprt::operands
operandst & operands()
Definition: expr.h:94
validate_code.h
codet::op1
exprt & op1()
Definition: expr.h:128
ATOMIC_BEGIN
@ ATOMIC_BEGIN
Definition: goto_program.h:43
goto_programt::instructiont::is_assume
bool is_assume() const
Definition: goto_program.h:474
symbol_table.h
Author: Diffblue Ltd.
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
ASSERT
@ ASSERT
Definition: goto_program.h:36
goto_programt::decl_identifierst
std::set< irep_idt > decl_identifierst
Definition: goto_program.h:844
comment
static std::string comment(const rw_set_baset::entryt &entry, bool write)
Definition: race_check.cpp:109
goto_programt::instructiont
This class represents an instruction in the GOTO intermediate representation.
Definition: goto_program.h:180
std_expr.h
goto_programt::instructiont::is_target
bool is_target() const
Is this node a branch target?
Definition: goto_program.h:425
from_expr
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
Definition: language_util.cpp:38
goto_programt::instructiont::nil_target
static const unsigned nil_target
Uniquely identify an invalid target or location.
Definition: goto_program.h:525
goto_programt::instructiont::call_function
const exprt & call_function() const
Get the function that is called for FUNCTION_CALL.
Definition: goto_program.h:279
format_type.h
goto_programt::instructiont::get_target
targett get_target() const
Returns the first (and only) successor for the usual case of a single target.
Definition: goto_program.h:398
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_programt::make_incomplete_goto
static instructiont make_incomplete_goto(const exprt &_cond, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:1002
parse_lhs_read
void parse_lhs_read(const exprt &src, std::list< exprt > &dest)
Definition: goto_program.cpp:335