@@ -1019,6 +1019,48 @@ void c_typecheck_baset::typecheck_compound_body(
1019
1019
1020
1020
/* ******************************************************************\
1021
1021
1022
+ Function: c_typecheck_baset::fitting_int_type
1023
+
1024
+ Inputs:
1025
+
1026
+ Outputs:
1027
+
1028
+ Purpose:
1029
+
1030
+ \*******************************************************************/
1031
+
1032
+ typet c_typecheck_baset::fitting_int_type (
1033
+ const mp_integer &min_value,
1034
+ const mp_integer &max_value,
1035
+ bool at_least_int) const
1036
+ {
1037
+ if (max_value<(mp_integer (1 )<<(config.ansi_c .char_width -1 )) &&
1038
+ min_value>=-(mp_integer (1 )<<(config.ansi_c .char_width -1 )))
1039
+ return at_least_int?signed_int_type ():signed_char_type ();
1040
+ else if (max_value<(mp_integer (1 )<<config.ansi_c .char_width ) &&
1041
+ min_value>=0 )
1042
+ return at_least_int?signed_int_type ():unsigned_char_type ();
1043
+ else if (max_value<(mp_integer (1 )<<(config.ansi_c .short_int_width -1 )) &&
1044
+ min_value>=-(mp_integer (1 )<<(config.ansi_c .short_int_width -1 )))
1045
+ return at_least_int?signed_int_type ():signed_short_int_type ();
1046
+ else if (max_value<(mp_integer (1 )<<config.ansi_c .short_int_width ) &&
1047
+ min_value>=0 )
1048
+ return at_least_int?signed_int_type ():unsigned_short_int_type ();
1049
+ else if (max_value<(mp_integer (1 )<<(config.ansi_c .int_width -1 )) &&
1050
+ min_value>=-(mp_integer (1 )<<(config.ansi_c .int_width -1 )))
1051
+ return signed_int_type ();
1052
+ else if (max_value<(mp_integer (1 )<<config.ansi_c .int_width ) &&
1053
+ min_value>=0 )
1054
+ return unsigned_int_type ();
1055
+ else if (max_value<(mp_integer (1 )<<(config.ansi_c .long_long_int_width -1 )) &&
1056
+ min_value>=-(mp_integer (1 )<<(config.ansi_c .long_long_int_width -1 )))
1057
+ return signed_long_long_int_type ();
1058
+ else
1059
+ return unsigned_long_long_int_type ();
1060
+ }
1061
+
1062
+ /* ******************************************************************\
1063
+
1022
1064
Function: c_typecheck_baset::typecheck_c_enum_type
1023
1065
1024
1066
Inputs:
@@ -1046,36 +1088,54 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
1046
1088
throw 0 ;
1047
1089
}
1048
1090
1049
- // enums start at zero
1050
- mp_integer value=0 ;
1051
-
1052
- // track min and max to find a nice base type
1053
- mp_integer min_value=0 , max_value=0 ;
1054
-
1091
+ // enums start at zero;
1092
+ // we also track min and max to find a nice base type
1093
+ mp_integer value=0 , min_value=0 , max_value=0 ;
1094
+
1055
1095
std::list<c_enum_typet::c_enum_membert> enum_members;
1056
1096
1057
- Forall_operands (it, as_expr)
1058
- {
1059
- ansi_c_declarationt &declaration=to_ansi_c_declaration (*it);
1060
-
1061
- // In C, enum constants always have type "int". They do not
1062
- // have the enum type.
1063
- declaration.type ()=typet (ID_int);
1097
+ // We need to determine a width, and a signedness
1098
+ // to obtain an 'underlying type'.
1099
+ // We just do int, but gcc might pick smaller widths
1100
+ // if the type is marked as 'packed'.
1101
+ // gcc/clang may also pick a larger width. Visual Studio doesn't.
1064
1102
1103
+ for (auto & it : as_expr.operands ())
1104
+ {
1105
+ ansi_c_declarationt &declaration=to_ansi_c_declaration (it);
1065
1106
exprt &v=declaration.declarator ().value ();
1066
1107
1067
- if (v.is_nil ()) // no value given
1068
- v=from_integer (value, signed_int_type ());
1069
- else
1108
+ if (v.is_not_nil ()) // value given?
1070
1109
{
1071
1110
exprt tmp_v=v;
1072
1111
typecheck_expr (tmp_v);
1073
1112
add_rounding_mode (tmp_v);
1074
1113
simplify (tmp_v, *this );
1075
- if (tmp_v.is_constant ())
1076
- v=tmp_v;
1114
+ if (tmp_v.is_true ())
1115
+ value=1 ;
1116
+ else if (tmp_v.is_false ())
1117
+ value=0 ;
1118
+ else if (!to_integer (tmp_v, value))
1119
+ {
1120
+ }
1121
+ else
1122
+ {
1123
+ error ().source_location =v.source_location ();
1124
+ error () << " enum is not a constant" ;
1125
+ throw 0 ;
1126
+ }
1077
1127
}
1078
1128
1129
+ if (value<min_value) min_value=value;
1130
+ if (value>max_value) max_value=value;
1131
+
1132
+ // The type of the enum constant is 'int', unless it it's larger.
1133
+ typet underlying_type=
1134
+ fitting_int_type (min_value, max_value, true );
1135
+
1136
+ v=from_integer (value, underlying_type);
1137
+
1138
+ declaration.type ()=underlying_type;
1079
1139
typecheck_declaration (declaration);
1080
1140
1081
1141
irep_idt base_name=
@@ -1084,70 +1144,23 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
1084
1144
irep_idt identifier=
1085
1145
declaration.declarator ().get_name ();
1086
1146
1087
- // get value
1088
- const symbolt &symbol=lookup (identifier);
1089
-
1090
- to_integer (symbol.value , value);
1091
-
1092
1147
// store
1093
1148
c_enum_typet::c_enum_membert member;
1094
1149
member.set_identifier (identifier);
1095
1150
member.set_base_name (base_name);
1096
1151
member.set_value (integer2string (value));
1097
1152
enum_members.push_back (member);
1098
-
1099
- if (value<min_value) min_value=value;
1100
- if (value>max_value) max_value=value;
1101
-
1153
+
1102
1154
// produce value for next constant
1103
1155
++value;
1104
1156
}
1105
-
1157
+
1106
1158
// Remove these now; we add them to the
1107
1159
// c_enum symbol later.
1108
- #ifdef OPERANDS_IN_GETSUB
1109
1160
as_expr.operands ().clear ();
1110
- #else
1111
- type.remove (ID_operands);
1112
- #endif
1113
1161
1114
- // We need to determine a width, and a signedness.
1115
- // We just do int, but gcc might pick smaller widths
1116
- // if the type is marked as 'packed'.
1117
-
1118
- unsigned bits=0 ;
1119
- bool is_signed=min_value<0 ;
1120
-
1121
- if (is_signed)
1122
- {
1123
- if (max_value<(1 <<7 ) && min_value>=-(1 <<7 ))
1124
- bits=1 *8 ;
1125
- else if (max_value<(1 <<15 ) && min_value>=-(1 <<15 ))
1126
- bits=2 *8 ;
1127
- else if (max_value<(mp_integer (1 )<<31 ) && min_value>=-(mp_integer (1 )<<31 ))
1128
- bits=4 *8 ;
1129
- else
1130
- bits=8 *8 ;
1131
- }
1132
- else // unsigned
1133
- {
1134
- if (max_value<(1 <<8 ))
1135
- bits=1 *8 ;
1136
- else if (max_value<(1 <<16 ))
1137
- bits=2 *8 ;
1138
- else if (max_value<(mp_integer (1 )<<32 ))
1139
- bits=4 *8 ;
1140
- else
1141
- bits=8 *8 ;
1142
- }
1162
+ bool is_packed=type.get_bool (ID_C_packed);
1143
1163
1144
- if (!type.get_bool (ID_C_packed))
1145
- {
1146
- // If it's not packed we do int as a minimum.
1147
- if (bits<config.ansi_c .int_width )
1148
- bits=config.ansi_c .int_width ;
1149
- }
1150
-
1151
1164
// tag?
1152
1165
if (type.find (ID_tag).is_nil ())
1153
1166
{
@@ -1165,7 +1178,7 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
1165
1178
anon_identifier+=id2string (it->get_value ());
1166
1179
}
1167
1180
1168
- if (type. get_bool (ID_C_packed) )
1181
+ if (is_packed )
1169
1182
anon_identifier+=" #packed" ;
1170
1183
1171
1184
type.add (ID_tag).set (ID_identifier, anon_identifier);
@@ -1194,9 +1207,16 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
1194
1207
it++)
1195
1208
body.push_back (*it);
1196
1209
1197
- // We use a subtype to store signed and width
1198
- enum_tag_symbol.type .subtype ().id (is_signed?ID_signedbv:ID_unsignedbv);
1199
- enum_tag_symbol.type .subtype ().set (ID_width, bits);
1210
+ // We use a subtype to store the underlying type.
1211
+ // This is at least 'int' unless packed if negative,
1212
+ // and at least 'unsigned int' otherwise.
1213
+ typet underlying_type=
1214
+ fitting_int_type (min_value, max_value, !is_packed);
1215
+ if (underlying_type==signed_int_type () &&
1216
+ min_value>=0 )
1217
+ underlying_type=unsigned_int_type ();
1218
+
1219
+ enum_tag_symbol.type .subtype ()=underlying_type;
1200
1220
1201
1221
// is it in the symbol table already?
1202
1222
symbol_tablet::symbolst::iterator s_it=
0 commit comments