@@ -1019,6 +1019,48 @@ void c_typecheck_baset::typecheck_compound_body(
10191019
10201020/* ******************************************************************\
10211021
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+
10221064Function: c_typecheck_baset::typecheck_c_enum_type
10231065
10241066 Inputs:
@@ -1046,36 +1088,54 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
10461088 throw 0 ;
10471089 }
10481090
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+
10551095 std::list<c_enum_typet::c_enum_membert> enum_members;
10561096
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.
10641102
1103+ for (auto & it : as_expr.operands ())
1104+ {
1105+ ansi_c_declarationt &declaration=to_ansi_c_declaration (it);
10651106 exprt &v=declaration.declarator ().value ();
10661107
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?
10701109 {
10711110 exprt tmp_v=v;
10721111 typecheck_expr (tmp_v);
10731112 add_rounding_mode (tmp_v);
10741113 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+ }
10771127 }
10781128
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;
10791139 typecheck_declaration (declaration);
10801140
10811141 irep_idt base_name=
@@ -1084,70 +1144,23 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
10841144 irep_idt identifier=
10851145 declaration.declarator ().get_name ();
10861146
1087- // get value
1088- const symbolt &symbol=lookup (identifier);
1089-
1090- to_integer (symbol.value , value);
1091-
10921147 // store
10931148 c_enum_typet::c_enum_membert member;
10941149 member.set_identifier (identifier);
10951150 member.set_base_name (base_name);
10961151 member.set_value (integer2string (value));
10971152 enum_members.push_back (member);
1098-
1099- if (value<min_value) min_value=value;
1100- if (value>max_value) max_value=value;
1101-
1153+
11021154 // produce value for next constant
11031155 ++value;
11041156 }
1105-
1157+
11061158 // Remove these now; we add them to the
11071159 // c_enum symbol later.
1108- #ifdef OPERANDS_IN_GETSUB
11091160 as_expr.operands ().clear ();
1110- #else
1111- type.remove (ID_operands);
1112- #endif
11131161
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);
11431163
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-
11511164 // tag?
11521165 if (type.find (ID_tag).is_nil ())
11531166 {
@@ -1165,7 +1178,7 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
11651178 anon_identifier+=id2string (it->get_value ());
11661179 }
11671180
1168- if (type. get_bool (ID_C_packed) )
1181+ if (is_packed )
11691182 anon_identifier+=" #packed" ;
11701183
11711184 type.add (ID_tag).set (ID_identifier, anon_identifier);
@@ -1194,9 +1207,16 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
11941207 it++)
11951208 body.push_back (*it);
11961209
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;
12001220
12011221 // is it in the symbol table already?
12021222 symbol_tablet::symbolst::iterator s_it=
0 commit comments