@@ -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 ())
@@ -521,7 +528,21 @@ void dump_ct::convert_compound(
521
528
struct_body << " ;" << std::endl;
522
529
}
523
530
524
- os << type_to_string (unresolved);
531
+ typet unresolved_clean=unresolved;
532
+ typedef_typest::const_iterator td_entry=
533
+ typedef_types.find (unresolved);
534
+ irep_idt typedef_str;
535
+ if (td_entry!=typedef_types.end ())
536
+ {
537
+ unresolved_clean.remove (ID_C_typedef);
538
+ typedef_str=td_entry->second ;
539
+ std::pair<std::string, bool > &td_map_entry=typedef_map[typedef_str];
540
+ if (!td_map_entry.second )
541
+ td_map_entry.first =" " ;
542
+ os << " typedef " ;
543
+ }
544
+
545
+ os << type_to_string (unresolved_clean);
525
546
if (!base_decls.str ().empty ())
526
547
{
527
548
assert (language->id ()==" cpp" );
@@ -548,6 +569,8 @@ void dump_ct::convert_compound(
548
569
os << " __attribute__ ((__transparent_union__))" ;
549
570
if (type.get_bool (ID_C_packed))
550
571
os << " __attribute__ ((__packed__))" ;
572
+ if (!typedef_str.empty ())
573
+ os << " " << typedef_str;
551
574
os << " ;" ;
552
575
os << std::endl;
553
576
os << std::endl;
@@ -901,6 +924,10 @@ void dump_ct::cleanup_decl(
901
924
902
925
tmp.add_instruction (END_FUNCTION);
903
926
927
+ std::unordered_set<irep_idt, irep_id_hash> typedef_names;
928
+ for (const auto &td : typedef_map)
929
+ typedef_names.insert (td.first );
930
+
904
931
code_blockt b;
905
932
goto_program2codet p2s (
906
933
irep_idt (),
@@ -909,6 +936,7 @@ void dump_ct::cleanup_decl(
909
936
b,
910
937
local_static,
911
938
local_type_decls,
939
+ typedef_names,
912
940
system_headers);
913
941
p2s ();
914
942
@@ -918,6 +946,132 @@ void dump_ct::cleanup_decl(
918
946
919
947
/* ******************************************************************\
920
948
949
+ Function: dump_ct::collect_typedefs
950
+
951
+ Inputs:
952
+ type Type to inspect for ID_C_typedef entry
953
+ early Set to true to enforce that typedef is dumped before any
954
+ function declarations or struct definitions
955
+
956
+ Outputs:
957
+
958
+ Purpose: Find any typedef names contained in the input type and store
959
+ their declaration strings in typedef_map for eventual output.
960
+
961
+ \*******************************************************************/
962
+
963
+ void dump_ct::collect_typedefs (const typet &type, bool early)
964
+ {
965
+ if (type.id ()==ID_code)
966
+ {
967
+ const code_typet &code_type=to_code_type (type);
968
+
969
+ collect_typedefs (code_type.return_type (), early);
970
+ for (const auto ¶m : code_type.parameters ())
971
+ collect_typedefs (param.type (), early);
972
+ }
973
+ else if (type.id ()==ID_pointer || type.id ()==ID_array)
974
+ {
975
+ collect_typedefs (type.subtype (), early);
976
+ }
977
+ else if (type.id ()==ID_symbol)
978
+ {
979
+ const symbolt &symbol=
980
+ ns.lookup (to_symbol_type (type).get_identifier ());
981
+ collect_typedefs (symbol.type , early);
982
+ }
983
+
984
+ const irep_idt &typedef_str=type.get (ID_C_typedef);
985
+
986
+ if (!typedef_str.empty ())
987
+ {
988
+ std::pair<typedef_mapt::iterator, bool > entry=
989
+ typedef_map.insert ({typedef_str, {" " , early}});
990
+
991
+ if (entry.second )
992
+ {
993
+ if (typedef_str==" __gnuc_va_list" || typedef_str == " va_list" )
994
+ {
995
+ system_headers.insert (" stdarg.h" );
996
+ }
997
+ else
998
+ {
999
+ typet t=type;
1000
+ t.remove (ID_C_typedef);
1001
+
1002
+ std::ostringstream oss;
1003
+ oss << " typedef " << type_to_string (t) << " "
1004
+ << typedef_str << ' ;' ;
1005
+
1006
+ entry.first ->second .first =oss.str ();
1007
+ }
1008
+ }
1009
+ else if (early)
1010
+ {
1011
+ entry.first ->second .second =true ;
1012
+ }
1013
+ }
1014
+ }
1015
+
1016
+ /* ******************************************************************\
1017
+
1018
+ Function: dump_ct::gather_global_typedefs
1019
+
1020
+ Inputs:
1021
+
1022
+ Outputs:
1023
+
1024
+ Purpose: find all global typdefs in the symbol table and store them
1025
+ in typedef_types
1026
+
1027
+ \*******************************************************************/
1028
+
1029
+ void dump_ct::gather_global_typedefs ()
1030
+ {
1031
+ forall_symbols (it, copied_symbol_table.symbols )
1032
+ {
1033
+ const symbolt &symbol=it->second ;
1034
+
1035
+ if (symbol.is_macro && symbol.is_type && !ignore (symbol) &&
1036
+ symbol.location .get_function ().empty ())
1037
+ {
1038
+ assert (!symbol.type .get (ID_C_typedef).empty ());
1039
+ typedef_types[symbol.type ]=symbol.type .get (ID_C_typedef);
1040
+ collect_typedefs (symbol.type , false );
1041
+ }
1042
+ }
1043
+ }
1044
+
1045
+ /* ******************************************************************\
1046
+
1047
+ Function: dump_ct::dump_typedefs
1048
+
1049
+ Inputs:
1050
+
1051
+ Outputs: os output stream
1052
+
1053
+ Purpose: print all typedefs that are not covered via
1054
+ typedef struct xyz { ... } name;
1055
+
1056
+ \*******************************************************************/
1057
+
1058
+ void dump_ct::dump_typedefs (std::ostream &os) const
1059
+ {
1060
+ bool need_newline=false ;
1061
+
1062
+ for (const auto &td : typedef_map)
1063
+ if (!td.second .first .empty ())
1064
+ {
1065
+ need_newline=true ;
1066
+ os << td.second .first << std::endl;
1067
+ }
1068
+
1069
+ if (need_newline)
1070
+ os << std::endl;
1071
+ }
1072
+
1073
+ /* ******************************************************************\
1074
+
921
1075
Function: dump_ct::convert_global_variables
922
1076
923
1077
Inputs:
@@ -1024,13 +1178,18 @@ void dump_ct::convert_function_declaration(
1024
1178
code_blockt b;
1025
1179
std::list<irep_idt> type_decls, local_static;
1026
1180
1181
+ std::unordered_set<irep_idt, irep_id_hash> typedef_names;
1182
+ for (const auto &td : typedef_map)
1183
+ typedef_names.insert (td.first );
1184
+
1027
1185
goto_program2codet p2s (
1028
1186
symbol.name ,
1029
1187
func_entry->second .body ,
1030
1188
copied_symbol_table,
1031
1189
b,
1032
1190
local_static,
1033
1191
type_decls,
1192
+ typedef_names,
1034
1193
system_headers);
1035
1194
p2s ();
1036
1195
@@ -1065,6 +1224,10 @@ void dump_ct::convert_function_declaration(
1065
1224
if (symbol.name !=goto_functionst::entry_point () &&
1066
1225
symbol.name !=ID_main)
1067
1226
{
1227
+ // make sure typedef names are available before outputting this
1228
+ // declaration
1229
+ collect_typedefs (symbol.type , true );
1230
+
1068
1231
os_decl << " // " << symbol.name << std::endl;
1069
1232
os_decl << " // " << symbol.location << std::endl;
1070
1233
os_decl << make_decl (symbol.name , symbol.type ) << " ;" << std::endl;
0 commit comments