Hi!

The following patch implements C++26 P2864R2 by emitting pedwarn enabled by
the same options as the C++20 and later warnings (i.e. -Wenum-compare,
-Wdeprecated-enum-enum-conversion and -Wdeprecated-enum-float-conversion
which are all enabled by default).  I think we still want to allow users
some option workaround, so am not using directly error, but if that is
what you want instead, I can change it.

Tested on x86_64-linux with GXX_TESTSUITE_STDS=98,11,14,17,20,23,2c, ok
for trunk?

2023-11-13  Jakub Jelinek  <ja...@redhat.com>

gcc/cp/
        * typeck.cc: Implement C++26 P2864R2 - Remove Deprecated Arithmetic
        Conversion on Enumerations From C++26.
        (do_warn_enum_conversions): Use pedwarn rather than warning_at for
        C++26 and remove " is deprecated" part of the diagnostics in that
        case.
        (cp_build_binary_op): For C++26 call do_warn_enum_conversions
        for complain & tf_warning_or_error.
        * call.cc (build_conditional_expr): Use pedwarn rather than warning_at
        for C++26 and remove " is deprecated" part of the diagnostics in that
        case and check for complain & tf_warning_or_error.  Use emit_diagnostic
        with cxx_dialect >= cxx26 ? DK_PEDWARN : DK_WARNING.
        (build_new_op): Use emit_diagnostic with cxx_dialect >= cxx26
        ? DK_PEDWARN : DK_WARNING and complain & tf_warning_or_error check
        for C++26.
gcc/testsuite/
        * g++.dg/cpp2a/enum-conv1.C: Adjust expected diagnostics in C++26.
        * g++.dg/diagnostic/enum3.C: Likewise.
        * g++.dg/parse/attr3.C: Likewise.
        * g++.dg/cpp0x/linkage2.C: Likewise.

--- gcc/cp/typeck.cc.jj 2023-11-02 07:49:16.135878656 +0100
+++ gcc/cp/typeck.cc    2023-11-13 11:03:42.869760702 +0100
@@ -4976,13 +4976,21 @@ do_warn_enum_conversions (location_t loc
        case BIT_AND_EXPR:
        case BIT_IOR_EXPR:
        case BIT_XOR_EXPR:
-         warning_at (loc, opt, "bitwise operation between different "
-                     "enumeration types %qT and %qT is deprecated",
-                     type0, type1);
+         if (cxx_dialect >= cxx26)
+           pedwarn (loc, opt, "bitwise operation between different "
+                    "enumeration types %qT and %qT", type0, type1);
+         else
+           warning_at (loc, opt, "bitwise operation between different "
+                       "enumeration types %qT and %qT is deprecated",
+                       type0, type1);
          return;
        default:
-         warning_at (loc, opt, "arithmetic between different enumeration "
-                     "types %qT and %qT is deprecated", type0, type1);
+         if (cxx_dialect >= cxx26)
+           pedwarn (loc, opt, "arithmetic between different enumeration "
+                    "types %qT and %qT", type0, type1);
+         else
+           warning_at (loc, opt, "arithmetic between different enumeration "
+                       "types %qT and %qT is deprecated", type0, type1);
          return;
        }
     }
