@@ -1160,10 +1160,24 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
1160
1160
throw 0 ;
1161
1161
}
1162
1162
1163
- if (as_expr.find (ID_enum_underlying_type).is_not_nil ())
1163
+ const bool have_underlying_type =
1164
+ type.find_type (ID_enum_underlying_type).is_not_nil ();
1165
+
1166
+ if (have_underlying_type)
1164
1167
{
1165
- warning ().source_location = source_location;
1166
- warning () << " ignoring specification of underlying type for enum" << eom;
1168
+ typecheck_type (type.add_type (ID_enum_underlying_type));
1169
+
1170
+ const typet &underlying_type =
1171
+ static_cast <const typet &>(type.find (ID_enum_underlying_type));
1172
+
1173
+ if (!is_signed_or_unsigned_bitvector (underlying_type))
1174
+ {
1175
+ std::ostringstream msg;
1176
+ msg << source_location << " : non-integral type '"
1177
+ << underlying_type.get (ID_C_c_type)
1178
+ << " ' is an invalid underlying type" ;
1179
+ throw invalid_source_file_exceptiont{msg.str ()};
1180
+ }
1167
1181
}
1168
1182
1169
1183
// enums start at zero;
@@ -1211,8 +1225,27 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
1211
1225
if (value>max_value)
1212
1226
max_value=value;
1213
1227
1214
- typet constant_type=
1215
- enum_constant_type (min_value, max_value);
1228
+ typet constant_type;
1229
+
1230
+ if (have_underlying_type)
1231
+ {
1232
+ constant_type = type.find_type (ID_enum_underlying_type);
1233
+ const auto &tmp = to_integer_bitvector_type (constant_type);
1234
+
1235
+ if (value < tmp.smallest () || value > tmp.largest ())
1236
+ {
1237
+ std::ostringstream msg;
1238
+ msg
1239
+ << v.source_location ()
1240
+ << " : enumerator value is not representable in the underlying type '"
1241
+ << constant_type.get (ID_C_c_type) << " '" ;
1242
+ throw invalid_source_file_exceptiont{msg.str ()};
1243
+ }
1244
+ }
1245
+ else
1246
+ {
1247
+ constant_type = enum_constant_type (min_value, max_value);
1248
+ }
1216
1249
1217
1250
v=from_integer (value, constant_type);
1218
1251
@@ -1245,8 +1278,17 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
1245
1278
bool is_packed=type.get_bool (ID_C_packed);
1246
1279
1247
1280
// We use a subtype to store the underlying type.
1248
- bitvector_typet underlying_type =
1249
- enum_underlying_type (min_value, max_value, is_packed);
1281
+ bitvector_typet underlying_type (ID_nil);
1282
+
1283
+ if (have_underlying_type)
1284
+ {
1285
+ underlying_type =
1286
+ to_bitvector_type (type.find_type (ID_enum_underlying_type));
1287
+ }
1288
+ else
1289
+ {
1290
+ underlying_type = enum_underlying_type (min_value, max_value, is_packed);
1291
+ }
1250
1292
1251
1293
// Get the width to make the values have a bitvector type
1252
1294
std::size_t width = underlying_type.get_width ();
0 commit comments