diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-11-15 08:27:07 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-11-15 08:27:07 +0100 |
commit | 5f580e24088b85be95aeae0ceb2edff0cea861dd (patch) | |
tree | 4f79f88352efb01a9f67e0649f4bae325b5fd9bd /gcc/cp | |
parent | 081fddbbcf9790229f4fe885781548ba1f6a365a (diff) | |
download | gcc-5f580e24088b85be95aeae0ceb2edff0cea861dd.zip gcc-5f580e24088b85be95aeae0ceb2edff0cea861dd.tar.gz gcc-5f580e24088b85be95aeae0ceb2edff0cea861dd.tar.bz2 |
c++: Implement C++26 P2864R2 - Remove Deprecated Arithmetic Conversion on Enumerations From C++26
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. Additionally, for
cxx_dialect >= cxx26 && (complain & tf_warning_or_error) == 0 it causes for
these newly ill-formed constructs error_mark_node to be silently returned.
2023-11-15 Jakub Jelinek <jakub@redhat.com>
gcc/cp/
* typeck.cc: Implement C++26 P2864R2 - Remove Deprecated Arithmetic
Conversion on Enumerations From C++26.
(do_warn_enum_conversions): Return bool rather than void, add COMPLAIN
argument. Use pedwarn rather than warning_at for C++26 and remove
" is deprecated" part of the diagnostics in that case. For SFINAE
in C++26 return true on newly erroneous cases.
(cp_build_binary_op): For C++26 call do_warn_enum_conversions
unconditionally, pass complain argument to it and if it returns true,
return error_mark_node.
* 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. For SFINAE in
C++26 return error_mark_node on newly erroneous cases.
(build_new_op): Use emit_diagnostic with cxx_dialect >= cxx26
? DK_PEDWARN : DK_WARNING and complain & tf_warning_or_error check
for C++26. For SFINAE in C++26 return error_mark_node on newly
erroneous cases.
gcc/testsuite/
* g++.dg/cpp26/enum-conv1.C: New test.
* 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.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/call.cc | 48 | ||||
-rw-r--r-- | gcc/cp/typeck.cc | 89 |
2 files changed, 98 insertions, 39 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 86feff5..81b104f 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -6163,19 +6163,36 @@ build_conditional_expr (const op_location_t &loc, == 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 (cxx_dialect >= cxx26) + return error_mark_node; } - else if ((complain & tf_warning) - && warn_deprecated_enum_float_conv + else if ((((complain & (cxx_dialect >= cxx26 + ? tf_warning_or_error : tf_warning)) + && warn_deprecated_enum_float_conv) + || (cxx_dialect >= cxx26 + && (complain & tf_warning_or_error) == 0)) && ((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 && (complain & tf_warning_or_error) == 0) + return error_mark_node; + 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", @@ -7258,11 +7275,18 @@ build_new_op (const op_location_t &loc, enum tree_code code, int flags, if (TREE_CODE (arg1_type) == ENUMERAL_TYPE && 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); + != TYPE_MAIN_VARIANT (arg2_type))) + { + if (cxx_dialect >= cxx26 + && (complain & tf_warning_or_error) == 0) + result = error_mark_node; + else if (cxx_dialect >= cxx26 || (complain & 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; diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 49afbd8..e995fb6 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -4940,16 +4940,25 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain) type, this behavior is deprecated ([depr.arith.conv.enum]). CODE is the code of the binary operation, TYPE0 and TYPE1 are the types of the operands, and LOC is the location for the whole binary expression. + For C++26 this is ill-formed rather than deprecated. + Return true for SFINAE errors. TODO: Consider combining this with -Wenum-compare in build_new_op_1. */ -static void +static bool do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, - tree type1) + tree type1, tsubst_flags_t complain) { if (TREE_CODE (type0) == ENUMERAL_TYPE && TREE_CODE (type1) == ENUMERAL_TYPE && TYPE_MAIN_VARIANT (type0) != TYPE_MAIN_VARIANT (type1)) { + if (cxx_dialect >= cxx26) + { + if ((complain & tf_warning_or_error) == 0) + return true; + } + else if ((complain & tf_warning) == 0) + return false; /* In C++20, -Wdeprecated-enum-enum-conversion is on by default. Otherwise, warn if -Wenum-conversion is on. */ enum opt_code opt; @@ -4958,7 +4967,7 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, else if (warn_enum_conversion) opt = OPT_Wenum_conversion; else - return; + return false; switch (code) { @@ -4969,21 +4978,29 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, case EQ_EXPR: case NE_EXPR: /* Comparisons are handled by -Wenum-compare. */ - return; + return false; case SPACESHIP_EXPR: /* This is invalid, don't warn. */ - return; + return false; 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); - return; + 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 false; default: - warning_at (loc, opt, "arithmetic between different enumeration " - "types %qT and %qT is deprecated", type0, type1); - return; + 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 false; } } else if ((TREE_CODE (type0) == ENUMERAL_TYPE @@ -4991,6 +5008,13 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, || (SCALAR_FLOAT_TYPE_P (type0) && TREE_CODE (type1) == ENUMERAL_TYPE)) { + if (cxx_dialect >= cxx26) + { + if ((complain & tf_warning_or_error) == 0) + return true; + } + else if ((complain & tf_warning) == 0) + return false; const bool enum_first_p = TREE_CODE (type0) == ENUMERAL_TYPE; /* In C++20, -Wdeprecated-enum-float-conversion is on by default. Otherwise, warn if -Wenum-conversion is on. */ @@ -5000,7 +5024,7 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, else if (warn_enum_conversion) opt = OPT_Wenum_conversion; else - return; + return false; switch (code) { @@ -5010,7 +5034,13 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, 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); @@ -5018,12 +5048,18 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, warning_at (loc, opt, "comparison of floating-point type %qT " "with enumeration type %qT is deprecated", type0, type1); - return; + return false; case SPACESHIP_EXPR: /* This is invalid, don't warn. */ - return; + return false; 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); @@ -5031,9 +5067,10 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, warning_at (loc, opt, "arithmetic between floating-point type %qT " "and enumeration type %qT is deprecated", type0, type1); - return; + return false; } } + return false; } /* Build a binary-operation expression without default conversions. @@ -6163,15 +6200,13 @@ cp_build_binary_op (const op_location_t &location, 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 (do_warn_enum_conversions (location, code, TREE_TYPE (orig_op0), + TREE_TYPE (orig_op1), complain)) + return error_mark_node; } if (may_need_excess_precision && (orig_type0 != type0 || orig_type1 != type1) |