@@ -5010,7 +5018,13 @@ do_warn_enum_conversions (location_t loc
        case LE_EXPR:
        case EQ_EXPR:
        case NE_EXPR:
-         if (enum_first_p)
+         if (enum_first_p && cxx_dialect >= cxx26)
+           pedwarn (loc, opt, "comparison of enumeration type %qT with "
+                    "floating-point type %qT", type0, type1);
+         else if (cxx_dialect >= cxx26)
+           pedwarn (loc, opt, "comparison of floating-point type %qT "
+                     "with enumeration type %qT", type0, type1);
+         else if (enum_first_p)
            warning_at (loc, opt, "comparison of enumeration type %qT with "
                        "floating-point type %qT is deprecated",
                        type0, type1);
@@ -5023,7 +5037,13 @@ do_warn_enum_conversions (location_t loc
          /* This is invalid, don't warn.  */
          return;
        default:
-         if (enum_first_p)
+         if (enum_first_p && cxx_dialect >= cxx26)
+           pedwarn (loc, opt, "arithmetic between enumeration type %qT "
+                    "and floating-point type %qT", type0, type1);
+         else if (cxx_dialect >= cxx26)
+           pedwarn (loc, opt, "arithmetic between floating-point type %qT "
+                    "and enumeration type %qT", type0, type1);
+         else if (enum_first_p)
            warning_at (loc, opt, "arithmetic between enumeration type %qT "
                        "and floating-point type %qT is deprecated",
                        type0, type1);
@@ -6163,15 +6183,13 @@ cp_build_binary_op (const op_location_t
          return error_mark_node;
        }
       if (complain & tf_warning)
-       {
-         do_warn_double_promotion (result_type, type0, type1,
-                                   "implicit conversion from %qH to %qI "
-                                   "to match other operand of binary "
-                                   "expression",
-                                   location);
-         do_warn_enum_conversions (location, code, TREE_TYPE (orig_op0),
-                                   TREE_TYPE (orig_op1));
-       }
+       do_warn_double_promotion (result_type, type0, type1,
+                                 "implicit conversion from %qH to %qI "
+                                 "to match other operand of binary "
+                                 "expression", location);
+      if (complain & (cxx_dialect >= cxx26 ? tf_warning_or_error : tf_warning))
+       do_warn_enum_conversions (location, code, TREE_TYPE (orig_op0),
+                                 TREE_TYPE (orig_op1));
     }
   if (may_need_excess_precision
       && (orig_type0 != type0 || orig_type1 != type1)
--- gcc/cp/call.cc.jj   2023-11-11 08:51:54.419204769 +0100
+++ gcc/cp/call.cc      2023-11-13 11:16:08.033333959 +0100
@@ -6163,19 +6163,30 @@ build_conditional_expr (const op_locatio
                  == DECL_CONTEXT (stripped_orig_arg3)))
            /* Two enumerators from the same enumeration can have different
               types when the enumeration is still being defined.  */;
-          else if (complain & tf_warning)
-           warning_at (loc, OPT_Wenum_compare, "enumerated mismatch "
-                       "in conditional expression: %qT vs %qT",
-                       arg2_type, arg3_type);
+         else if (complain & (cxx_dialect >= cxx26
+                              ? tf_warning_or_error : tf_warning))
+           emit_diagnostic (cxx_dialect >= cxx26 ? DK_PEDWARN : DK_WARNING,
+                            loc, OPT_Wenum_compare, "enumerated mismatch "
+                            "in conditional expression: %qT vs %qT",
+                            arg2_type, arg3_type);
         }
