CBMC
dump_c.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 "dump_c.h"
13 #include "dump_c_class.h"
14 
15 #include <util/byte_operators.h>
16 #include <util/c_types.h>
17 #include <util/config.h>
18 #include <util/expr_initializer.h>
19 #include <util/expr_util.h>
20 #include <util/find_symbols.h>
21 #include <util/get_base_name.h>
22 #include <util/invariant.h>
23 #include <util/prefix.h>
24 #include <util/replace_symbol.h>
25 #include <util/string_utils.h>
26 
27 #include <ansi-c/expr2c.h>
28 #include <ansi-c/type2name.h>
29 #include <cpp/cpp_type2name.h>
30 #include <cpp/expr2cpp.h>
32 
33 #include "goto_program2code.h"
34 
35 static std::string clean_identifier(const irep_idt &id)
36 {
37  std::string result;
38  result.reserve(id2string(id).size());
39 
40  for(auto c : id2string(id))
41  {
42  if(c >= '0' && c <= '9')
43  result += c;
44  else if(c >= 'A' && c <= 'Z')
45  result += c;
46  else if(c >= 'a' && c <= 'z')
47  result += c;
48  else if(c == '_' || c == '$')
49  result += c;
50  else
51  result += "_" + std::to_string(c);
52  }
53 
54  return result;
55 }
56 
59 
66 
67 inline std::ostream &operator << (std::ostream &out, dump_ct &src)
68 {
69  src(out);
70  return out;
71 }
72 
73 void dump_ct::operator()(std::ostream &os)
74 {
75  std::stringstream func_decl_stream;
76  std::stringstream compound_body_stream;
77  std::stringstream global_var_stream;
78  std::stringstream global_decl_stream;
79  std::stringstream global_decl_header_stream;
80  std::stringstream func_body_stream;
81  local_static_declst local_static_decls;
82 
83  // add copies of struct types when ID_C_transparent_union is only
84  // annotated to parameter
85  symbol_tablet additional_symbols;
86  for(auto it = copied_symbol_table.begin(); it != copied_symbol_table.end();
87  ++it)
88  {
89  const symbolt &symbol = it->second;
90 
91  if(
92  (symbol.type.id() == ID_union || symbol.type.id() == ID_struct) &&
93  !symbol.is_type)
94  {
95  std::string tag_name;
96  if(mode == ID_C)
97  tag_name = "tag-" + type2name(symbol.type, ns);
98  else if(mode == ID_cpp)
99  tag_name = "tag-" + cpp_type2name(symbol.type);
100  else
101  UNREACHABLE;
102  type_symbolt ts{tag_name, symbol.type, symbol.mode};
103  typet &type = it.get_writeable_symbol().type;
104  if(ts.type.id() == ID_union)
105  type = union_tag_typet{ts.name};
106  else
107  type = struct_tag_typet{ts.name};
108  additional_symbols.add(ts);
109  }
110 
111  if(symbol.type.id()!=ID_code)
112  continue;
113 
114  code_typet &code_type = to_code_type(it.get_writeable_symbol().type);
115  code_typet::parameterst &parameters=code_type.parameters();
116 
117  for(code_typet::parameterst::iterator
118  it2=parameters.begin();
119  it2!=parameters.end();
120  ++it2)
121  {
122  typet &type=it2->type();
123 
124  if(type.id() == ID_union_tag && type.get_bool(ID_C_transparent_union))
125  {
126  symbolt new_type_sym =
127  ns.lookup(to_union_tag_type(type).get_identifier());
128 
129  new_type_sym.name=id2string(new_type_sym.name)+"$transparent";
130  new_type_sym.type.set(ID_C_transparent_union, true);
131 
132  // we might have it already, in which case this has no effect
133  additional_symbols.add(new_type_sym);
134 
135  to_union_tag_type(type).set_identifier(new_type_sym.name);
136  type.remove(ID_C_transparent_union);
137  }
138  }
139  }
140  for(const auto &symbol_pair : additional_symbols.symbols)
141  {
142  copied_symbol_table.add(symbol_pair.second);
143  }
144 
145  typedef std::unordered_map<irep_idt, unsigned> unique_tagst;
146  unique_tagst unique_tags;
147 
148  // add tags to anonymous union/struct/enum,
149  // and prepare lexicographic order
150  std::set<std::string> symbols_sorted;
151  for(auto it = copied_symbol_table.begin(); it != copied_symbol_table.end();
152  ++it)
153  {
154  symbolt &symbol = it.get_writeable_symbol();
155  bool tag_added=false;
156 
157  // TODO we could get rid of some of the ID_anonymous by looking up
158  // the origin symbol types in typedef_types and adjusting any other
159  // uses of ID_tag
160  if((symbol.type.id()==ID_union || symbol.type.id()==ID_struct) &&
161  symbol.type.get(ID_tag).empty())
162  {
163  PRECONDITION(symbol.is_type);
164  symbol.type.set(ID_tag, ID_anonymous);
165  tag_added=true;
166  }
167  else if(symbol.type.id()==ID_c_enum &&
168  symbol.type.find(ID_tag).get(ID_C_base_name).empty())
169  {
170  PRECONDITION(symbol.is_type);
171  symbol.type.add(ID_tag).set(ID_C_base_name, ID_anonymous);
172  tag_added=true;
173  }
174 
175  const std::string name_str = id2string(it->first);
176  if(symbol.is_type &&
177  (symbol.type.id()==ID_union ||
178  symbol.type.id()==ID_struct ||
179  symbol.type.id()==ID_c_enum))
180  {
181  std::string new_tag=symbol.type.id()==ID_c_enum?
182  symbol.type.find(ID_tag).get_string(ID_C_base_name):
183  symbol.type.get_string(ID_tag);
184 
185  std::string::size_type tag_pos=new_tag.rfind("tag-");
186  if(tag_pos!=std::string::npos)
187  new_tag.erase(0, tag_pos+4);
188  const std::string new_tag_base=new_tag;
189 
190  for(std::pair<unique_tagst::iterator, bool>
191  unique_entry=unique_tags.insert(std::make_pair(new_tag, 0));
192  !unique_entry.second;
193  unique_entry=unique_tags.insert(std::make_pair(new_tag, 0)))
194  {
195  new_tag=new_tag_base+"$"+
196  std::to_string(unique_entry.first->second);
197  ++(unique_entry.first->second);
198  }
199 
200  if(symbol.type.id()==ID_c_enum)
201  {
202  symbol.type.add(ID_tag).set(ID_C_base_name, new_tag);
203  symbol.base_name=new_tag;
204  }
205  else
206  symbol.type.set(ID_tag, new_tag);
207  }
208 
209  // we don't want to dump in full all definitions; in particular
210  // do not dump anonymous types that are defined in system headers
211  if(
212  (!tag_added || symbol.is_type) &&
214  symbol.name != goto_functions.entry_point() &&
215  symbol.name != CPROVER_PREFIX "arg_string") // model for argc/argv
216  {
217  continue;
218  }
219 
220  bool inserted=symbols_sorted.insert(name_str).second;
221  CHECK_RETURN(inserted);
222  }
223 
225 
226  // collect all declarations we might need, include local static variables
227  bool skip_function_main=false;
228  std::vector<std::string> header_files;
229  for(std::set<std::string>::const_iterator
230  it=symbols_sorted.begin();
231  it!=symbols_sorted.end();
232  ++it)
233  {
234  const symbolt &symbol=ns.lookup(*it);
235  const irep_idt &type_id=symbol.type.id();
236 
237  if(symbol.is_type &&
238  symbol.location.get_function().empty() &&
239  (type_id==ID_struct ||
240  type_id==ID_union ||
241  type_id==ID_c_enum))
242  {
244  {
245  global_decl_stream << "// " << symbol.name << '\n';
246  global_decl_stream << "// " << symbol.location << '\n';
247 
248  std::string location_file =
249  get_base_name(id2string(symbol.location.get_file()), false);
250  // collect header the types are borrowed from
251  // expect header files to end in .h
252  if(
253  location_file.length() > 1 &&
254  location_file[location_file.length() - 1] == 'h')
255  {
256  std::vector<std::string>::iterator it =
257  find(header_files.begin(), header_files.end(), location_file);
258  if(it == header_files.end())
259  {
260  header_files.push_back(location_file);
261  global_decl_header_stream << "#include \"" << location_file
262  << "\"\n";
263  }
264  }
265 
266  if(type_id==ID_c_enum)
267  convert_compound_enum(symbol.type, global_decl_stream);
268  else if(type_id == ID_struct)
269  {
270  global_decl_stream << type_to_string(struct_tag_typet{symbol.name})
271  << ";\n\n";
272  }
273  else
274  {
275  global_decl_stream << type_to_string(union_tag_typet{symbol.name})
276  << ";\n\n";
277  }
278  }
279  }
280  else if(
281  symbol.is_static_lifetime && symbol.type.id() != ID_code &&
282  !symbol.type.get_bool(ID_C_do_not_dump))
284  symbol,
285  global_var_stream,
286  local_static_decls);
287  else if(symbol.type.id()==ID_code)
288  {
289  goto_functionst::function_mapt::const_iterator func_entry=
290  goto_functions.function_map.find(symbol.name);
291 
292  if(
293  !harness && func_entry != goto_functions.function_map.end() &&
294  func_entry->second.body_available() &&
295  (symbol.name == ID_main ||
296  (config.main.has_value() && symbol.name == config.main.value())))
297  {
298  skip_function_main=true;
299  }
300  }
301  }
302 
303  // function declarations and definitions
304  for(std::set<std::string>::const_iterator
305  it=symbols_sorted.begin();
306  it!=symbols_sorted.end();
307  ++it)
308  {
309  const symbolt &symbol=ns.lookup(*it);
310 
311  if(symbol.type.id()!=ID_code ||
312  symbol.is_type)
313  continue;
314 
316  symbol,
317  skip_function_main,
318  func_decl_stream,
319  func_body_stream,
320  local_static_decls);
321  }
322 
323  // (possibly modified) compound types
324  for(std::set<std::string>::const_iterator
325  it=symbols_sorted.begin();
326  it!=symbols_sorted.end();
327  ++it)
328  {
329  const symbolt &symbol=ns.lookup(*it);
330 
331  if(
332  symbol.is_type &&
333  (symbol.type.id() == ID_struct || symbol.type.id() == ID_union) &&
335  {
337  symbol,
338  compound_body_stream);
339  }
340  }
341 
342  // Dump the code to the target stream;
343  // the statements before to this point collect the code to dump!
344  for(std::set<std::string>::const_iterator
345  it=system_headers.begin();
346  it!=system_headers.end();
347  ++it)
348  os << "#include <" << *it << ">\n";
349  if(!system_headers.empty())
350  os << '\n';
351 
352  if(!global_decl_header_stream.str().empty() && dump_c_config.include_headers)
353  os << global_decl_header_stream.str() << '\n';
354 
355  if(global_var_stream.str().find("NULL")!=std::string::npos ||
356  func_body_stream.str().find("NULL")!=std::string::npos)
357  {
358  os << "#ifndef NULL\n"
359  << "#define NULL ((void*)0)\n"
360  << "#endif\n\n";
361  }
362  if(func_body_stream.str().find("FENCE")!=std::string::npos)
363  {
364  os << "#ifndef FENCE\n"
365  << "#define FENCE(x) ((void)0)\n"
366  << "#endif\n\n";
367  }
368  if(func_body_stream.str().find("IEEE_FLOAT_")!=std::string::npos)
369  {
370  os << "#ifndef IEEE_FLOAT_EQUAL\n"
371  << "#define IEEE_FLOAT_EQUAL(x,y) ((x)==(y))\n"
372  << "#endif\n"
373  << "#ifndef IEEE_FLOAT_NOTEQUAL\n"
374  << "#define IEEE_FLOAT_NOTEQUAL(x,y) ((x)!=(y))\n"
375  << "#endif\n\n";
376  }
377 
378  if(!global_decl_stream.str().empty() && dump_c_config.include_global_decls)
379  os << global_decl_stream.str() << '\n';
380 
382  dump_typedefs(os);
383 
384  if(!func_decl_stream.str().empty() && dump_c_config.include_function_decls)
385  os << func_decl_stream.str() << '\n';
386  if(!compound_body_stream.str().empty() && dump_c_config.include_compounds)
387  os << compound_body_stream.str() << '\n';
388  if(!global_var_stream.str().empty() && dump_c_config.include_global_vars)
389  os << global_var_stream.str() << '\n';
391  os << func_body_stream.str();
392 }
393 
396  const symbolt &symbol,
397  std::ostream &os_body)
398 {
399  if(
400  !symbol.location.get_function().empty() ||
401  symbol.type.get_bool(ID_C_do_not_dump))
402  {
403  return;
404  }
405 
406  // do compound type body
407  if(symbol.type.id() == ID_struct)
409  symbol.type,
410  struct_tag_typet(symbol.name),
412  os_body);
413  else if(symbol.type.id() == ID_union)
415  symbol.type,
416  union_tag_typet(symbol.name),
418  os_body);
419  else if(symbol.type.id() == ID_c_enum)
421  symbol.type,
422  c_enum_tag_typet(symbol.name),
424  os_body);
425 }
426 
428  const typet &type,
429  const typet &unresolved,
430  bool recursive,
431  std::ostream &os)
432 {
433  if(
434  type.id() == ID_c_enum_tag || type.id() == ID_struct_tag ||
435  type.id() == ID_union_tag)
436  {
437  const symbolt &symbol = ns.lookup(to_tag_type(type));
438  DATA_INVARIANT(symbol.is_type, "tag expected to be type symbol");
439 
441  convert_compound(symbol.type, unresolved, recursive, os);
442  }
443  else if(type.id()==ID_array || type.id()==ID_pointer)
444  {
445  if(!recursive)
446  return;
447 
449  to_type_with_subtype(type).subtype(),
450  to_type_with_subtype(type).subtype(),
451  recursive,
452  os);
453 
454  // sizeof may contain a type symbol that has to be declared first
455  if(type.id()==ID_array)
456  {
457  find_symbols_sett syms;
458  find_non_pointer_type_symbols(to_array_type(type).size(), syms);
459 
460  for(find_symbols_sett::const_iterator
461  it=syms.begin();
462  it!=syms.end();
463  ++it)
464  {
465  const symbolt &type_symbol = ns.lookup(*it);
466  irep_idt tag_kind =
467  type_symbol.type.id() == ID_c_enum
468  ? ID_c_enum_tag
469  : (type_symbol.type.id() == ID_union ? ID_union_tag
470  : ID_struct_tag);
471  tag_typet s_type(tag_kind, *it);
472  convert_compound(s_type, s_type, recursive, os);
473  }
474  }
475  }
476  else if(type.id()==ID_struct || type.id()==ID_union)
477  convert_compound(to_struct_union_type(type), unresolved, recursive, os);
478  else if(type.id()==ID_c_enum)
479  convert_compound_enum(type, os);
480 }
481 
483  const struct_union_typet &type,
484  const typet &unresolved,
485  bool recursive,
486  std::ostream &os)
487 {
488  const irep_idt &name=type.get(ID_tag);
489 
490  if(!converted_compound.insert(name).second || type.get_bool(ID_C_do_not_dump))
491  return;
492 
493  // make sure typedef names used in the declaration are available
494  collect_typedefs(type, true);
495 
496  const irept &bases = type.find(ID_bases);
497  std::stringstream base_decls;
498  for(const auto &parent : bases.get_sub())
499  {
500  UNREACHABLE;
501  (void)parent;
502 #if 0
503  assert(parent.id() == ID_base);
504  assert(parent.get(ID_type) == ID_struct_tag);
505 
506  const irep_idt &base_id=
507  parent.find(ID_type).get(ID_identifier);
508  const irep_idt &renamed_base_id=global_renaming[base_id];
509  const symbolt &parsymb=ns.lookup(renamed_base_id);
510 
511  convert_compound_rec(parsymb.type, os);
512 
513  base_decls << id2string(renamed_base_id) +
514  (parent_it+1==bases.get_sub().end()?"":", ");
515 #endif
516  }
517 
518 #if 0
519  // for the constructor
520  string constructor_args;
521  string constructor_body;
522 
523  std::string component_name = id2string(renaming[compo.get(ID_name)]);
524  assert(component_name != "");
525 
526  if(it != struct_type.components().begin()) constructor_args += ", ";
527 
528  if(compo.type().id() == ID_pointer)
529  constructor_args += type_to_string(compo.type()) + component_name;
530  else
531  constructor_args += "const " + type_to_string(compo.type()) + "& " + component_name;
532 
533  constructor_body += indent + indent + "this->"+component_name + " = " + component_name + ";\n";
534 #endif
535 
536  std::stringstream struct_body;
537 
538  for(const auto &comp : type.components())
539  {
540  const typet &comp_type = comp.type();
541 
543  comp_type.id() != ID_code, "struct member must not be of code type");
544 
545  if(comp.get_bool(ID_from_base) || comp.get_is_padding())
546  continue;
547 
548  const typet *non_array_type = &comp_type;
549  while(non_array_type->id()==ID_array)
550  non_array_type = &(to_array_type(*non_array_type).element_type());
551 
552  bool is_anon =
553  can_cast_type<tag_typet>(comp.type()) &&
554  has_prefix(
555  id2string(to_tag_type(comp.type()).get_identifier()), "tag-#anon");
556 
557  if(recursive)
558  {
559  if(non_array_type->id() != ID_pointer && !is_anon)
560  convert_compound(comp.type(), comp.type(), recursive, os);
561  else
562  collect_typedefs(comp.type(), true);
563  }
564 
565  struct_body << indent(1) << "// " << comp.get_name() << '\n';
566  struct_body << indent(1);
567 
568  irep_idt comp_name = clean_identifier(comp.get_name());
569 
570  // component names such as "main" would collide with other objects in the
571  // namespace
572  std::string fake_unique_name="NO/SUCH/NS::"+id2string(comp_name);
573  typet comp_type_to_use = comp.type();
574  if(is_anon)
575  {
576  comp_type_to_use =
577  (comp.type().id() == ID_struct_tag || comp.type().id() == ID_union_tag)
579  : comp.type();
580  comp_type_to_use.remove(ID_tag);
581  if(
582  recursive && (comp_type_to_use.id() == ID_struct ||
583  comp_type_to_use.id() == ID_union))
584  {
585  const auto &sub_comps =
586  to_struct_union_type(comp_type_to_use).components();
587  for(const auto &sc : sub_comps)
588  convert_compound(sc.type(), sc.type(), recursive, os);
589  }
590  }
591  std::string s = make_decl(fake_unique_name, comp_type_to_use);
592  POSTCONDITION(s.find("NO/SUCH/NS")==std::string::npos);
593 
594  if(comp_type.id()==ID_c_bit_field &&
595  to_c_bit_field_type(comp_type).get_width()==0)
596  {
597  comp_name.clear();
598  s=type_to_string(comp_type);
599  }
600 
601  if(s.find(CPROVER_PREFIX "bitvector") == std::string::npos)
602  {
603  struct_body << s;
604  }
605  else if(comp_type.id()==ID_signedbv)
606  {
607  const signedbv_typet &t=to_signedbv_type(comp_type);
609  struct_body << "long long int " << comp_name
610  << " : " << t.get_width();
611  else if(mode == ID_cpp)
612  struct_body << "__signedbv<" << t.get_width() << "> "
613  << comp_name;
614  else
615  struct_body << s;
616  }
617  else if(comp_type.id()==ID_unsignedbv)
618  {
619  const unsignedbv_typet &t=to_unsignedbv_type(comp_type);
621  struct_body << "unsigned long long " << comp_name
622  << " : " << t.get_width();
623  else if(mode == ID_cpp)
624  struct_body << "__unsignedbv<" << t.get_width() << "> "
625  << comp_name;
626  else
627  struct_body << s;
628  }
629  else
630  UNREACHABLE;
631 
632  struct_body << ";\n";
633  }
634 
635  typet unresolved_clean=unresolved;
636  irep_idt typedef_str;
637  for(auto td_entry : typedef_types)
638  {
639  if(
640  td_entry.first.get(ID_identifier) == unresolved.get(ID_identifier) &&
641  (td_entry.first.source_location() == unresolved.source_location()))
642  {
643  unresolved_clean.remove(ID_C_typedef);
644  typedef_str = td_entry.second;
645  std::pair<typedef_mapt::iterator, bool> td_map_entry =
646  typedef_map.insert({typedef_str, typedef_infot(typedef_str)});
647  PRECONDITION(!td_map_entry.second);
648  if(!td_map_entry.first->second.early)
649  td_map_entry.first->second.type_decl_str.clear();
650  os << "typedef ";
651  break;
652  }
653  }
654 
655  os << type_to_string(unresolved_clean);
656  if(!base_decls.str().empty())
657  {
658  PRECONDITION(mode == ID_cpp);
659  os << ": " << base_decls.str();
660  }
661  os << '\n';
662  os << "{\n";
663  os << struct_body.str();
664 
665  /*
666  if(!struct_type.components().empty())
667  {
668  os << indent << name << "(){}\n";
669  os << indent << "explicit " << name
670  << "(" + constructor_args + ")\n";
671  os << indent << "{\n";
672  os << constructor_body;
673  os << indent << "}\n";
674  }
675  */
676 
677  os << "}";
678  if(type.get_bool(ID_C_transparent_union))
679  os << " __attribute__ ((__transparent_union__))";
680  if(type.get_bool(ID_C_packed))
681  os << " __attribute__ ((__packed__))";
682  if(!typedef_str.empty())
683  os << " " << typedef_str;
684  os << ";\n\n";
685 }
686 
688  const typet &type,
689  std::ostream &os)
690 {
691  PRECONDITION(type.id()==ID_c_enum);
692 
693  const irept &tag=type.find(ID_tag);
694  const irep_idt &name=tag.get(ID_C_base_name);
695 
696  if(tag.is_nil() ||
697  !converted_enum.insert(name).second)
698  return;
699 
700  c_enum_typet enum_type=to_c_enum_type(type);
701  c_enum_typet::memberst &members=
702  (c_enum_typet::memberst &)(enum_type.add(ID_body).get_sub());
703  for(c_enum_typet::memberst::iterator
704  it=members.begin();
705  it!=members.end();
706  ++it)
707  {
708  const irep_idt bn=it->get_base_name();
709 
710  if(declared_enum_constants.find(bn)!=
711  declared_enum_constants.end() ||
713  {
714  std::string new_bn=id2string(name)+"$$"+id2string(bn);
715  it->set_base_name(new_bn);
716  }
717 
719  std::make_pair(bn, it->get_base_name()));
720  }
721 
722  os << type_to_string(enum_type);
723 
724  if(enum_type.get_bool(ID_C_packed))
725  os << " __attribute__ ((__packed__))";
726 
727  os << ";\n\n";
728 }
729 
731  code_frontend_declt &decl,
732  std::list<irep_idt> &local_static,
733  std::list<irep_idt> &local_type_decls)
734 {
735  goto_programt tmp;
736  tmp.add(goto_programt::make_decl(decl.symbol()));
737 
738  if(std::optional<exprt> value = decl.initial_value())
739  {
740  decl.set_initial_value({});
741  tmp.add(goto_programt::make_assignment(decl.symbol(), std::move(*value)));
742  }
743 
745 
746  // goto_program2codet requires valid location numbers:
747  tmp.update();
748 
749  std::unordered_set<irep_idt> typedef_names;
750  for(const auto &td : typedef_map)
751  typedef_names.insert(td.first);
752 
753  code_blockt b;
754  goto_program2codet p2s(
755  irep_idt(),
756  tmp,
758  b,
759  local_static,
760  local_type_decls,
761  typedef_names,
763  p2s();
764 
765  POSTCONDITION(b.statements().size() == 1);
766  decl.swap(b.op0());
767 }
768 
774 void dump_ct::collect_typedefs(const typet &type, bool early)
775 {
776  std::unordered_set<irep_idt> deps;
777  collect_typedefs_rec(type, early, deps);
778 }
779 
788  const typet &type,
789  bool early,
790  std::unordered_set<irep_idt> &dependencies)
791 {
792  std::unordered_set<irep_idt> local_deps;
793 
794  if(type.id()==ID_code)
795  {
796  const code_typet &code_type=to_code_type(type);
797 
798  collect_typedefs_rec(code_type.return_type(), early, local_deps);
799  for(const auto &param : code_type.parameters())
800  collect_typedefs_rec(param.type(), early, local_deps);
801  }
802  else if(type.id()==ID_pointer || type.id()==ID_array)
803  {
805  to_type_with_subtype(type).subtype(), early, local_deps);
806  }
807  else if(
808  type.id() == ID_c_enum_tag || type.id() == ID_struct_tag ||
809  type.id() == ID_union_tag)
810  {
811  const symbolt &symbol = ns.lookup(to_tag_type(type));
812  collect_typedefs_rec(symbol.type, early, local_deps);
813  }
814 
815  const irep_idt &typedef_str=type.get(ID_C_typedef);
816 
817  if(!typedef_str.empty())
818  {
819  std::pair<typedef_mapt::iterator, bool> entry=
820  typedef_map.insert({typedef_str, typedef_infot(typedef_str)});
821 
822  if(entry.second ||
823  (early && entry.first->second.type_decl_str.empty()))
824  {
825  if(typedef_str=="__gnuc_va_list" || typedef_str == "va_list")
826  {
827  system_headers.insert("stdarg.h");
828  early=false;
829  }
830  else
831  {
832  typet t=type;
833  t.remove(ID_C_typedef);
834 
835  std::ostringstream oss;
836  oss << "typedef " << make_decl(typedef_str, t) << ';';
837 
838  entry.first->second.type_decl_str=oss.str();
839  entry.first->second.dependencies=local_deps;
840  }
841  }
842 
843  if(early)
844  {
845  entry.first->second.early=true;
846 
847  for(const auto &d : local_deps)
848  {
849  auto td_entry=typedef_map.find(d);
850  PRECONDITION(td_entry!=typedef_map.end());
851  td_entry->second.early=true;
852  }
853  }
854 
855  dependencies.insert(typedef_str);
856  }
857 
858  dependencies.insert(local_deps.begin(), local_deps.end());
859 }
860 
863 {
864  // sort the symbols first to ensure deterministic replacement in
865  // typedef_types below as there could be redundant declarations
866  // typedef int x;
867  // typedef int y;
868  std::map<std::string, symbolt> symbols_sorted;
869  for(const auto &symbol_entry : copied_symbol_table.symbols)
870  symbols_sorted.insert(
871  {id2string(symbol_entry.first), symbol_entry.second});
872 
873  for(const auto &symbol_entry : symbols_sorted)
874  {
875  const symbolt &symbol=symbol_entry.second;
876 
877  if(symbol.is_macro && symbol.is_type &&
878  symbol.location.get_function().empty())
879  {
880  const irep_idt &typedef_str=symbol.type.get(ID_C_typedef);
881  PRECONDITION(!typedef_str.empty());
882  typedef_types[symbol.type]=typedef_str;
884  typedef_map.insert({typedef_str, typedef_infot(typedef_str)});
885  else
886  collect_typedefs(symbol.type, false);
887  }
888  }
889 }
890 
893 void dump_ct::dump_typedefs(std::ostream &os) const
894 {
895  // we need to compute a topological sort; we do so by picking all
896  // typedefs the dependencies of which have been emitted into to_insert
897  std::vector<typedef_infot> typedefs_sorted;
898  typedefs_sorted.reserve(typedef_map.size());
899 
900  // elements in to_insert are lexicographically sorted and ready for
901  // output
902  std::map<std::string, typedef_infot> to_insert;
903 
904  std::unordered_set<irep_idt> typedefs_done;
905  std::unordered_map<irep_idt, std::unordered_set<irep_idt>> forward_deps,
906  reverse_deps;
907 
908  for(const auto &td : typedef_map)
909  if(!td.second.type_decl_str.empty())
910  {
911  if(td.second.dependencies.empty())
912  // those can be dumped immediately
913  to_insert.insert({id2string(td.first), td.second});
914  else
915  {
916  // delay them until dependencies are dumped
917  forward_deps.insert({td.first, td.second.dependencies});
918  for(const auto &d : td.second.dependencies)
919  reverse_deps[d].insert(td.first);
920  }
921  }
922 
923  while(!to_insert.empty())
924  {
925  // the topologically next element (lexicographically ranked first
926  // among all the dependencies of which have been dumped)
927  typedef_infot t=to_insert.begin()->second;
928  to_insert.erase(to_insert.begin());
929  // move to the output queue
930  typedefs_sorted.push_back(t);
931 
932  // find any depending typedefs that are now valid, or at least
933  // reduce the remaining dependencies
934  auto r_it=reverse_deps.find(t.typedef_name);
935  if(r_it==reverse_deps.end())
936  continue;
937 
938  // reduce remaining dependencies
939  std::unordered_set<irep_idt> &r_deps = r_it->second;
940  for(std::unordered_set<irep_idt>::iterator it = r_deps.begin();
941  it != r_deps.end();) // no ++it
942  {
943  auto f_it=forward_deps.find(*it);
944  if(f_it==forward_deps.end()) // might be done already
945  {
946  it=r_deps.erase(it);
947  continue;
948  }
949 
950  // update dependencies
951  std::unordered_set<irep_idt> &f_deps = f_it->second;
952  PRECONDITION(!f_deps.empty());
953  PRECONDITION(f_deps.find(t.typedef_name)!=f_deps.end());
954  f_deps.erase(t.typedef_name);
955 
956  if(f_deps.empty()) // all depenencies done now!
957  {
958  const auto td_entry=typedef_map.find(*it);
959  PRECONDITION(td_entry!=typedef_map.end());
960  to_insert.insert({id2string(*it), td_entry->second});
961  forward_deps.erase(*it);
962  it=r_deps.erase(it);
963  }
964  else
965  ++it;
966  }
967  }
968 
969  POSTCONDITION(forward_deps.empty());
970 
971  for(const auto &td : typedefs_sorted)
972  os << td.type_decl_str << '\n';
973 
974  if(!typedefs_sorted.empty())
975  os << '\n';
976 }
977 
979  const symbolt &symbol,
980  std::ostream &os,
981  local_static_declst &local_static_decls)
982 {
983  const irep_idt &func=symbol.location.get_function();
984  if((func.empty() || symbol.is_extern || symbol.value.is_not_nil()) &&
985  !converted_global.insert(symbol.name).second)
986  return;
987 
988  code_frontend_declt d(symbol.symbol_expr());
989 
991 
992  // add a tentative declaration to cater for symbols in the initializer
993  // relying on it this symbol
994  if((func.empty() || symbol.is_extern) &&
995  (symbol.value.is_nil() || !syms.empty()))
996  {
997  os << "// " << symbol.name << '\n';
998  os << "// " << symbol.location << '\n';
999  os << expr_to_string(d) << '\n';
1000  }
1001 
1002  if(!symbol.value.is_nil())
1003  {
1004  std::set<std::string> symbols_sorted;
1005  for(find_symbols_sett::const_iterator
1006  it=syms.begin();
1007  it!=syms.end();
1008  ++it)
1009  {
1010  bool inserted=symbols_sorted.insert(id2string(*it)).second;
1011  CHECK_RETURN(inserted);
1012  }
1013 
1014  for(std::set<std::string>::const_iterator
1015  it=symbols_sorted.begin();
1016  it!=symbols_sorted.end();
1017  ++it)
1018  {
1019  const symbolt &sym=ns.lookup(*it);
1020  if(!sym.is_type && sym.is_static_lifetime && sym.type.id()!=ID_code)
1021  convert_global_variable(sym, os, local_static_decls);
1022  }
1023 
1024  d.copy_to_operands(symbol.value);
1025  }
1026 
1027  if(!func.empty() && !symbol.is_extern)
1028  {
1029  local_static_decls.emplace(symbol.name, d);
1030  }
1031  else if(!symbol.value.is_nil())
1032  {
1033  os << "// " << symbol.name << '\n';
1034  os << "// " << symbol.location << '\n';
1035 
1036  std::list<irep_idt> empty_static, empty_types;
1037  cleanup_decl(d, empty_static, empty_types);
1038  CHECK_RETURN(empty_static.empty());
1039  os << expr_to_string(d) << '\n';
1040  }
1041 }
1042 
1047 {
1049  code_blockt decls;
1050 
1051  const symbolt *argc_sym=nullptr;
1052  if(!ns.lookup("argc'", argc_sym))
1053  {
1054  symbol_exprt argc("argc", argc_sym->type);
1055  replace.insert(argc_sym->symbol_expr(), argc);
1056  code_declt d(argc);
1057  decls.add(d);
1058  }
1059  const symbolt *argv_sym=nullptr;
1060  if(!ns.lookup("argv'", argv_sym))
1061  {
1062  symbol_exprt argv("argv", argv_sym->type);
1063  // replace argc' by argc in the type of argv['] to maintain type consistency
1064  // while replacing
1065  replace(argv);
1066  replace.insert(symbol_exprt(argv_sym->name, argv.type()), argv);
1067  code_declt d(argv);
1068  decls.add(d);
1069  }
1070  const symbolt *return_sym=nullptr;
1071  if(!ns.lookup("return'", return_sym))
1072  {
1073  symbol_exprt return_value("return_value", return_sym->type);
1074  replace.insert(return_sym->symbol_expr(), return_value);
1075  code_declt d(return_value);
1076  decls.add(d);
1077  }
1078 
1079  for(auto &code : b.statements())
1080  {
1081  if(code.get_statement()==ID_function_call)
1082  {
1083  exprt &func=to_code_function_call(code).function();
1084  if(func.id()==ID_symbol)
1085  {
1086  symbol_exprt &s=to_symbol_expr(func);
1087  if(s.get_identifier()==ID_main)
1089  else if(s.get_identifier() == INITIALIZE_FUNCTION)
1090  continue;
1091  }
1092  }
1093 
1094  decls.add(code);
1095  }
1096 
1097  b.swap(decls);
1098  replace(b);
1099 }
1100 
1102  const symbolt &symbol,
1103  const bool skip_main,
1104  std::ostream &os_decl,
1105  std::ostream &os_body,
1106  local_static_declst &local_static_decls)
1107 {
1108  // don't dump artificial main
1109  if(skip_main && symbol.name==goto_functionst::entry_point())
1110  return;
1111 
1112  // convert the goto program back to code - this might change
1113  // the function type
1114  goto_functionst::function_mapt::const_iterator func_entry=
1115  goto_functions.function_map.find(symbol.name);
1116  if(func_entry!=goto_functions.function_map.end() &&
1117  func_entry->second.body_available())
1118  {
1119  code_blockt b;
1120  std::list<irep_idt> type_decls, local_static;
1121 
1122  std::unordered_set<irep_idt> typedef_names;
1123  for(const auto &td : typedef_map)
1124  typedef_names.insert(td.first);
1125 
1126  goto_program2codet p2s(
1127  symbol.name,
1128  func_entry->second.body,
1130  b,
1131  local_static,
1132  type_decls,
1133  typedef_names,
1134  system_headers);
1135  p2s();
1136 
1138  b,
1139  local_static,
1140  local_static_decls,
1141  type_decls);
1142 
1143  convertedt converted_c_bak(converted_compound);
1144  convertedt converted_e_bak(converted_enum);
1145 
1147  enum_constants_bak(declared_enum_constants);
1148 
1150  b,
1151  type_decls);
1152 
1153  converted_enum.swap(converted_e_bak);
1154  converted_compound.swap(converted_c_bak);
1155 
1156  if(harness && symbol.name==goto_functions.entry_point())
1157  cleanup_harness(b);
1158 
1159  os_body << "// " << symbol.name << '\n';
1160  os_body << "// " << symbol.location << '\n';
1161  if(symbol.name==goto_functions.entry_point())
1162  os_body << make_decl(ID_main, symbol.type) << '\n';
1163  else if(!harness || symbol.name!=ID_main)
1164  os_body << make_decl(symbol.name, symbol.type) << '\n';
1165  else if(harness && symbol.name==ID_main)
1166  {
1167  os_body << make_decl(CPROVER_PREFIX+id2string(symbol.name), symbol.type)
1168  << '\n';
1169  }
1170  os_body << expr_to_string(b);
1171  os_body << "\n\n";
1172 
1173  declared_enum_constants.swap(enum_constants_bak);
1174  }
1175 
1176  if(symbol.name!=goto_functionst::entry_point() &&
1177  symbol.name!=ID_main)
1178  {
1179  os_decl << "// " << symbol.name << '\n';
1180  os_decl << "// " << symbol.location << '\n';
1181  os_decl << make_decl(symbol.name, symbol.type) << ";\n";
1182  }
1183  else if(harness && symbol.name==ID_main)
1184  {
1185  os_decl << "// " << symbol.name << '\n';
1186  os_decl << "// " << symbol.location << '\n';
1187  os_decl << make_decl(CPROVER_PREFIX+id2string(symbol.name), symbol.type)
1188  << ";\n";
1189  }
1190 
1191  // make sure typedef names used in the function declaration are
1192  // available
1193  collect_typedefs(symbol.type, true);
1194 }
1195 
1197  const irep_idt &identifier,
1198  codet &root,
1199  code_blockt* &dest,
1200  exprt::operandst::iterator &before)
1201 {
1202  if(!root.has_operands())
1203  return false;
1204 
1205  code_blockt *our_dest=nullptr;
1206 
1207  exprt::operandst &operands=root.operands();
1208  exprt::operandst::iterator first_found=operands.end();
1209 
1210  Forall_expr(it, operands)
1211  {
1212  bool found=false;
1213 
1214  // be aware of the skip-carries-type hack
1215  if(it->id()==ID_code &&
1216  to_code(*it).get_statement()!=ID_skip)
1218  identifier,
1219  to_code(*it),
1220  our_dest,
1221  before);
1222  else
1223  {
1224  find_symbols_sett syms;
1225  find_type_and_expr_symbols(*it, syms);
1226 
1227  found=syms.find(identifier)!=syms.end();
1228  }
1229 
1230  if(!found)
1231  continue;
1232 
1233  if(!our_dest)
1234  {
1235  // first containing block
1236  if(root.get_statement()==ID_block)
1237  {
1238  dest=&(to_code_block(root));
1239  before=it;
1240  }
1241 
1242  return true;
1243  }
1244  else
1245  {
1246  // there is a containing block and this is the first operand
1247  // that contains identifier
1248  if(first_found==operands.end())
1249  first_found=it;
1250  // we have seen it already - pick the first occurrence in this
1251  // block
1252  else if(root.get_statement()==ID_block)
1253  {
1254  dest=&(to_code_block(root));
1255  before=first_found;
1256 
1257  return true;
1258  }
1259  // we have seen it already - outer block has to deal with this
1260  else
1261  return true;
1262  }
1263  }
1264 
1265  if(first_found!=operands.end())
1266  {
1267  dest=our_dest;
1268 
1269  return true;
1270  }
1271 
1272  return false;
1273 }
1274 
1276  code_blockt &b,
1277  const std::list<irep_idt> &local_static,
1278  local_static_declst &local_static_decls,
1279  std::list<irep_idt> &type_decls)
1280 {
1281  // look up last identifier first as its value may introduce the
1282  // other ones
1283  for(std::list<irep_idt>::const_reverse_iterator
1284  it=local_static.rbegin();
1285  it!=local_static.rend();
1286  ++it)
1287  {
1288  local_static_declst::const_iterator d_it=
1289  local_static_decls.find(*it);
1290  PRECONDITION(d_it!=local_static_decls.end());
1291 
1292  code_frontend_declt d = d_it->second;
1293  std::list<irep_idt> redundant;
1294  cleanup_decl(d, redundant, type_decls);
1295 
1296  code_blockt *dest_ptr=nullptr;
1297  exprt::operandst::iterator before=b.operands().end();
1298 
1299  // some use of static variables might be optimised out if it is
1300  // within an if(false) { ... } block
1301  if(find_block_position_rec(*it, b, dest_ptr, before))
1302  {
1303  CHECK_RETURN(dest_ptr!=nullptr);
1304  dest_ptr->operands().insert(before, d);
1305  }
1306  }
1307 }
1308 
1310  code_blockt &b,
1311  const std::list<irep_idt> &type_decls)
1312 {
1313  // look up last identifier first as its value may introduce the
1314  // other ones
1315  for(std::list<irep_idt>::const_reverse_iterator
1316  it=type_decls.rbegin();
1317  it!=type_decls.rend();
1318  ++it)
1319  {
1320  const typet &type=ns.lookup(*it).type;
1321  // feed through plain C to expr2c by ending and re-starting
1322  // a comment block ...
1323  std::ostringstream os_body;
1324  os_body << *it << " */\n";
1325  irep_idt tag_kind =
1326  type.id() == ID_c_enum
1327  ? ID_c_enum_tag
1328  : (type.id() == ID_union ? ID_union_tag : ID_struct_tag);
1329  convert_compound(type, tag_typet(tag_kind, *it), false, os_body);
1330  os_body << "/*";
1331 
1332  code_skipt skip;
1333  skip.add_source_location().set_comment(os_body.str());
1334  // another hack to ensure symbols inside types are seen
1335  skip.type()=type;
1336 
1337  code_blockt *dest_ptr=nullptr;
1338  exprt::operandst::iterator before=b.operands().end();
1339 
1340  // we might not find it in case a transparent union type cast
1341  // has been removed by cleanup operations
1342  if(find_block_position_rec(*it, b, dest_ptr, before))
1343  {
1344  CHECK_RETURN(dest_ptr!=nullptr);
1345  dest_ptr->operands().insert(before, skip);
1346  }
1347  }
1348 }
1349 
1351 {
1352  Forall_operands(it, expr)
1353  cleanup_expr(*it);
1354 
1355  cleanup_type(expr.type());
1356 
1357  if(expr.id()==ID_struct)
1358  {
1359  struct_typet type = expr.type().id() == ID_struct_tag
1361  : to_struct_type(expr.type());
1362 
1363  struct_union_typet::componentst old_components;
1364  old_components.swap(type.components());
1365 
1366  exprt::operandst old_ops;
1367  old_ops.swap(expr.operands());
1368 
1369  PRECONDITION(old_components.size()==old_ops.size());
1370  exprt::operandst::iterator o_it=old_ops.begin();
1371  for(const auto &old_comp : old_components)
1372  {
1373  const bool is_zero_bit_field =
1374  old_comp.type().id() == ID_c_bit_field &&
1375  to_c_bit_field_type(old_comp.type()).get_width() == 0;
1376 
1377  if(!old_comp.get_is_padding() && !is_zero_bit_field)
1378  {
1379  type.components().push_back(old_comp);
1380  expr.add_to_operands(std::move(*o_it));
1381  }
1382  ++o_it;
1383  }
1384  expr.type().swap(type);
1385  }
1386  else if(expr.id()==ID_union)
1387  {
1388  union_exprt &u=to_union_expr(expr);
1389  const union_typet &u_type_f = u.type().id() == ID_union_tag
1391  : to_union_type(u.type());
1392 
1393  if(!u.type().get_bool(ID_C_transparent_union) &&
1394  !u_type_f.get_bool(ID_C_transparent_union))
1395  {
1396  if(u_type_f.get_component(u.get_component_name()).get_is_padding())
1397  // we just use an empty struct to fake an empty union
1398  expr = struct_exprt({}, struct_typet());
1399  }
1400  // add a typecast for NULL
1401  else if(
1403  to_pointer_type(u.op().type()).base_type().id() == ID_empty)
1404  {
1405  const struct_union_typet::componentt &comp=
1406  u_type_f.get_component(u.get_component_name());
1407  const typet &u_op_type=comp.type();
1408  PRECONDITION(u_op_type.id()==ID_pointer);
1409 
1410  typecast_exprt tc(u.op(), u_op_type);
1411  expr.swap(tc);
1412  }
1413  else
1414  {
1415  exprt tmp;
1416  tmp.swap(u.op());
1417  expr.swap(tmp);
1418  }
1419  }
1420  else if(
1421  expr.id() == ID_typecast &&
1422  to_typecast_expr(expr).op().id() == ID_typecast &&
1423  expr.type() == to_typecast_expr(expr).op().type())
1424  {
1425  exprt tmp = to_typecast_expr(expr).op();
1426  expr.swap(tmp);
1427  }
1428  else if(expr.id()==ID_code &&
1429  to_code(expr).get_statement()==ID_function_call &&
1430  to_code_function_call(to_code(expr)).function().id()==ID_symbol)
1431  {
1433  const symbol_exprt &fn=to_symbol_expr(call.function());
1434  code_function_callt::argumentst &arguments=call.arguments();
1435 
1436  // don't edit function calls we might have introduced
1437  const symbolt *s;
1438  if(!ns.lookup(fn.get_identifier(), s))
1439  {
1440  const symbolt &fn_sym=ns.lookup(fn.get_identifier());
1441  const code_typet &code_type=to_code_type(fn_sym.type);
1442  const code_typet::parameterst &parameters=code_type.parameters();
1443 
1444  if(parameters.size()==arguments.size())
1445  {
1446  code_typet::parameterst::const_iterator it=parameters.begin();
1447  for(auto &argument : arguments)
1448  {
1449  const typet &type = it->type().id() == ID_union_tag
1450  ? static_cast<const typet &>(ns.follow_tag(
1451  to_union_tag_type(it->type())))
1452  : it->type();
1453  if(type.id()==ID_union &&
1454  type.get_bool(ID_C_transparent_union))
1455  {
1456  if(argument.id() == ID_typecast && argument.type() == type)
1457  argument = to_typecast_expr(argument).op();
1458 
1459  // add a typecast for NULL or 0
1460  if(
1461  argument.is_constant() &&
1462  is_null_pointer(to_constant_expr(argument)))
1463  {
1464  const typet &comp_type=
1465  to_union_type(type).components().front().type();
1466 
1467  if(comp_type.id()==ID_pointer)
1468  argument = typecast_exprt(argument, comp_type);
1469  }
1470  }
1471 
1472  ++it;
1473  }
1474  }
1475  }
1476  }
1477  else if(expr.is_constant() && expr.type().id() == ID_signedbv)
1478  {
1479  #if 0
1480  const irep_idt &cformat=expr.get(ID_C_cformat);
1481 
1482  if(!cformat.empty())
1483  {
1484  declared_enum_constants_mapt::const_iterator entry=
1485  declared_enum_constants.find(cformat);
1486 
1487  if(entry!=declared_enum_constants.end() &&
1488  entry->first!=entry->second)
1489  expr.set(ID_C_cformat, entry->second);
1490  else if(entry==declared_enum_constants.end() &&
1491  !std::isdigit(id2string(cformat)[0]))
1492  expr.remove(ID_C_cformat);
1493  }
1494  #endif
1495  }
1496  else if(
1497  expr.id() == ID_byte_update_little_endian ||
1498  expr.id() == ID_byte_update_big_endian)
1499  {
1500  const byte_update_exprt &bu = to_byte_update_expr(expr);
1501 
1502  if(bu.op().id() == ID_union && bu.offset().is_zero())
1503  {
1504  const union_exprt &union_expr = to_union_expr(bu.op());
1505  const union_typet &union_type =
1506  union_expr.type().id() == ID_union_tag
1507  ? ns.follow_tag(to_union_tag_type(union_expr.type()))
1508  : to_union_type(union_expr.type());
1509 
1510  for(const auto &comp : union_type.components())
1511  {
1512  if(bu.value().type() == comp.type())
1513  {
1514  exprt member1{ID_member};
1515  member1.set(ID_component_name, union_expr.get_component_name());
1516  exprt designated_initializer1{ID_designated_initializer};
1517  designated_initializer1.add_to_operands(union_expr.op());
1518  designated_initializer1.add(ID_designator).move_to_sub(member1);
1519 
1520  exprt member2{ID_member};
1521  member2.set(ID_component_name, comp.get_name());
1522  exprt designated_initializer2{ID_designated_initializer};
1523  designated_initializer2.add_to_operands(bu.value());
1524  designated_initializer2.add(ID_designator).move_to_sub(member2);
1525 
1526  binary_exprt initializer_list{std::move(designated_initializer1),
1527  ID_initializer_list,
1528  std::move(designated_initializer2)};
1529  expr.swap(initializer_list);
1530 
1531  return;
1532  }
1533  }
1534  }
1535  else if(
1536  bu.op().id() == ID_side_effect &&
1537  to_side_effect_expr(bu.op()).get_statement() == ID_nondet &&
1538  (bu.op().type().id() == ID_union ||
1539  bu.op().type().id() == ID_union_tag) &&
1540  bu.offset().is_zero())
1541  {
1542  const union_typet &union_type =
1543  bu.op().type().id() == ID_union_tag
1545  : to_union_type(bu.op().type());
1546 
1547  for(const auto &comp : union_type.components())
1548  {
1549  if(bu.value().type() == comp.type())
1550  {
1551  union_exprt union_expr{comp.get_name(), bu.value(), bu.op().type()};
1552  expr.swap(union_expr);
1553 
1554  return;
1555  }
1556  }
1557  }
1558 
1559  std::optional<exprt> clean_init;
1560  if(
1561  (bu.type().id() == ID_union || bu.type().id() == ID_union_tag) &&
1563  {
1564  clean_init = zero_initializer(bu.op().type(), source_locationt{}, ns)
1565  .value_or(nil_exprt{});
1566  if(clean_init->id() != ID_struct || clean_init->has_operands())
1567  cleanup_expr(*clean_init);
1568  }
1569 
1570  if(clean_init.has_value() && bu.op() == *clean_init)
1571  {
1572  const union_typet &union_type =
1573  bu.type().id() == ID_union_tag
1575  : to_union_type(bu.type());
1576 
1577  for(const auto &comp : union_type.components())
1578  {
1579  if(bu.value().type() == comp.type())
1580  {
1581  union_exprt union_expr{comp.get_name(), bu.value(), bu.type()};
1582  expr.swap(union_expr);
1583 
1584  return;
1585  }
1586  }
1587 
1588  // we still haven't found a suitable component, so just ignore types and
1589  // build an initializer list without designators
1590  expr = unary_exprt{ID_initializer_list, bu.value()};
1591  }
1592  }
1593  else if(expr.id() == ID_member)
1594  {
1595  member_exprt &member_expr = to_member_expr(expr);
1596  member_expr.set_component_name(
1597  clean_identifier(member_expr.get_component_name()));
1598  }
1599 }
1600 
1602 {
1603  for(typet &subtype : to_type_with_subtypes(type).subtypes())
1604  cleanup_type(subtype);
1605 
1606  if(type.id()==ID_code)
1607  {
1608  code_typet &code_type=to_code_type(type);
1609 
1610  cleanup_type(code_type.return_type());
1611 
1612  for(code_typet::parameterst::iterator
1613  it=code_type.parameters().begin();
1614  it!=code_type.parameters().end();
1615  ++it)
1616  cleanup_type(it->type());
1617  }
1618 
1619  if(type.id()==ID_array)
1620  cleanup_expr(to_array_type(type).size());
1621 }
1622 
1624 {
1625  // future TODO: with C++20 we can actually use designated initializers as
1626  // commented out below
1627  static expr2c_configurationt configuration{
1628  /* .include_struct_padding_components = */ true,
1629  /* .print_struct_body_in_type = */ true,
1630  /* .include_array_size = */ true,
1631  /* .true_string = */ "1",
1632  /* .false_string = */ "0",
1633  /* .use_library_macros = */ true,
1634  /* .print_enum_int_value = */ false,
1635  /* .expand_typedef = */ false};
1636 
1637  return configuration;
1638 }
1639 
1640 std::string dump_ct::type_to_string(const typet &type)
1641 {
1642  std::string ret;
1643  typet t=type;
1644  cleanup_type(t);
1645 
1646  if(mode == ID_C)
1647  return type2c(t, ns, expr2c_configuration());
1648  else if(mode == ID_cpp)
1649  return type2cpp(t, ns);
1650  else
1651  UNREACHABLE;
1652 }
1653 
1654 std::string dump_ct::expr_to_string(const exprt &expr)
1655 {
1656  std::string ret;
1657  exprt e=expr;
1658  cleanup_expr(e);
1659 
1660  if(mode == ID_C)
1661  return expr2c(e, ns, expr2c_configuration());
1662  else if(mode == ID_cpp)
1663  return expr2cpp(e, ns);
1664  else
1665  UNREACHABLE;
1666 }
1667 
1668 void dump_c(
1669  const goto_functionst &src,
1670  const bool use_system_headers,
1671  const bool use_all_headers,
1672  const bool include_harness,
1673  const namespacet &ns,
1674  std::ostream &out)
1675 {
1676  dump_ct goto2c(
1677  src, use_system_headers, use_all_headers, include_harness, ns, ID_C);
1678  out << goto2c;
1679 }
1680 
1682  const goto_functionst &src,
1683  const bool use_system_headers,
1684  const bool use_all_headers,
1685  const bool include_harness,
1686  const namespacet &ns,
1687  std::ostream &out)
1688 {
1689  dump_ct goto2cpp(
1690  src, use_system_headers, use_all_headers, include_harness, ns, ID_cpp);
1691  out << goto2cpp;
1692 }
1693 
1694 static bool
1695 module_local_declaration(const symbolt &symbol, const std::string module)
1696 {
1697  std::string base_name =
1698  get_base_name(id2string(symbol.location.get_file()), true);
1699  std::string symbol_module = strip_string(id2string(symbol.module));
1700  return (base_name == module && symbol_module == module);
1701 }
1702 
1704  const goto_functionst &src,
1705  const bool use_system_headers,
1706  const bool use_all_headers,
1707  const bool include_harness,
1708  const namespacet &ns,
1709  const std::string module,
1710  std::ostream &out)
1711 {
1712  symbol_tablet symbol_table = ns.get_symbol_table();
1713  for(symbol_tablet::iteratort it = symbol_table.begin();
1714  it != symbol_table.end();
1715  it++)
1716  {
1717  symbolt &new_symbol = it.get_writeable_symbol();
1718  if(module_local_declaration(new_symbol, module))
1719  {
1720  new_symbol.type.set(ID_C_do_not_dump, 0);
1721  }
1722  else
1723  {
1724  new_symbol.type.set(ID_C_do_not_dump, 1);
1725  }
1726  }
1727 
1728  namespacet new_ns(symbol_table);
1729  dump_ct goto2c(
1730  src,
1731  use_system_headers,
1732  use_all_headers,
1733  include_harness,
1734  new_ns,
1735  ID_C,
1737  out << goto2c;
1738 }
configt config
Definition: config.cpp:25
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
Expression classes for byte-level operators.
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition: c_types.h:335
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:224
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 union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition: c_types.h:184
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:827
A base class for binary expressions.
Definition: std_expr.h:638
std::size_t get_width() const
Definition: std_types.h:920
Expression corresponding to op() where the bytes starting at position offset (given in number of byte...
const exprt & value() const
const exprt & op() const
const exprt & offset() const
C enum tag type, i.e., c_enum_typet with an identifier.
Definition: c_types.h:352
The type of C enums.
Definition: c_types.h:239
std::vector< c_enum_membert > memberst
Definition: c_types.h:275
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
A goto_instruction_codet representing the declaration of a local variable.
A codet representing the declaration of a local variable.
Definition: std_code.h:347
std::optional< exprt > initial_value() const
Returns the initial value to which the declared variable is initialized, or empty in the case where n...
Definition: std_code.h:373
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
A codet representing a skip statement.
Definition: std_code.h:322
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
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:29
exprt & op0()
Definition: expr.h:133
const irep_idt & get_statement() const
Definition: std_code_base.h:65
std::optional< std::string > main
Definition: config.h:356
struct configt::ansi_ct ansi_c
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
void clear()
Definition: dstring.h:159
std::unordered_set< irep_idt > convertedt
Definition: dump_c_class.h:163
void convert_compound_declaration(const symbolt &symbol, std::ostream &os_body)
declare compound types
Definition: dump_c.cpp:395
void convert_compound(const typet &type, const typet &unresolved, bool recursive, std::ostream &os)
Definition: dump_c.cpp:427
const namespacet ns
Definition: dump_c_class.h:158
void insert_local_type_decls(code_blockt &b, const std::list< irep_idt > &type_decls)
Definition: dump_c.cpp:1309
void cleanup_expr(exprt &expr)
Definition: dump_c.cpp:1350
void insert_local_static_decls(code_blockt &b, const std::list< irep_idt > &local_static, local_static_declst &local_static_decls, std::list< irep_idt > &type_decls)
Definition: dump_c.cpp:1275
std::string expr_to_string(const exprt &expr)
Definition: dump_c.cpp:1654
void operator()(std::ostream &out)
Definition: dump_c.cpp:73
const goto_functionst & goto_functions
Definition: dump_c_class.h:156
convertedt converted_compound
Definition: dump_c_class.h:164
void collect_typedefs(const typet &type, bool early)
Find any typedef names contained in the input type and store their declaration strings in typedef_map...
Definition: dump_c.cpp:774
void gather_global_typedefs()
Find all global typdefs in the symbol table and store them in typedef_types.
Definition: dump_c.cpp:862
typedef_typest typedef_types
Definition: dump_c_class.h:189
symbol_tablet copied_symbol_table
Definition: dump_c_class.h:157
typedef_mapt typedef_map
Definition: dump_c_class.h:187
void collect_typedefs_rec(const typet &type, bool early, std::unordered_set< irep_idt > &dependencies)
Find any typedef names contained in the input type and store their declaration strings in typedef_map...
Definition: dump_c.cpp:787
declared_enum_constants_mapt declared_enum_constants
Definition: dump_c_class.h:171
std::string make_decl(const irep_idt &identifier, const typet &type)
Definition: dump_c_class.h:199
convertedt converted_enum
Definition: dump_c_class.h:164
const irep_idt mode
Definition: dump_c_class.h:160
void convert_global_variable(const symbolt &symbol, std::ostream &os, local_static_declst &local_static_decls)
Definition: dump_c.cpp:978
std::set< std::string > system_headers
Definition: dump_c_class.h:166
void dump_typedefs(std::ostream &os) const
Print all typedefs that are not covered via typedef struct xyz { ...
Definition: dump_c.cpp:893
const bool harness
Definition: dump_c_class.h:161
system_library_symbolst system_symbols
Definition: dump_c_class.h:168
void convert_compound_enum(const typet &type, std::ostream &os)
Definition: dump_c.cpp:687
std::unordered_map< irep_idt, irep_idt > declared_enum_constants_mapt
Definition: dump_c_class.h:170
const dump_c_configurationt dump_c_config
Definition: dump_c_class.h:159
void cleanup_harness(code_blockt &b)
Replace CPROVER internal symbols in b by printable values and generate necessary declarations.
Definition: dump_c.cpp:1046
void cleanup_type(typet &type)
Definition: dump_c.cpp:1601
void cleanup_decl(code_frontend_declt &decl, std::list< irep_idt > &local_static, std::list< irep_idt > &local_type_decls)
Definition: dump_c.cpp:730
std::string type_to_string(const typet &type)
Definition: dump_c.cpp:1640
std::unordered_map< irep_idt, code_frontend_declt > local_static_declst
Definition: dump_c_class.h:238
static std::string indent(const unsigned n)
Definition: dump_c_class.h:194
void convert_function_declaration(const symbolt &symbol, const bool skip_main, std::ostream &os_decl, std::ostream &os_body, local_static_declst &local_static_decls)
Definition: dump_c.cpp:1101
convertedt converted_global
Definition: dump_c_class.h:164
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
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_zero() const
Return whether the expression is a constant representing 0.
Definition: expr.cpp:47
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
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:170
A collection of goto functions.
function_mapt function_map
static irep_idt entry_point()
Get the identifier of the entry point to a goto model.
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
void update()
Update all indices.
static instructiont make_end_function(const source_locationt &l=source_locationt::nil())
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
targett add(instructiont &&instruction)
Adds a given instruction at the end.
Definition: goto_program.h:739
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
Definition: goto_program.h:964
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition: irep.h:360
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:57
subt & get_sub()
Definition: irep.h:444
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
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:408
bool is_not_nil() const
Definition: irep.h:368
const irep_idt & id() const
Definition: irep.h:384
void swap(irept &irep)
Definition: irep.h:430
const std::string & get_string(const irep_idt &name) const
Definition: irep.h:397
irept & add(const irep_idt &name)
Definition: irep.cpp:103
bool is_nil() const
Definition: irep.h:364
Extract member of struct or union.
Definition: std_expr.h:2841
irep_idt get_component_name() const
Definition: std_expr.h:2863
void set_component_name(const irep_idt &component_name)
Definition: std_expr.h:2868
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
const symbol_table_baset & get_symbol_table() const
Return first symbol table registered with the namespace.
Definition: namespace.h:126
The NIL expression.
Definition: std_expr.h:3073
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
Replace a symbol expression by a given expression.
const irep_idt & get_statement() const
Definition: std_code.h:1472
Fixed-width bit-vector with two's complement interpretation.
const irep_idt & get_function() const
void set_comment(const irep_idt &comment)
const irep_idt & get_file() const
Struct constructor from list of elements.
Definition: std_expr.h:1872
A struct tag type, i.e., struct_typet with an identifier.
Definition: std_types.h:493
Structure type, corresponds to C style structs.
Definition: std_types.h:231
Base type for structs and unions.
Definition: std_types.h:62
const componentt & get_component(const irep_idt &component_name) const
Get the reference to a component with given name.
Definition: std_types.cpp:63
bool is_incomplete() const
A struct/union may be incomplete.
Definition: std_types.h:185
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
void set_identifier(const irep_idt &identifier)
Definition: std_expr.h:155
const irep_idt & get_identifier() const
Definition: std_expr.h:160
const symbolst & symbols
Read-only field, used to look up symbols given their names.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
The symbol table.
Definition: symbol_table.h:14
virtual iteratort begin() override
Definition: symbol_table.h:108
virtual iteratort end() override
Definition: symbol_table.h:112
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
bool is_extern
Definition: symbol.h:74
bool is_macro
Definition: symbol.h:62
irep_idt module
Name of module the symbol belongs to.
Definition: symbol.h:43
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
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
typet type
Type of symbol.
Definition: symbol.h:31
irep_idt name
The unique identifier.
Definition: symbol.h:40
exprt value
Initial value of symbol.
Definition: symbol.h:34
irep_idt mode
Language mode.
Definition: symbol.h:49
bool is_symbol_internal_symbol(const symbolt &symbol, std::set< std::string > &out_system_headers) const
To find out if a symbol is an internal symbol.
A tag-based type, i.e., typet with an identifier.
Definition: std_types.h:396
void set_identifier(const irep_idt &identifier)
Definition: std_types.h:405
const irep_idt & get_identifier() const
Definition: std_types.h:410
Symbol table entry describing a data typeThis is a symbol generated as part of type checking.
Definition: symbol.h:139
Semantic type conversion.
Definition: std_expr.h:2068
The type of an expression, extends irept.
Definition: type.h:29
const source_locationt & source_location() const
Definition: type.h:72
Generic base class for unary expressions.
Definition: std_expr.h:361
const exprt & op() const
Definition: std_expr.h:391
Union constructor from single element.
Definition: std_expr.h:1765
irep_idt get_component_name() const
Definition: std_expr.h:1773
A union tag type, i.e., union_typet with an identifier.
Definition: c_types.h:199
The union type.
Definition: c_types.h:147
Fixed-width bit-vector with unsigned binary interpretation.
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
std::string cpp_type2name(const typet &type)
C++ Language Module.
#define CPROVER_PREFIX
int isdigit(int c)
Definition: ctype.c:24
static bool find_block_position_rec(const irep_idt &identifier, codet &root, code_blockt *&dest, exprt::operandst::iterator &before)
Definition: dump_c.cpp:1196
std::ostream & operator<<(std::ostream &out, dump_ct &src)
Definition: dump_c.cpp:67
static bool module_local_declaration(const symbolt &symbol, const std::string module)
Definition: dump_c.cpp:1695
void dump_cpp(const goto_functionst &src, const bool use_system_headers, const bool use_all_headers, const bool include_harness, const namespacet &ns, std::ostream &out)
Definition: dump_c.cpp:1681
void dump_c(const goto_functionst &src, const bool use_system_headers, const bool use_all_headers, const bool include_harness, const namespacet &ns, std::ostream &out)
Definition: dump_c.cpp:1668
static expr2c_configurationt expr2c_configuration()
Definition: dump_c.cpp:1623
void dump_c_type_header(const goto_functionst &src, const bool use_system_headers, const bool use_all_headers, const bool include_harness, const namespacet &ns, const std::string module, std::ostream &out)
Definition: dump_c.cpp:1703
static std::string clean_identifier(const irep_idt &id)
Definition: dump_c.cpp:35
Dump C from Goto Program.
Dump Goto-Program as C/C++ Source.
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
Definition: expr2c.cpp:4146
std::string type2c(const typet &type, const namespacet &ns, const expr2c_configurationt &configuration)
Definition: expr2c.cpp:4162
std::string type2cpp(const typet &type, const namespacet &ns)
Definition: expr2cpp.cpp:507
std::string expr2cpp(const exprt &expr, const namespacet &ns)
Definition: expr2cpp.cpp:500
#define Forall_operands(it, expr)
Definition: expr.h:27
#define Forall_expr(it, expr)
Definition: expr.h:36
std::optional< exprt > zero_initializer(const typet &type, const source_locationt &source_location, const namespacet &ns)
Create the equivalent of zero for type type.
Expression Initialization.
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:369
Deprecated expression utility functions.
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,...
void find_non_pointer_type_symbols(const exprt &src, find_symbols_sett &dest)
Collect type tags contained in src when the expression of such a type is not a pointer,...
find_symbols_sett find_symbol_identifiers(const exprt &src)
Find identifiers of the sub expressions with id ID_symbol, considering both free and bound variables.
Definition: find_symbols.h:53
std::unordered_set< irep_idt > find_symbols_sett
Definition: find_symbols.h:20
std::string get_base_name(const std::string &in, bool strip_suffix)
cleans a filename from path and extension
const code_function_callt & to_code_function_call(const goto_instruction_codet &code)
Dump Goto-Program as C/C++ Source.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:534
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
#define POSTCONDITION(CONDITION)
Definition: invariant.h:479
#define INITIALIZE_FUNCTION
side_effect_exprt & to_side_effect_expr(exprt &expr)
Definition: std_code.h:1506
const code_blockt & to_code_block(const codet &code)
Definition: std_code.h:203
const codet & to_code(const exprt &expr)
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:3037
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 member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2933
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:788
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
bool can_cast_type< tag_typet >(const typet &type)
Check whether a reference to a typet is a tag_typet.
Definition: std_types.h:420
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518
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
const tag_typet & to_tag_type(const typet &type)
Cast a typet to a tag_typet.
Definition: std_types.h:434
void replace(const union_find_replacet &replace_map, string_not_contains_constraintt &constraint)
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
std::string strip_string(const std::string &s)
Remove all whitespace characters from either end of a string.
std::size_t long_long_int_width
Definition: config.h:142
Used for configuring the behaviour of dump_c.
Definition: dump_c_class.h:27
dump_c_configurationt disable_include_function_decls()
Definition: dump_c_class.h:62
bool include_global_decls
Include the global declarations in the dump.
Definition: dump_c_class.h:35
bool include_typedefs
Include the typedefs in the dump.
Definition: dump_c_class.h:38
bool include_global_vars
Include global variable definitions in the dump.
Definition: dump_c_class.h:41
static dump_c_configurationt default_configuration
The default used for dump-c and dump-cpp.
Definition: dump_c_class.h:57
bool include_function_decls
Include the function declarations in the dump.
Definition: dump_c_class.h:29
bool include_headers
Include headers type declarations are borrowed from.
Definition: dump_c_class.h:50
bool include_compounds
Include struct definitions in the dump.
Definition: dump_c_class.h:44
dump_c_configurationt disable_include_global_vars()
Definition: dump_c_class.h:86
static dump_c_configurationt type_header_configuration
The config used for dump-c-type-header.
Definition: dump_c_class.h:60
dump_c_configurationt disable_include_function_bodies()
Definition: dump_c_class.h:68
dump_c_configurationt enable_include_headers()
Definition: dump_c_class.h:104
bool include_function_bodies
Include the functions in the dump.
Definition: dump_c_class.h:32
bool follow_compounds
Define whether to follow compunds recursively.
Definition: dump_c_class.h:47
Used for configuring the behaviour of expr2c and type2c.
Definition: expr2c.h:21
static std::string type2name(const typet &type, const namespacet &ns, symbol_numbert &symbol_number)
Definition: type2name.cpp:82
Type Naming for C.
const type_with_subtypest & to_type_with_subtypes(const typet &type)
Definition: type.h:252
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:208
#define size_type
Definition: unistd.c:347
dstringt irep_idt