CBMC
Loading...
Searching...
No Matches
dump_c.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Dump Goto-Program as C/C++ Source
4
5Author: 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>
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
35static 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
67inline std::ostream &operator << (std::ostream &out, dump_ct &src)
68{
69 src(out);
70 return out;
71}
72
73void 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;
82
83 // add copies of struct types when ID_C_transparent_union is only
84 // annotated to parameter
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
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};
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 {
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
134
135 to_union_tag_type(type).set_identifier(new_type_sym.name);
137 }
138 }
139 }
140 for(const auto &symbol_pair : additional_symbols.symbols)
141 {
143 }
144
145 typedef std::unordered_map<irep_idt, unsigned> unique_tagst;
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);
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 {
196 std::to_string(unique_entry.first->second);
197 ++(unique_entry.first->second);
198 }
199
200 if(symbol.type.id()==ID_c_enum)
201 {
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 ||
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)
268 else if(type_id == ID_struct)
269 {
271 << ";\n\n";
272 }
273 else
274 {
276 << ";\n\n";
277 }
278 }
279 }
280 else if(
281 symbol.is_static_lifetime && symbol.type.id() != ID_code &&
284 symbol,
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 {
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,
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) &&
334 !to_struct_union_type(symbol.type).is_incomplete())
335 {
337 symbol,
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
381 if(dump_c_config.include_typedefs)
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';
390 if(dump_c_config.include_function_bodies)
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() ||
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),
411 dump_c_config.follow_compounds,
412 os_body);
413 else if(symbol.type.id() == ID_union)
415 symbol.type,
416 union_tag_typet(symbol.name),
417 dump_c_config.follow_compounds,
418 os_body);
419 else if(symbol.type.id() == ID_c_enum)
421 symbol.type,
422 c_enum_tag_typet(symbol.name),
423 dump_c_config.follow_compounds,
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
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 {
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);
467 type_symbol.type.id() == ID_c_enum
469 : (type_symbol.type.id() == ID_union ? ID_union_tag
470 : ID_struct_tag);
473 }
474 }
475 }
476 else if(type.id()==ID_struct || type.id()==ID_union)
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 {
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);
509 const symbolt &parsymb=ns.lookup(renamed_base_id);
510
512
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
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 =
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
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 {
577 (comp.type().id() == ID_struct_tag || comp.type().id() == ID_union_tag)
578 ? ns.follow_tag(to_struct_or_union_tag_type(comp.type()))
579 : comp.type();
580 comp_type_to_use.remove(ID_tag);
581 if(
583 comp_type_to_use.id() == ID_union))
584 {
585 const auto &sub_comps =
587 for(const auto &sc : sub_comps)
588 convert_compound(sc.type(), sc.type(), recursive, os);
589 }
590 }
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 {
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 {
608 if(t.get_width()<=config.ansi_c.long_long_int_width)
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 {
620 if(t.get_width()<=config.ansi_c.long_long_int_width)
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
631
632 struct_body << ";\n";
633 }
634
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 {
644 typedef_str = td_entry.second;
645 std::pair<typedef_mapt::iterator, bool> td_map_entry =
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
656 if(!base_decls.str().empty())
657 {
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 << "}";
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
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)!=
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
723
724 if(enum_type.get_bool(ID_C_packed))
725 os << " __attribute__ ((__packed__))";
726
727 os << ";\n\n";
728}
729
732 std::list<irep_idt> &local_static,
733 std::list<irep_idt> &local_type_decls)
734{
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
755 irep_idt(),
756 tmp,
758 b,
759 local_static,
761 typedef_names,
763 p2s();
764
765 POSTCONDITION(b.statements().size() == 1);
766 decl.swap(b.op0());
767}
768
774void 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
816
817 if(!typedef_str.empty())
818 {
819 std::pair<typedef_mapt::iterator, bool> entry=
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;
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);
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 {
881 PRECONDITION(!typedef_str.empty());
882 typedef_types[symbol.type]=typedef_str;
883 if(system_symbols.is_symbol_internal_symbol(symbol, system_headers))
884 typedef_map.insert({typedef_str, typedef_infot(typedef_str)});
885 else
886 collect_typedefs(symbol.type, false);
887 }
888 }
889}
890
893void 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,
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
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,
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
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)
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;
1038 CHECK_RETURN(empty_static.empty());
1039 os << expr_to_string(d) << '\n';
1040 }
1041}
1042
1047{
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 {
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,
1107{
1108 // don't dump artificial main
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
1127 symbol.name,
1128 func_entry->second.body,
1130 b,
1131 local_static,
1132 type_decls,
1133 typedef_names,
1135 p2s();
1136
1138 b,
1139 local_static,
1141 type_decls);
1142
1145
1148
1150 b,
1151 type_decls);
1152
1155
1156 if(harness && symbol.name==goto_functions.entry_point())
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 {
1168 << '\n';
1169 }
1171 os_body << "\n\n";
1172
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';
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 {
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,
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;
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";
1326 type.id() == ID_c_enum
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
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
1360 ? ns.follow_tag(to_struct_tag_type(expr.type()))
1361 : to_struct_type(expr.type());
1362
1364 old_components.swap(type.components());
1365
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 {
1389 const union_typet &u_type_f = u.type().id() == ID_union_tag
1390 ? ns.follow_tag(to_union_tag_type(u.type()))
1391 : to_union_type(u.type());
1392
1393 if(!u.type().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(
1402 u.op().is_constant() && to_constant_expr(u.op()).is_null_pointer() &&
1403 to_pointer_type(u.op().type()).base_type().id() == ID_empty)
1404 {
1406 u_type_f.get_component(u.get_component_name());
1407 const typet &u_op_type=comp.type();
1409
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());
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 &&
1455 {
1456 if(argument.id() == ID_typecast && argument.type() == type)
1458
1459 // add a typecast for NULL or 0
1460 if(
1461 argument.is_constant() &&
1463 {
1464 const typet &comp_type=
1465 to_union_type(type).components().front().type();
1466
1467 if(comp_type.id()==ID_pointer)
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=
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 {
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 {
1515 member1.set(ID_component_name, union_expr.get_component_name());
1517 designated_initializer1.add_to_operands(union_expr.op());
1519
1521 member2.set(ID_component_name, comp.get_name());
1523 designated_initializer2.add_to_operands(bu.value());
1525
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 &&
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
1544 ? ns.follow_tag(to_union_tag_type(bu.op().type()))
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) &&
1562 bu.source_location().get_function().empty())
1563 {
1565 .value_or(nil_exprt{});
1566 if(clean_init->id() != ID_struct || clean_init->has_operands())
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
1574 ? ns.follow_tag(to_union_tag_type(bu.type()))
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 {
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 {
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
1640std::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
1652}
1653
1654std::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
1666}
1667
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{
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{
1690 src, use_system_headers, use_all_headers, include_harness, ns, ID_cpp);
1691 out << goto2cpp;
1692}
1693
1694static bool
1695module_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);
1730 src,
1732 use_all_headers,
1734 new_ns,
1735 ID_C,
1737 out << goto2c;
1738}
configt config
Definition config.cpp:25
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
Expression classes for byte-level operators.
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition c_types.h:80
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition c_types.h:335
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition c_types.h:224
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
A base class for binary expressions.
Definition std_expr.h:638
std::size_t get_width() const
Definition std_types.h:925
Expression corresponding to op() where the bytes starting at position offset (given in number of byte...
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
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
symbol_exprt & symbol()
Definition std_code.h:354
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
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
goto_instruction_codet representation of a function call statement.
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:586
Data structure for representing an arbitrary statement in a program.
const irep_idt & get_statement() const
std::optional< std::string > main
Definition config.h:390
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
std::unordered_set< irep_idt > convertedt
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
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
convertedt converted_compound
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
symbol_tablet copied_symbol_table
typedef_mapt typedef_map
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
std::string make_decl(const irep_idt &identifier, const typet &type)
convertedt converted_enum
const irep_idt mode
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
void dump_typedefs(std::ostream &os) const
Print all typedefs that are not covered via typedef struct xyz { ... } name;.
Definition dump_c.cpp:893
const bool harness
system_library_symbolst system_symbols
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
const dump_c_configurationt dump_c_config
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
static std::string indent(const unsigned n)
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
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
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:212
typet & type()
Return the type of the expression.
Definition expr.h:84
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.
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.
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.
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
void remove(const irep_idt &name)
Definition irep.cpp:87
void set(const irep_idt &name, const irep_idt &value)
Definition irep.h:412
bool is_not_nil() const
Definition irep.h:372
subt & get_sub()
Definition irep.h:448
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
irept & add(const irep_idt &name)
Definition irep.cpp:103
bool is_nil() const
Definition irep.h:368
const std::string & get_string(const irep_idt &name) const
Definition irep.h:401
Extract member of struct or union.
Definition std_expr.h:2971
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
const symbol_table_baset & get_symbol_table() const
Return first symbol table registered with the namespace.
Definition namespace.h:123
The NIL expression.
Definition std_expr.h:3208
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
const irep_idt & get_file() const
Struct constructor from list of elements.
Definition std_expr.h:1877
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 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.
virtual iteratort begin() override
virtual iteratort end() override
Symbol table entry.
Definition symbol.h:28
bool is_extern
Definition symbol.h:74
bool is_macro
Definition symbol.h:62
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
irep_idt irep_idt base_name
Name of module the symbol belongs to.
Definition symbol.h:46
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
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:2073
The type of an expression, extends irept.
Definition type.h:29
Generic base class for unary expressions.
Definition std_expr.h:361
Union constructor from single element.
Definition std_expr.h:1770
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
static std::unordered_set< irep_idt > find_symbol_identifiers(const goto_programt &src)
Find all identifiers in src.
std::ostream & operator<<(std::ostream &out, dump_ct &src)
Definition dump_c.cpp:67
static bool find_block_position_rec(const irep_idt &identifier, codet &root, code_blockt *&dest, exprt::operandst::iterator &before)
Definition dump_c.cpp:1196
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:4184
std::string type2c(const typet &type, const namespacet &ns, const expr2c_configurationt &configuration)
Definition expr2c.cpp:4200
static std::string clean_identifier(const irep_idt &id)
Definition expr2c.cpp:93
std::string type2cpp(const typet &type, const namespacet &ns)
Definition expr2cpp.cpp:493
std::string expr2cpp(const exprt &expr, const namespacet &ns)
Definition expr2cpp.cpp:486
#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...
Deprecated expression utility functions.
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,...
void find_type_and_expr_symbols(const exprt &src, find_symbols_sett &dest, const std::vector< irep_idt > &subs_to_find)
Find identifiers with id ID_symbol of the sub expressions and the subs with ID in subs_to_find consid...
std::unordered_set< irep_idt > find_symbols_sett
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:44
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
#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 typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3063
const union_exprt & to_union_expr(const exprt &expr)
Cast an exprt to a union_exprt.
Definition std_expr.h:1816
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
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 array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
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_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
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 strip_string(const std::string &s)
Remove all whitespace characters from either end of a string.
Used for configuring the behaviour of dump_c.
dump_c_configurationt disable_include_function_decls()
static dump_c_configurationt default_configuration
The default used for dump-c and dump-cpp.
dump_c_configurationt disable_include_global_vars()
static dump_c_configurationt type_header_configuration
The config used for dump-c-type-header.
dump_c_configurationt disable_include_function_bodies()
dump_c_configurationt enable_include_headers()
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
dstringt irep_idt