aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2020-10-28 19:02:29 -0400
committerMarek Polacek <polacek@redhat.com>2020-10-29 14:06:13 -0400
commit79991e2348a864ace6ea2bf108a7502862f1129f (patch)
treea1208522e1a5783776514985cc2371947e4be5dc
parente1344fe7b6a96966281c78e46e777b456d5c2e19 (diff)
downloadgcc-79991e2348a864ace6ea2bf108a7502862f1129f.zip
gcc-79991e2348a864ace6ea2bf108a7502862f1129f.tar.gz
gcc-79991e2348a864ace6ea2bf108a7502862f1129f.tar.bz2
c++: Reject float <=> enum.
As [depr.arith.conv.enum] says, these are ill-formed. gcc/cp/ChangeLog: * typeck.c (do_warn_enum_conversions): Don't warn for SPACESHIP_EXPR. (cp_build_binary_op): Reject float <=> enum or enum <=> float. Use CP_INTEGRAL_TYPE_P instead of INTEGRAL_OR_ENUMERATION_TYPE_P. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/enum-conv1.C: Remove unused code. * g++.dg/cpp2a/spaceship-err5.C: New test.
-rw-r--r--gcc/cp/typeck.c13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/enum-conv1.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C23
3 files changed, 34 insertions, 5 deletions
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 7305310..d3b7016 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4512,6 +4512,9 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
"with enumeration type %qT is deprecated",
type0, type1);
return;
+ case SPACESHIP_EXPR:
+ /* This is invalid, don't warn. */
+ return;
default:
if (enum_first_p)
warning_at (loc, opt, "arithmetic between enumeration type %qT "
@@ -5584,6 +5587,12 @@ cp_build_binary_op (const op_location_t &location,
arithmetic conversions are applied to the operands." So we don't do
arithmetic conversions if the operands both have enumeral type. */
result_type = NULL_TREE;
+ else if ((orig_code0 == ENUMERAL_TYPE && orig_code1 == REAL_TYPE)
+ || (orig_code0 == REAL_TYPE && orig_code1 == ENUMERAL_TYPE))
+ /* [depr.arith.conv.enum]: Three-way comparisons between such operands
+ [where one is of enumeration type and the other is of a different
+ enumeration type or a floating-point type] are ill-formed. */
+ result_type = NULL_TREE;
if (result_type)
{
@@ -5598,12 +5607,12 @@ cp_build_binary_op (const op_location_t &location,
type to a floating point type, the program is ill-formed. */
bool ok = true;
if (TREE_CODE (result_type) == REAL_TYPE
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op0)))
+ && CP_INTEGRAL_TYPE_P (orig_type0))
/* OK */;
else if (!check_narrowing (result_type, orig_op0, complain))
ok = false;
if (TREE_CODE (result_type) == REAL_TYPE
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op1)))
+ && CP_INTEGRAL_TYPE_P (orig_type1))
/* OK */;
else if (!check_narrowing (result_type, orig_op1, complain))
ok = false;
diff --git a/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C b/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C
index d4960f3..4571b5e 100644
--- a/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C
@@ -110,9 +110,6 @@ enum_float (bool b)
r += b ? d : u1; // { dg-warning "conditional expression between" "" { target c++20 } }
r += b ? u1 : d; // { dg-warning "conditional expression between" "" { target c++20 } }
- // FIXME should be error
- // e1 <=> d;
-
d += e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
d = e1;
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C
new file mode 100644
index 0000000..3dc2a0f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++20 } }
+// Test [depr.arith.conv.enum] for <=>.
+
+#include <compare>
+
+enum E1 { e } e1;
+enum E2 { f } e2;
+static double d;
+
+void
+g ()
+{
+ void(e1 <=> e);
+ e1 <=> d; // { dg-error "invalid operands of types .E1. and .double." }
+ d <=> e1; // { dg-error "invalid operands of types .double. and .E1." }
+ e <=> d; // { dg-error "invalid operands of types .E1. and .double." }
+ d <=> e; // { dg-error "invalid operands of types .double. and .E1." }
+
+ e <=> f; // { dg-error "invalid operands of types .E1. and .E2." }
+ f <=> e; // { dg-error "invalid operands of types .E2. and .E1." }
+ e1 <=> e2; // { dg-error "invalid operands of types .E1. and .E2." }
+ e2 <=> e1; // { dg-error "invalid operands of types .E2. and .E1." }
+}