[PATCH] c++: Deprecate arithmetic convs on different enums [PR97573]

Marek Polacek polacek@redhat.com
Thu Oct 29 02:46:54 GMT 2020


On Wed, Oct 28, 2020 at 02:43:30PM -0400, Jason Merrill wrote:
> On 10/28/20 2:01 PM, Marek Polacek wrote:
> > I noticed that C++20 P1120R0 deprecated certain arithmetic conversions
> > as outlined in [depr.arith.conv.enum], but we don't warn about them.  In
> > particular, "If one operand is of enumeration type and the other operand
> > is of a different enumeration type or a floating-point type, this
> > behavior is deprecated."  These will likely become ill-formed in C++23,
> > so we should warn by default in C++20.  To this effect, this patch adds
> > two new warnings (like clang++): -Wdeprecated-enum-enum-conversion and
> > -Wdeprecated-enum-float-conversion.  They are enabled by default in
> > C++20.  In older dialects, to enable these warnings you can now use
> > -Wenum-conversion which I made available in C++ too.  Note that unlike
> > C, in C++ it is not enabled by -Wextra, because that breaks bootstrap.
> > 
> > We already warn about comparisons of two different enumeration types via
> > -Wenum-compare, the rest is handled in this patch: we're performing the
> > usual arithmetic conversions in these contexts:
> >    - an arithmetic operation,
> >    - a bitwise operation,
> >    - a comparison,
> >    - a conditional operator,
> >    - a compound assign operator.
> > 
> > Using the spaceship operator as enum <=> real_type is ill-formed but we
> > don't reject it yet.
> 
> Hmm, oops.  Will you fix that as well?  It should be simple to fix in the
> SPACESHIP_EXPR block that starts just at the end of this patch.

Sure.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

>From 8ae2e45f2dd35510aed3be1ab249b8612e33f00d Mon Sep 17 00:00:00 2001
From: Marek Polacek <polacek@redhat.com>
Date: Wed, 28 Oct 2020 19:02:29 -0400
Subject: [PATCH] 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.
---
 gcc/cp/typeck.c                             | 13 ++++++++++--
 gcc/testsuite/g++.dg/cpp2a/enum-conv1.C     |  3 ---
 gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C | 23 +++++++++++++++++++++
 3 files changed, 34 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 7305310ecbe..d3b701610cf 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 d4960f334dd..4571b5e8968 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 00000000000..3dc2a0f2365
--- /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." }
+}

base-commit: 4166ebedf8b8a302b86132fdf846fac204c83368
-- 
2.28.0



More information about the Gcc-patches mailing list