-      else if ((complain & tf_warning)
+      else if ((complain & (cxx_dialect >= cxx26
+                           ? tf_warning_or_error : tf_warning))
               && warn_deprecated_enum_float_conv
               && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
                    && SCALAR_FLOAT_TYPE_P (arg3_type))
                   || (SCALAR_FLOAT_TYPE_P (arg2_type)
                       && TREE_CODE (arg3_type) == ENUMERAL_TYPE)))
        {
-         if (TREE_CODE (arg2_type) == ENUMERAL_TYPE)
+         if (cxx_dialect >= cxx26 && TREE_CODE (arg2_type) == ENUMERAL_TYPE)
+           pedwarn (loc, OPT_Wdeprecated_enum_float_conversion,
+                    "conditional expression between enumeration type "
+                    "%qT and floating-point type %qT", arg2_type, arg3_type);
+         else if (cxx_dialect >= cxx26)
+           pedwarn (loc, OPT_Wdeprecated_enum_float_conversion,
+                    "conditional expression between floating-point type "
+                    "%qT and enumeration type %qT", arg2_type, arg3_type);
+         else if (TREE_CODE (arg2_type) == ENUMERAL_TYPE)
            warning_at (loc, OPT_Wdeprecated_enum_float_conversion,
                        "conditional expression between enumeration type "
                        "%qT and floating-point type %qT is deprecated",
@@ -7259,10 +7270,13 @@ build_new_op (const op_location_t &loc,
                  && TREE_CODE (arg2_type) == ENUMERAL_TYPE
                  && (TYPE_MAIN_VARIANT (arg1_type)
                      != TYPE_MAIN_VARIANT (arg2_type))
-                 && (complain & tf_warning))
-               warning_at (loc, OPT_Wenum_compare,
-                           "comparison between %q#T and %q#T",
-                           arg1_type, arg2_type);
+                 && (complain & (cxx_dialect >= cxx26
+                                 ? tf_warning_or_error : tf_warning)))
+               emit_diagnostic (cxx_dialect >= cxx26
+                                ? DK_PEDWARN : DK_WARNING,
+                                loc, OPT_Wenum_compare,
+                                "comparison between %q#T and %q#T",
+                                arg1_type, arg2_type);
              break;
            default:
              break;
--- gcc/testsuite/g++.dg/cpp2a/enum-conv1.C.jj  2020-10-30 08:59:57.068496404 
+0100
+++ gcc/testsuite/g++.dg/cpp2a/enum-conv1.C     2023-11-13 11:38:24.454690122 
+0100
@@ -14,11 +14,16 @@ void
 conv ()
 {
   bool b1 = e == e1;
-  bool b2 = e == f; // { dg-warning "comparison between .enum E1. and .enum 
E2." }
-  bool b3 = e == 0.0; // { dg-warning "comparison of enumeration type .E1. 
with floating-point type .double." "" { target c++20 } }
-  bool b4 = 0.0 == f; // { dg-warning "comparison of floating-point type 
.double. with enumeration type .E2." "" { target c++20 } }
-  int n1 = true ? e : f; // { dg-warning "enumerated mismatch" }
-  int n2 = true ? e : 0.0; // { dg-warning "conditional expression between" "" 
{ target c++20 } }
+  bool b2 = e == f; // { dg-warning "comparison between .enum E1. and .enum 
E2." "" { target c++23_down } }
+                   // { dg-error "comparison between .enum E1. and .enum E2." 
"" { target c++26 } .-1 }
+  bool b3 = e == 0.0; // { dg-warning "comparison of enumeration type .E1. 
with floating-point type .double." "" { target { c++20 && c++23_down } } }
+                     // { dg-error "comparison of enumeration type .E1. with 
floating-point type .double." "" { target c++26 } .-1 }
+  bool b4 = 0.0 == f; // { dg-warning "comparison of floating-point type 
.double. with enumeration type .E2." "" { target { c++20 && c++23_down } } }
+                     // { dg-error "comparison of floating-point type .double. 
with enumeration type .E2." "" { target c++26 } .-1 }
+  int n1 = true ? e : f; // { dg-warning "enumerated mismatch" "" { target 
c++23_down } }
+                        // { dg-error "enumerated mismatch" "" { target c++26 
} .-1 }
+  int n2 = true ? e : 0.0; // { dg-warning "conditional expression between" "" 
{ target { c++20 && c++23_down } } }
+                          // { dg-error "conditional expression between" "" { 
target c++26 } .-1 }
 }
 
 int
@@ -29,42 +34,60 @@ enum_enum (bool b)
 
   r += e - e;
   r += e - e1;
-  r += e - f; // { dg-warning "arithmetic between different enumeration types 
.E1. and .E2." "" { target c++20 } }
-  r += f - e; // { dg-warning "arithmetic between different enumeration types 
.E2. and .E1." "" { target c++20 } }
-
+  r += e - f; // { dg-warning "arithmetic between different enumeration types 
.E1. and .E2." "" { target { c++20 && c++23_down } } }
+             // { dg-error "arithmetic between different enumeration types 
.E1. and .E2." "" { target c++26 } .-1 }
+  r += f - e; // { dg-warning "arithmetic between different enumeration types 
.E2. and .E1." "" { target { c++20 && c++23_down } } }
+             // { dg-error "arithmetic between different enumeration types 
.E2. and .E1." "" { target c++26 } .-1 }
   r += f + f;
-  r += f + e; // { dg-warning "arithmetic between different enumeration types 
.E2. and .E1." "" { target c++20 } }
-  r += e + f; // { dg-warning "arithmetic between different enumeration types 
.E1. and .E2." "" { target c++20 } }
+  r += f + e; // { dg-warning "arithmetic between different enumeration types 
.E2. and .E1." "" { target { c++20 && c++23_down } } }
+             // { dg-error "arithmetic between different enumeration types 
.E2. and .E1." "" { target c++26 } .-1 }
+  r += e + f; // { dg-warning "arithmetic between different enumeration types 
.E1. and .E2." "" { target { c++20 && c++23_down } } }
+             // { dg-error "arithmetic between different enumeration types 
.E1. and .E2." "" { target c++26 } .-1 }
 
