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 | 1082 | } else |
| 1083 | 1083 | type.t = VT_INT; |
| 1084 | 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 | 1088 | type.t |= VT_UNSIGNED; |
| 1087 | 1089 | gen_cast(&type); |
| 1088 | 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.