@@ -62,6 +62,8 @@ void dump_ct::operator()(std::ostream &os)
6262 std::stringstream func_body_stream;
6363 local_static_declst local_static_decls;
6464
65+ gather_global_typedefs ();
66+
6567 // add copies of struct types when ID_C_transparent_union is only
6668 // annotated to parameter
6769 symbol_tablet symbols_transparent;
@@ -113,6 +115,9 @@ void dump_ct::operator()(std::ostream &os)
113115 symbolt &symbol=it->second ;
114116 bool tag_added=false ;
115117
118+ // TODO we could get rid of some of the ID_anonymous by looking up
119+ // the origin symbol types in typedef_types and adjusting any other
120+ // uses of ID_tag
116121 if ((symbol.type .id ()==ID_union || symbol.type .id ()==ID_struct) &&
117122 symbol.type .get (ID_tag).empty ())
118123 {
@@ -285,6 +290,8 @@ void dump_ct::operator()(std::ostream &os)
285290 os << std::endl;
286291 }
287292
293+ dump_typedefs (os);
294+
288295 if (!func_decl_stream.str ().empty ())
289296 os << func_decl_stream.str () << std::endl;
290297 if (!compound_body_stream.str ().empty ())
@@ -408,6 +415,9 @@ void dump_ct::convert_compound(
408415 if (!converted_compound.insert (name).second )
409416 return ;
410417
418+ // make sure typedef names used in the declaration are available
419+ collect_typedefs (type, true );
420+
411421 const irept &bases = type.find (ID_bases);
412422 std::stringstream base_decls;
413423 forall_irep (parent_it, bases.get_sub ())
@@ -466,8 +476,13 @@ void dump_ct::convert_compound(
466476 while (non_array_type->id ()==ID_array)
467477 non_array_type=&(ns.follow (non_array_type->subtype ()));
468478
469- if (recursive && non_array_type->id ()!=ID_pointer)
470- convert_compound (comp.type (), comp.type (), recursive, os);
479+ if (recursive)
480+ {
481+ if (non_array_type->id ()!=ID_pointer)
482+ convert_compound (comp.type (), comp.type (), recursive, os);
483+ else
484+ collect_typedefs (comp.type (), true );
485+ }
471486
472487 irep_idt comp_name=comp.get_name ();
473488
@@ -521,7 +536,21 @@ void dump_ct::convert_compound(
521536 struct_body << " ;" << std::endl;
522537 }
523538
524- os << type_to_string (unresolved);
539+ typet unresolved_clean=unresolved;
540+ typedef_typest::const_iterator td_entry=
541+ typedef_types.find (unresolved);
542+ irep_idt typedef_str;
543+ if (td_entry!=typedef_types.end ())
544+ {
545+ unresolved_clean.remove (ID_C_typedef);
546+ typedef_str=td_entry->second ;
547+ std::pair<std::string, bool > &td_map_entry=typedef_map[typedef_str];
548+ if (!td_map_entry.second )
549+ td_map_entry.first =" " ;
550+ os << " typedef " ;
551+ }
552+
553+ os << type_to_string (unresolved_clean);
525554 if (!base_decls.str ().empty ())
526555 {
527556 assert (language->id ()==" cpp" );
@@ -548,6 +577,8 @@ void dump_ct::convert_compound(
548577 os << " __attribute__ ((__transparent_union__))" ;
549578 if (type.get_bool (ID_C_packed))
550579 os << " __attribute__ ((__packed__))" ;
580+ if (!typedef_str.empty ())
581+ os << " " << typedef_str;
551582 os << " ;" ;
552583 os << std::endl;
553584 os << std::endl;
@@ -901,6 +932,10 @@ void dump_ct::cleanup_decl(
901932
902933 tmp.add_instruction (END_FUNCTION);
903934
935+ std::unordered_set<irep_idt, irep_id_hash> typedef_names;
936+ for (const auto &td : typedef_map)
937+ typedef_names.insert (td.first );
938+
904939 code_blockt b;
905940 goto_program2codet p2s (
906941 irep_idt (),
@@ -909,6 +944,7 @@ void dump_ct::cleanup_decl(
909944 b,
910945 local_static,
911946 local_type_decls,
947+ typedef_names,
912948 system_headers);
913949 p2s ();
914950
@@ -918,6 +954,132 @@ void dump_ct::cleanup_decl(
918954
919955/* ******************************************************************\
920956
957+ Function: dump_ct::collect_typedefs
958+
959+ Inputs:
960+ type Type to inspect for ID_C_typedef entry
961+ early Set to true to enforce that typedef is dumped before any
962+ function declarations or struct definitions
963+
964+ Outputs:
965+
966+ Purpose: Find any typedef names contained in the input type and store
967+ their declaration strings in typedef_map for eventual output.
968+
969+ \*******************************************************************/
970+
971+ void dump_ct::collect_typedefs (const typet &type, bool early)
972+ {
973+ if (type.id ()==ID_code)
974+ {
975+ const code_typet &code_type=to_code_type (type);
976+
977+ collect_typedefs (code_type.return_type (), early);
978+ for (const auto ¶m : code_type.parameters ())
979+ collect_typedefs (param.type (), early);
980+ }
981+ else if (type.id ()==ID_pointer || type.id ()==ID_array)
982+ {
983+ collect_typedefs (type.subtype (), early);
984+ }
985+ else if (type.id ()==ID_symbol)
986+ {
987+ const symbolt &symbol=
988+ ns.lookup (to_symbol_type (type).get_identifier ());
989+ collect_typedefs (symbol.type , early);
990+ }
991+
992+ const irep_idt &typedef_str=type.get (ID_C_typedef);
993+
994+ if (!typedef_str.empty ())
995+ {
996+ std::pair<typedef_mapt::iterator, bool > entry=
997+ typedef_map.insert ({typedef_str, {" " , early}});
998+
999+ if (entry.second )
1000+ {
1001+ if (typedef_str==" __gnuc_va_list" || typedef_str == " va_list" )
1002+ {
1003+ system_headers.insert (" stdarg.h" );
1004+ }
1005+ else
1006+ {
1007+ typet t=type;
1008+ t.remove (ID_C_typedef);
1009+
1010+ std::ostringstream oss;
1011+ oss << " typedef " << type_to_string (t) << " "
1012+ << typedef_str << ' ;' ;
1013+
1014+ entry.first ->second .first =oss.str ();
1015+ }
1016+ }
1017+ else if (early)
1018+ {
1019+ entry.first ->second .second =true ;
1020+ }
1021+ }
1022+ }
1023+
1024+ /* ******************************************************************\
1025+
1026+ Function: dump_ct::gather_global_typedefs
1027+
1028+ Inputs:
1029+
1030+ Outputs:
1031+
1032+ Purpose: find all global typdefs in the symbol table and store them
1033+ in typedef_types
1034+
1035+ \*******************************************************************/
1036+
1037+ void dump_ct::gather_global_typedefs ()
1038+ {
1039+ for (const auto &symbol_entry : copied_symbol_table.symbols )
1040+ {
1041+ const symbolt &symbol=symbol_entry.second ;
1042+
1043+ if (symbol.is_macro && symbol.is_type && !ignore (symbol) &&
1044+ symbol.location .get_function ().empty ())
1045+ {
1046+ assert (!symbol.type .get (ID_C_typedef).empty ());
1047+ typedef_types[symbol.type ]=symbol.type .get (ID_C_typedef);
1048+ collect_typedefs (symbol.type , false );
1049+ }
1050+ }
1051+ }
1052+
1053+ /* ******************************************************************\
1054+
1055+ Function: dump_ct::dump_typedefs
1056+
1057+ Inputs:
1058+
1059+ Outputs: os output stream
1060+
1061+ Purpose: print all typedefs that are not covered via
1062+ typedef struct xyz { ... } name;
1063+
1064+ \*******************************************************************/
1065+
1066+ void dump_ct::dump_typedefs (std::ostream &os) const
1067+ {
1068+ bool need_newline=false ;
1069+
1070+ for (const auto &td : typedef_map)
1071+ if (!td.second .first .empty ())
1072+ {
1073+ need_newline=true ;
1074+ os << td.second .first << std::endl;
1075+ }
1076+
1077+ if (need_newline)
1078+ os << std::endl;
1079+ }
1080+
1081+ /* ******************************************************************\
1082+
9211083Function: dump_ct::convert_global_variables
9221084
9231085Inputs:
@@ -1024,13 +1186,18 @@ void dump_ct::convert_function_declaration(
10241186 code_blockt b;
10251187 std::list<irep_idt> type_decls, local_static;
10261188
1189+ std::unordered_set<irep_idt, irep_id_hash> typedef_names;
1190+ for (const auto &td : typedef_map)
1191+ typedef_names.insert (td.first );
1192+
10271193 goto_program2codet p2s (
10281194 symbol.name ,
10291195 func_entry->second .body ,
10301196 copied_symbol_table,
10311197 b,
10321198 local_static,
10331199 type_decls,
1200+ typedef_names,
10341201 system_headers);
10351202 p2s ();
10361203
@@ -1069,6 +1236,10 @@ void dump_ct::convert_function_declaration(
10691236 os_decl << " // " << symbol.location << std::endl;
10701237 os_decl << make_decl (symbol.name , symbol.type ) << " ;" << std::endl;
10711238 }
1239+
1240+ // make sure typedef names used in the function declaration are
1241+ // available
1242+ collect_typedefs (symbol.type , true );
10721243}
10731244
10741245/* ******************************************************************\
0 commit comments