-  r += e1 - e2; // { dg-warning "arithmetic between different enumeration 
types .E1. and .E2." "" { target c++20 } }
+  r += e1 - e2; // { dg-warning "arithmetic between different enumeration 
types .E1. and .E2." "" { target { c++20 && c++23_down } } }
+             // { dg-error "arithmetic between different enumeration types 
.E1. and .E2." "" { target c++26 } .-1 }
   r += e1 - e1c;
   r += e1c - e1;
 
-  r += e * f; // { dg-warning "arithmetic between different enumeration types 
.E1. and .E2." "" { target c++20 } }
-  r += f * e; // { dg-warning "arithmetic between different enumeration types 
.E2. and .E1." "" { target c++20 } }
+  r += e * f; // { dg-warning "arithmetic between different enumeration types 
.E1. and .E2." "" { target { c++20 && c++23_down } } }
+             // { dg-error "arithmetic between different enumeration types 
.E1. and .E2." "" { target c++26 } .-1 }
+  r += f * e; // { dg-warning "arithmetic between different enumeration types 
.E2. and .E1." "" { target { c++20 && c++23_down } } }
+             // { dg-error "arithmetic between different enumeration types 
.E2. and .E1." "" { target c++26 } .-1 }
   r += e * e;
 
   r += e1 < e1c;
   r += e < e1;
-  r += e1 < e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
-  r += e < f; // { dg-warning "comparison between .enum E1. and .enum E2." }
-  r += f < e; // { dg-warning "comparison between .enum E2. and .enum E1." }
+  r += e1 < e2; // { dg-warning "comparison between .enum E1. and .enum E2." 
"" { target c++23_down } }
+               // { dg-error "comparison between .enum E1. and .enum E2." "" { 
target c++26 } .-1 }
+  r += e < f; // { dg-warning "comparison between .enum E1. and .enum E2." "" 
{ target c++23_down } }
+             // { dg-error "comparison between .enum E1. and .enum E2." "" { 
target c++26 } .-1 }
+  r += f < e; // { dg-warning "comparison between .enum E2. and .enum E1." "" 
{ target c++23_down } }
+             // { dg-error "comparison between .enum E2. and .enum E1." "" { 
target c++26 } .-1 }
 
   r += e1 == e1c;
   r += e == e1;
-  r += e == f; // { dg-warning "comparison between .enum E1. and .enum E2." }
-  r += f == e; // { dg-warning "comparison between .enum E2. and .enum E1." }
-  r += e1 == e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
-  r += e2 == e1; // { dg-warning "comparison between .enum E2. and .enum E1." }
+  r += e == f; // { dg-warning "comparison between .enum E1. and .enum E2." "" 
{ target c++23_down } }
+              // { dg-error "comparison between .enum E1. and .enum E2." "" { 
target c++26 } .-1 }
+  r += f == e; // { dg-warning "comparison between .enum E2. and .enum E1." "" 
{ target c++23_down } }
+              // { dg-error "comparison between .enum E2. and .enum E1." "" { 
target c++26 } .-1 }
+  r += e1 == e2; // { dg-warning "comparison between .enum E1. and .enum E2." 
"" { target c++23_down } }
+                // { dg-error "comparison between .enum E1. and .enum E2." "" 
{ target c++26 } .-1 }
+  r += e2 == e1; // { dg-warning "comparison between .enum E2. and .enum E1." 
"" { target c++23_down } }
+                // { dg-error "comparison between .enum E2. and .enum E1." "" 
{ target c++26 } .-1 }
 
   r += b ? e1 : e1c;
   r += b ? e1 : e;
