From 075723456073bf7319805ce964a3f8a036eb7d27 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Fri, 5 May 2017 23:16:43 +0200 Subject: [PATCH] Fix unsigned enum bit-fields 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. --- tccgen.c | 4 +- tests/tests2/92_enum_bitfield.c | 57 ++++++++++++++++++++++++++++ tests/tests2/92_enum_bitfield.expect | 0 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/tests2/92_enum_bitfield.c create mode 100644 tests/tests2/92_enum_bitfield.expect diff --git a/tccgen.c b/tccgen.c index cbfe5ff..b9938ea 100644 --- a/tccgen.c +++ b/tccgen.c @@ -1082,7 +1082,9 @@ ST_FUNC int gv(int rc) } else type.t = VT_INT; if((vtop->type.t & VT_UNSIGNED) || - (vtop->type.t & VT_BTYPE) == VT_BOOL) + (vtop->type.t & VT_BTYPE) == VT_BOOL || + (((vtop->type.t & VT_BTYPE) == VT_ENUM) && + vtop->type.ref->a.unsigned_enum)) type.t |= VT_UNSIGNED; gen_cast(&type); /* generate shifts */ diff --git a/tests/tests2/92_enum_bitfield.c b/tests/tests2/92_enum_bitfield.c new file mode 100644 index 0000000..bb6dc35 --- /dev/null +++ b/tests/tests2/92_enum_bitfield.c @@ -0,0 +1,57 @@ +/* This checks if enums needing 8 bit but only having positive + values are correctly zero extended (instead of sign extended) + when stored into/loaded from a 8 bit bit-field of enum type (which + itself is implementation defined, so isn't necessarily supported by all + other compilers). */ +enum tree_code { + SOME_CODE = 148, /* has bit 7 set, and hence all further enum values as well */ + LAST_AND_UNUSED_TREE_CODE +}; +typedef union tree_node *tree; +struct tree_common +{ + union tree_node *chain; + union tree_node *type; + enum tree_code code : 8; + unsigned side_effects_flag : 1; +}; +union tree_node +{ + struct tree_common common; + }; +enum c_tree_code { + C_DUMMY_TREE_CODE = LAST_AND_UNUSED_TREE_CODE, + STMT_EXPR, + LAST_C_TREE_CODE +}; +enum cplus_tree_code { + CP_DUMMY_TREE_CODE = LAST_C_TREE_CODE, + AMBIG_CONV, + LAST_CPLUS_TREE_CODE +}; + +extern int printf(const char *, ...); +int blah(){return 0;} + +int convert_like_real (tree convs) +{ + switch (((enum tree_code) (convs)->common.code)) + { + case AMBIG_CONV: /* This has bit 7 set, which must not be the sign + bit in tree_common.code, i.e. the bitfield must + be somehow marked unsigned. */ + return blah(); + default: + break; + }; + printf("unsigned enum bit-fields broken\n"); +} + +int main() +{ + union tree_node convs; + + convs.common.code = AMBIG_CONV; + convert_like_real (&convs); + return 0; +} diff --git a/tests/tests2/92_enum_bitfield.expect b/tests/tests2/92_enum_bitfield.expect new file mode 100644 index 0000000..e69de29