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