-  r += b ? f : e; // { dg-warning "enumerated mismatch in conditional 
expression: .E2. vs .E1." }
-  r += b ? e1 : e2; // { dg-warning "enumerated mismatch in conditional 
expression: .E1. vs .E2." }
-
-  r += e | f; // { dg-warning "bitwise operation between different enumeration 
types .E1. and .E2." "" { target c++20 } }
-  r += e ^ f; // { dg-warning "bitwise operation between different enumeration 
types .E1. and .E2." "" { target c++20 } }
-  r += e & f; // { dg-warning "bitwise operation between different enumeration 
types .E1. and .E2." "" { target c++20 } }
+  r += b ? f : e; // { dg-warning "enumerated mismatch in conditional 
expression: .E2. vs .E1." "" { target c++23_down } }
+                 // { dg-error "enumerated mismatch in conditional expression: 
.E2. vs .E1." "" { target c++26 } .-1 }
+  r += b ? e1 : e2; // { dg-warning "enumerated mismatch in conditional 
expression: .E1. vs .E2." "" { target c++23_down } }
+                   // { dg-error "enumerated mismatch in conditional 
expression: .E1. vs .E2." "" { target c++26 } .-1 }
+
+  r += e | f; // { dg-warning "bitwise operation between different enumeration 
types .E1. and .E2." "" { target { c++20 && c++23_down } } }
+             // { dg-error "bitwise operation between different enumeration 
types .E1. and .E2." "" { target c++26 } .-1 }
+  r += e ^ f; // { dg-warning "bitwise operation between different enumeration 
types .E1. and .E2." "" { target { c++20 && c++23_down } } }
+             // { dg-error "bitwise operation between different enumeration 
types .E1. and .E2." "" { target c++26 } .-1 }
+  r += e & f; // { dg-warning "bitwise operation between different enumeration 
types .E1. and .E2." "" { target { c++20 && c++23_down } } }
+             // { dg-error "bitwise operation between different enumeration 
types .E1. and .E2." "" { target c++26 } .-1 }
   r += !e;
   r += e1 | e;
 
@@ -76,10 +99,14 @@ enum_enum (bool b)
 
   // Anonymous enum.
   r += u1 - u1;
-  r += u1 + u2; // { dg-warning "arithmetic between different enumeration 
types" "" { target c++20 } }
-  r += u1 * u2; // { dg-warning "arithmetic between different enumeration 
types" "" { target c++20 } }
-  r += u1 == u2; // { dg-warning "comparison between" }
-  r += u1 & u2; // { dg-warning "bitwise operation between different 
enumeration types" "" { target c++20 } }
+  r += u1 + u2; // { dg-warning "arithmetic between different enumeration 
types" "" { target { c++20 && c++23_down } } }
+               // { dg-error "arithmetic between different enumeration types" 
"" { target c++26 } .-1 }
+  r += u1 * u2; // { dg-warning "arithmetic between different enumeration 
types" "" { target { c++20 && c++23_down } } }
+               // { dg-error "arithmetic between different enumeration types" 
"" { target c++26 } .-1 }
+  r += u1 == u2; // { dg-warning "comparison between" "" { target c++23_down } 
}
+                // { dg-error "comparison between" "" { target c++26 } .-1 }
+  r += u1 & u2; // { dg-warning "bitwise operation between different 
enumeration types" "" { target { c++20 && c++23_down } } }
+               // { dg-error "bitwise operation between different enumeration 
types" "" { target c++26 } .-1 }
 
   return r;
 }
