@@ -62,6 +62,8 @@ void dump_ct::operator()(std::ostream &os)
62
62
std::stringstream func_body_stream;
63
63
local_static_declst local_static_decls;
64
64
65
+ gather_global_typedefs ();
66
+
65
67
// add copies of struct types when ID_C_transparent_union is only
66
68
// annotated to parameter
67
69
symbol_tablet symbols_transparent;
@@ -113,6 +115,9 @@ void dump_ct::operator()(std::ostream &os)
113
115
symbolt &symbol=it->second ;
114
116
bool tag_added=false ;
115
117
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
116
121
if ((symbol.type .id ()==ID_union || symbol.type .id ()==ID_struct) &&
117
122
symbol.type .get (ID_tag).empty ())
118
123
{
@@ -285,6 +290,8 @@ void dump_ct::operator()(std::ostream &os)
285
290
os << std::endl;
286
291
}
287
292
293
+ dump_typedefs (os);
294
+
288
295
if (!func_decl_stream.str ().empty ())
289
296
os << func_decl_stream.str () << std::endl;
290
297
if (!compound_body_stream.str ().empty ())
@@ -408,6 +415,9 @@ void dump_ct::convert_compound(
408
415
if (!converted_compound.insert (name).second )
409
416
return ;
410
417
418
+ // make sure typedef names used in the declaration are available
419
+ collect_typedefs (type, true );
420
+
411
421
const irept &bases = type.find (ID_bases);
412
422
std::stringstream base_decls;
413
423
forall_irep (parent_it, bases.get_sub ())
@@ -466,8 +476,13 @@ void dump_ct::convert_compound(
466
476
while (non_array_type->id ()==ID_array)
467
477
non_array_type=&(ns.follow (non_array_type->subtype ()));
468
478
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
+ }
471
486
472
487
irep_idt comp_name=comp.get_name ();
473
488
@@ -521,7 +536,21 @@ void dump_ct::convert_compound(
521
536
struct_body << " ;" << std::endl;
522
537
}
523
538
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);
525
554
if (!base_decls.str ().empty ())
526
555
{
527
556
assert (language->id ()==" cpp" );
@@ -548,6 +577,8 @@ void dump_ct::convert_compound(
548
577
os << " __attribute__ ((__transparent_union__))" ;
549
578
if (type.get_bool (ID_C_packed))
550
579
os << " __attribute__ ((__packed__))" ;
580
+ if (!typedef_str.empty ())
581
+ os << " " << typedef_str;
551
582
os << " ;" ;
552
583
os << std::endl;
553
584
os << std::endl;
@@ -901,6 +932,10 @@ void dump_ct::cleanup_decl(
901
932
902
933
tmp.add_instruction (END_FUNCTION);
903
934
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
+
904
939
code_blockt b;
905
940
goto_program2codet p2s (
906
941
irep_idt (),
@@ -909,6 +944,7 @@ void dump_ct::cleanup_decl(
909
944
b,
910
945
local_static,
911
946
local_type_decls,
947
+ typedef_names,
912
948
system_headers);
913
949
p2s ();
914
950
@@ -918,6 +954,132 @@ void dump_ct::cleanup_decl(
918
954
919
955
/* ******************************************************************\
920
956
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
+
921
1083
Function: dump_ct::convert_global_variables
922
1084
923
1085
Inputs:
@@ -1024,13 +1186,18 @@ void dump_ct::convert_function_declaration(
1024
1186
code_blockt b;
1025
1187
std::list<irep_idt> type_decls, local_static;
1026
1188
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
+
1027
1193
goto_program2codet p2s (
1028
1194
symbol.name ,
1029
1195
func_entry->second .body ,
1030
1196
copied_symbol_table,
1031
1197
b,
1032
1198
local_static,
1033
1199
type_decls,
1200
+ typedef_names,
1034
1201
system_headers);
1035
1202
p2s ();
1036
1203
@@ -1069,6 +1236,10 @@ void dump_ct::convert_function_declaration(
1069
1236
os_decl << " // " << symbol.location << std::endl;
1070
1237
os_decl << make_decl (symbol.name , symbol.type ) << " ;" << std::endl;
1071
1238
}
1239
+
1240
+ // make sure typedef names used in the function declaration are
1241
+ // available
1242
+ collect_typedefs (symbol.type , true );
1072
1243
}
1073
1244
1074
1245
/* ******************************************************************\
0 commit comments