aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-11-15 08:27:07 +0100
committerJakub Jelinek <jakub@redhat.com>2023-11-15 08:27:07 +0100
commit5f580e24088b85be95aeae0ceb2edff0cea861dd (patch)
tree4f79f88352efb01a9f67e0649f4bae325b5fd9bd /gcc/cp
parent081fddbbcf9790229f4fe885781548ba1f6a365a (diff)
downloadgcc-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.cc48
-rw-r--r--gcc/cp/typeck.cc89
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)