@@ -89,28 +116,47 @@ enum_float (bool b)
 {
   double r = 0.0;
 
-  r += e1 - d; // { dg-warning "arithmetic between enumeration type .E1. and 
floating-point type .double." "" { target c++20 } }
-  r += d - e1; // { dg-warning "arithmetic between floating-point type 
.double. and enumeration type .E1." "" { target c++20 } }
-  r += e1 + d; // { dg-warning "arithmetic between enumeration type .E1. and 
floating-point type .double." "" { target c++20 } }
-  r += d + e1; // { dg-warning "arithmetic between floating-point type 
.double. and enumeration type .E1." "" { target c++20 } }
-  r += e1 * d; // { dg-warning "arithmetic between enumeration type .E1. and 
floating-point type .double." "" { target c++20 } }
-  r += d * e1; // { dg-warning "arithmetic between floating-point type 
.double. and enumeration type .E1." "" { target c++20 } }
-  r += u1 * d; // { dg-warning "arithmetic between enumeration type" "" { 
target c++20 } }
-  r += d * u1; // { dg-warning "arithmetic between floating-point type" "" { 
target c++20 } }
-
-  r += e1 < d;  // { dg-warning "comparison of enumeration type .E1. with 
floating-point type .double." "" { target c++20 } }
-  r += d < e1;  // { dg-warning "comparison of floating-point type .double. 
with enumeration type .E1." "" { target c++20 } }
-  r += d == e1; // { dg-warning "comparison of floating-point type .double. 
with enumeration type .E1." "" { target c++20 } }
-  r += e1 == d; // { dg-warning "comparison of enumeration type .E1. with 
floating-point type .double." "" { target c++20 } }
-  r += u1 == d; // { dg-warning "comparison of enumeration type" "" { target 
c++20 } }
-  r += d == u1; // { dg-warning "comparison of floating-point type" "" { 
target c++20 } }
-
-  r += b ? e1 : d; // { dg-warning "conditional expression between enumeration 
type .E1. and floating-point type .double." "" { target c++20 } }
-  r += b ? d : e1; // { dg-warning "conditional expression between 
floating-point type .double. and enumeration type .E1." "" { target c++20 } }
-  r += b ? d : u1; // { dg-warning "conditional expression between" "" { 
target c++20 } }
-  r += b ? u1 : d; // { dg-warning "conditional expression between" "" { 
target c++20 } }
+  r += e1 - d; // { dg-warning "arithmetic between enumeration type .E1. and 
floating-point type .double." "" { target { c++20 && c++23_down } } }
+              // { dg-error "arithmetic between enumeration type .E1. and 
floating-point type .double." "" { target c++26 } .-1 }
+  r += d - e1; // { dg-warning "arithmetic between floating-point type 
.double. and enumeration type .E1." "" { target { c++20 && c++23_down } } }
+              // { dg-error "arithmetic between floating-point type .double. 
and enumeration type .E1." "" { target c++26 } .-1 }
+  r += e1 + d; // { dg-warning "arithmetic between enumeration type .E1. and 
floating-point type .double." "" { target { c++20 && c++23_down } } }
+              // { dg-error "arithmetic between enumeration type .E1. and 
floating-point type .double." "" { target c++26 } .-1 }
+  r += d + e1; // { dg-warning "arithmetic between floating-point type 
.double. and enumeration type .E1." "" { target { c++20 && c++23_down } } }
+              // { dg-error "arithmetic between floating-point type .double. 
and enumeration type .E1." "" { target c++26 } .-1 }
+  r += e1 * d; // { dg-warning "arithmetic between enumeration type .E1. and 
floating-point type .double." "" { target { c++20 && c++23_down } } }
+              // { dg-error "arithmetic between enumeration type .E1. and 
floating-point type .double." "" { target c++26 } .-1 }
+  r += d * e1; // { dg-warning "arithmetic between floating-point type 
.double. and enumeration type .E1." "" { target { c++20 && c++23_down } } }
+              // { dg-error "arithmetic between floating-point type .double. 
and enumeration type .E1." "" { target c++26 } .-1 }
+  r += u1 * d; // { dg-warning "arithmetic between enumeration type" "" { 
target { c++20 && c++23_down } } }
+              // { dg-error "arithmetic between enumeration type" "" { target 
c++26 } .-1 }
+  r += d * u1; // { dg-warning "arithmetic between floating-point type" "" { 
target { c++20 && c++23_down } } }
+              // { dg-error "arithmetic between floating-point type" "" { 
target c++26 } .-1 }
+
+  r += e1 < d;  // { dg-warning "comparison of enumeration type .E1. with 
floating-point type .double." "" { target { c++20 && c++23_down } } }
+               // { dg-error "comparison of enumeration type .E1. with 
floating-point type .double." "" { target c++26 } .-1 }
+  r += d < e1;  // { dg-warning "comparison of floating-point type .double. 
with enumeration type .E1." "" { target { c++20 && c++23_down } } }
+               // { dg-error "comparison of floating-point type .double. with 
enumeration type .E1." "" { target c++26 } .-1 }
+  r += d == e1; // { dg-warning "comparison of floating-point type .double. 
with enumeration type .E1." "" { target { c++20 && c++23_down } } }
+               // { dg-error "comparison of floating-point type .double. with 
enumeration type .E1." "" { target c++26 } .-1 }
+  r += e1 == d; // { dg-warning "comparison of enumeration type .E1. with 
floating-point type .double." "" { target { c++20 && c++23_down } } }
+               // { dg-error "comparison of enumeration type .E1. with 
floating-point type .double." "" { target c++26 } .-1 }
+  r += u1 == d; // { dg-warning "comparison of enumeration type" "" { target { 
c++20 && c++23_down } } }
+               // { dg-error "comparison of enumeration type" "" { target 
c++26 } .-1 }
+  r += d == u1; // { dg-warning "comparison of floating-point type" "" { 
target { c++20 && c++23_down } } }
+               // { dg-error "comparison of floating-point type" "" { target 
c++26 } .-1 }
+
+  r += b ? e1 : d; // { dg-warning "conditional expression between enumeration 
type .E1. and floating-point type .double." "" { target { c++20 && c++23_down } 
} }
+                  // { dg-error "conditional expression between enumeration 
type .E1. and floating-point type .double." "" { target c++26 } .-1 }
+  r += b ? d : e1; // { dg-warning "conditional expression between 
floating-point type .double. and enumeration type .E1." "" { target { c++20 && 
c++23_down } } }
+                  // { dg-error "conditional expression between floating-point 
type .double. and enumeration type .E1." "" { target c++26 } .-1 }
+  r += b ? d : u1; // { dg-warning "conditional expression between" "" { 
target { c++20 && c++23_down } } }
+                  // { dg-error "conditional expression between" "" { target 
c++26 } .-1 }
+  r += b ? u1 : d; // { dg-warning "conditional expression between" "" { 
target { c++20 && c++23_down } } }
+                  // { dg-error "conditional expression between" "" { target 
c++26 } .-1 }
 
