aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/typeck.c29
-rw-r--r--gcc/testsuite/g++.dg/expr/bitfield14.C17
3 files changed, 41 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bed72c9..7bf28f8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
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.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 620f2c9..c6bf41e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1971,12 +1971,6 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
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;
}
@@ -2189,13 +2183,23 @@ cp_perform_integral_promotions (tree expr, tsubst_flags_t complain)
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))
@@ -2203,6 +2207,9 @@ cp_perform_integral_promotions (tree expr, tsubst_flags_t complain)
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;
}
diff --git a/gcc/testsuite/g++.dg/expr/bitfield14.C b/gcc/testsuite/g++.dg/expr/bitfield14.C
new file mode 100644
index 0000000..546af85
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/bitfield14.C
@@ -0,0 +1,17 @@
+// 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;
+}