See testcase. If an enum has only positive values, fits N bits, and is placed in a N-bit bit-field that bit-fields must be treated as unsigned, not signed.
Unified · Split
| @@ -1082,7 +1082,9 @@ ST_FUNC int gv(int rc) · 1081 unmodified lines | |||
| 1082 | } else | 1082 | } else |
| 1083 | type.t = VT_INT; | 1083 | type.t = VT_INT; |
| 1084 | if((vtop->type.t & VT_UNSIGNED) || | 1084 | if((vtop->type.t & VT_UNSIGNED) || |
| 1085 | (vtop->type.t & VT_BTYPE) == VT_BOOL) | 1085 | (vtop->type.t & VT_BTYPE) == VT_BOOL || |
| 1086 | (((vtop->type.t & VT_BTYPE) == VT_ENUM) && | ||
| 1087 | vtop->type.ref->a.unsigned_enum)) | ||
| 1086 | type.t |= VT_UNSIGNED; | 1088 | type.t |= VT_UNSIGNED; |
| 1087 | gen_cast(&type); | 1089 | gen_cast(&type); |
| 1088 | /* generate shifts */ | 1090 | /* generate shifts */ |
| @@ -0,0 +1,57 @@ | |||
| 1 | /* This checks if enums needing 8 bit but only having positive | ||
| 2 | values are correctly zero extended (instead of sign extended) | ||
| 3 | when stored into/loaded from a 8 bit bit-field of enum type (which | ||
| 4 | itself is implementation defined, so isn't necessarily supported by all | ||
| 5 | other compilers). */ | ||
| 6 | enum tree_code { | ||
| 7 | SOME_CODE = 148, /* has bit 7 set, and hence all further enum values as well */ | ||
| 8 | LAST_AND_UNUSED_TREE_CODE | ||
| 9 | }; | ||
| 10 | typedef union tree_node *tree; | ||
| 11 | struct tree_common | ||
| 12 | { | ||
| 13 | union tree_node *chain; | ||
| 14 | union tree_node *type; | ||
| 15 | enum tree_code code : 8; | ||
| 16 | unsigned side_effects_flag : 1; | ||
| 17 | }; | ||
| 18 | union tree_node | ||
| 19 | { | ||
| 20 | struct tree_common common; | ||
| 21 | }; | ||
| 22 | enum c_tree_code { | ||
| 23 | C_DUMMY_TREE_CODE = LAST_AND_UNUSED_TREE_CODE, | ||
| 24 | STMT_EXPR, | ||
| 25 | LAST_C_TREE_CODE | ||
| 26 | }; | ||
| 27 | enum cplus_tree_code { | ||
| 28 | CP_DUMMY_TREE_CODE = LAST_C_TREE_CODE, | ||
| 29 | AMBIG_CONV, | ||
| 30 | LAST_CPLUS_TREE_CODE | ||
| 31 | }; | ||
| 32 | |||
| 33 | extern int printf(const char *, ...); | ||
| 34 | int blah(){return 0;} | ||
| 35 | |||
| 36 | int convert_like_real (tree convs) | ||
| 37 | { | ||
| 38 | switch (((enum tree_code) (convs)->common.code)) | ||
| 39 | { | ||
| 40 | case AMBIG_CONV: /* This has bit 7 set, which must not be the sign | ||
| 41 | bit in tree_common.code, i.e. the bitfield must | ||
| 42 | be somehow marked unsigned. */ | ||
| 43 | return blah(); | ||
| 44 | default: | ||
| 45 | break; | ||
| 46 | }; | ||
| 47 | printf("unsigned enum bit-fields broken\n"); | ||
| 48 | } | ||
| 49 | |||
| 50 | int main() | ||
| 51 | { | ||
| 52 | union tree_node convs; | ||
| 53 | |||
| 54 | convs.common.code = AMBIG_CONV; | ||
| 55 | convert_like_real (&convs); | ||
| 56 | return 0; | ||
| 57 | } | ||
Empty file added.