2019-09-15 Jason Merrill <jason@redhat.com>
+ PR c++/30277 - int-width bit-field promotion.
+ PR c++/33819 - long bit-field promotion.
+ * typeck.c (cp_perform_integral_promotions): Handle large bit-fields
+ properly. Handle 32-bit non-int bit-fields properly.
+ (is_bitfield_expr_with_lowered_type): Don't look through NOP_EXPR.
+
PR c++/82165 - enum bitfields and operator overloading.
* call.c (build_new_op_1): Use unlowered_expr_type.
else
return NULL_TREE;
- CASE_CONVERT:
- if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp, 0)))
- == TYPE_MAIN_VARIANT (TREE_TYPE (exp)))
- return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
- /* Fallthrough. */
-
default:
return NULL_TREE;
}
if (error_operand_p (expr))
return error_mark_node;
+ type = TREE_TYPE (expr);
+
/* [conv.prom]
- If the bitfield has an enumerated type, it is treated as any
- other value of that type for promotion purposes. */
- type = is_bitfield_expr_with_lowered_type (expr);
- if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
- type = TREE_TYPE (expr);
+ A prvalue for an integral bit-field (11.3.9) can be converted to a prvalue
+ of type int if int can represent all the values of the bit-field;
+ otherwise, it can be converted to unsigned int if unsigned int can
+ represent all the values of the bit-field. If the bit-field is larger yet,
+ no integral promotion applies to it. If the bit-field has an enumerated
+ type, it is treated as any other value of that type for promotion
+ purposes. */
+ tree bitfield_type = is_bitfield_expr_with_lowered_type (expr);
+ if (bitfield_type
+ && (TREE_CODE (bitfield_type) == ENUMERAL_TYPE
+ || TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)))
+ type = bitfield_type;
+
gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
/* Scoped enums don't promote. */
if (SCOPED_ENUM_P (type))
promoted_type = type_promotes_to (type);
if (type != promoted_type)
expr = cp_convert (promoted_type, expr, complain);
+ else if (bitfield_type && bitfield_type != type)
+ /* Prevent decay_conversion from converting to bitfield_type. */
+ expr = build_nop (type, expr);
return expr;
}