Skip to content

Commit 16b48f0

Browse files
committed
Set enum underlying type from specified type
1 parent d0cd064 commit 16b48f0

File tree

1 file changed

+49
-7
lines changed

1 file changed

+49
-7
lines changed

src/ansi-c/c_typecheck_type.cpp

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)