------- Comment #3 from jakub at gcc dot gnu dot org 2008-09-01 12:40 ------- This is a C++ FE bug. Shorter testcase: enum E { E0 = 0, E1 = 'E' };
struct S { E s0 : 8; enum E foo (bool, E); }; E S::foo (bool a, E b) { return a ? s0 : b; } The bug is IMHO in build_conditional_expr. One of: arg2_type = unlowered_expr_type (arg2); arg3_type = unlowered_expr_type (arg3); calls returns a different type from TREE_TYPE (argX), as that's bitfield COMPONENT_REF. Neither of the types are void and neither is class type, so nothing is converted first and we reach: /* [expr.cond] If the second and third operands are lvalues and have the same type, the result is of that type and is an lvalue. */ if (real_lvalue_p (arg2) && real_lvalue_p (arg3) && same_type_p (arg2_type, arg3_type)) { result_type = arg2_type; goto valid_operands; } where arg2_type is the same as arg3_type, but TREE_TYPE (arg2) != TREE_TYPE (arg3), not even useless type conversion, and at valid_operands we build it right away as COND_EXPR. Can x ? bitfield : val be even considered as valid lvalue by C++ standard (I mean e.g. bitfield can have different number of bits from val)? If we don't shortcut here, force_rvalue is called on both arguments and that will call the needed convert_bitfield_to_declared_type somewhere. E.g.: --- call.c.jj2008-08-29 18:23:10.000000000 +0200 +++ call.c2008-09-01 14:27:24.000000000 +0200 @@ -3596,7 +3596,9 @@ build_conditional_expr (tree arg1, tree type, the result is of that type and is an lvalue. */ if (real_lvalue_p (arg2) && real_lvalue_p (arg3) - && same_type_p (arg2_type, arg3_type)) + && same_type_p (arg2_type, arg3_type) + && is_bitfield_expr_with_lowered_type (arg2) == NULL_TREE + && is_bitfield_expr_with_lowered_type (arg3) == NULL_TREE) { result_type = arg2_type; goto valid_operands; cures this testcase, but I'm not sure if it is correct from C++ standard POV. -- jakub at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jason at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37146