Commit ddc1a45b by Jason Merrill Committed by Jason Merrill

PR c++/30277 - int-width bit-field promotion.

Here, if cp_perform_integral_promotions saw that the TREE_TYPE of a
bit-field reference was the same as the type it promotes to, it didn't do
anything.  But then decay_conversion saw that the bit-field reference was
unchanged, and converted it to its declared type.  So I needed to add
something to make it clear that promotion has been done.  But then the 33819
change caused trouble by looking through the NOP_EXPR I just added.  This
was the wrong fix for that bug; I've now fixed that better by recognizing in
cp_perform_integral_promotions that we won't promote a bit-field larger than
32 bits, so we should use the declared type.

	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.

From-SVN: r275746
parent 47518e13
2019-09-15 Jason Merrill <jason@redhat.com> 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. PR c++/82165 - enum bitfields and operator overloading.
* call.c (build_new_op_1): Use unlowered_expr_type. * call.c (build_new_op_1): Use unlowered_expr_type.
......
...@@ -1971,12 +1971,6 @@ is_bitfield_expr_with_lowered_type (const_tree exp) ...@@ -1971,12 +1971,6 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
else else
return NULL_TREE; 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: default:
return NULL_TREE; return NULL_TREE;
} }
...@@ -2189,13 +2183,23 @@ cp_perform_integral_promotions (tree expr, tsubst_flags_t complain) ...@@ -2189,13 +2183,23 @@ cp_perform_integral_promotions (tree expr, tsubst_flags_t complain)
if (error_operand_p (expr)) if (error_operand_p (expr))
return error_mark_node; return error_mark_node;
type = TREE_TYPE (expr);
/* [conv.prom] /* [conv.prom]
If the bitfield has an enumerated type, it is treated as any A prvalue for an integral bit-field (11.3.9) can be converted to a prvalue
other value of that type for promotion purposes. */ of type int if int can represent all the values of the bit-field;
type = is_bitfield_expr_with_lowered_type (expr); otherwise, it can be converted to unsigned int if unsigned int can
if (!type || TREE_CODE (type) != ENUMERAL_TYPE) represent all the values of the bit-field. If the bit-field is larger yet,
type = TREE_TYPE (expr); 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)); gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
/* Scoped enums don't promote. */ /* Scoped enums don't promote. */
if (SCOPED_ENUM_P (type)) if (SCOPED_ENUM_P (type))
...@@ -2203,6 +2207,9 @@ cp_perform_integral_promotions (tree expr, tsubst_flags_t complain) ...@@ -2203,6 +2207,9 @@ cp_perform_integral_promotions (tree expr, tsubst_flags_t complain)
promoted_type = type_promotes_to (type); promoted_type = type_promotes_to (type);
if (type != promoted_type) if (type != promoted_type)
expr = cp_convert (promoted_type, expr, complain); 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; return expr;
} }
......
// PR c++/30277
// { dg-do compile { target c++11 } }
struct S
{
signed long l: 32;
};
void foo(long) = delete;
void foo(int) {}
int main()
{
S x = {1};
foo(x.l+0);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment