@@ -1160,10 +1160,24 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
11601160 throw 0 ;
11611161 }
11621162
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)
11641167 {
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+ }
11671181 }
11681182
11691183 // enums start at zero;
@@ -1211,8 +1225,27 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
12111225 if (value>max_value)
12121226 max_value=value;
12131227
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+ }
12161249
12171250 v=from_integer (value, constant_type);
12181251
@@ -1245,8 +1278,17 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
12451278 bool is_packed=type.get_bool (ID_C_packed);
12461279
12471280 // 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+ }
12501292
12511293 // Get the width to make the values have a bitvector type
12521294 std::size_t width = underlying_type.get_width ();
0 commit comments