-  d += e1; // { dg-warning "arithmetic between floating-point type .double. 
and enumeration type .E1." "" { target c++20 } }
+  d += e1; // { dg-warning "arithmetic between floating-point type .double. 
and enumeration type .E1." "" { target { c++20 && c++23_down } } }
+          // { dg-error "arithmetic between floating-point type .double. and 
enumeration type .E1." "" { target c++26 } .-1 }
   d = e1;
 
   return r;
--- gcc/testsuite/g++.dg/diagnostic/enum3.C.jj  2021-06-09 10:20:08.971342523 
+0200
+++ gcc/testsuite/g++.dg/diagnostic/enum3.C     2023-11-13 12:28:19.035521575 
+0100
@@ -5,5 +5,6 @@ enum e1 { e1val };
 enum e2 { e3val };
 
 int main( int, char * [] ) {
-   if ( e1val == e3val ) return 1; // { dg-warning -Wenum-compare }
+   if ( e1val == e3val ) return 1; // { dg-warning "comparison between 'enum 
e1' and 'enum e2'" "" { target c++23_down } }
+                                  // { dg-error "comparison between 'enum e1' 
and 'enum e2'" "" { target c++26 } .-1 }
 }
--- gcc/testsuite/g++.dg/parse/attr3.C.jj       2020-10-29 10:10:11.569397839 
+0100
+++ gcc/testsuite/g++.dg/parse/attr3.C  2023-11-13 12:29:13.241759469 +0100
@@ -10,5 +10,6 @@ int main () {
     S::F y;    // { dg-warning "'F' is deprecated" }
     y = S::f;
 
-    return x + y; // { dg-warning "arithmetic between different enumeration 
types" "" { target c++20 } }
+    return x + y; // { dg-warning "arithmetic between different enumeration 
types" "" { target { c++20 && c++23_down } } }
+                 // { dg-error "arithmetic between different enumeration 
types" "" { target c++26 } .-1 }
 }
--- gcc/testsuite/g++.dg/cpp0x/linkage2.C.jj    2020-10-29 10:10:11.560397940 
+0100
+++ gcc/testsuite/g++.dg/cpp0x/linkage2.C       2023-11-13 12:30:26.712726512 
+0100
@@ -29,5 +29,6 @@ void f() {
   ba.g(a);              // OK
   ba.h(a);              // error, B<T>::h never defined
   i(ba, a);             // OK
-  e1+e2+e3; // { dg-warning "arithmetic between different enumeration types" 
"" { target c++20 } }
+  e1+e2+e3; // { dg-warning "arithmetic between different enumeration types" 
"" { target { c++20 && c++23_down } } }
+           // { dg-error "arithmetic between different enumeration types" "" { 
target c++26 } .-1 }
 }

        Jakub

Reply via email to