c++: Implement C++20 -Wdeprecated-array-compare [PR97573]
Commit Message
This patch addresses one of my leftovers from GCC 11. C++20 introduced
[depr.array.comp]:
"Equality and relational comparisons between two operands of array type are
deprecated."
so this patch adds -Wdeprecated-array-compare (enabled by default in C++20).
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
PR c++/97573
gcc/c-family/ChangeLog:
* c-opts.c (c_common_post_options): In C++20, turn on
-Wdeprecated-array-compare.
* c.opt (Wdeprecated-array-compare): New option.
gcc/cp/ChangeLog:
* typeck.c (do_warn_deprecated_array_compare): New.
(cp_build_binary_op): Call it for equality and relational comparisons.
gcc/ChangeLog:
* doc/invoke.texi: Document -Wdeprecated-array-compare.
gcc/testsuite/ChangeLog:
* g++.dg/tree-ssa/pr15791-1.C: Add dg-warning.
* g++.dg/cpp2a/array-comp1.C: New test.
* g++.dg/cpp2a/array-comp2.C: New test.
* g++.dg/cpp2a/array-comp3.C: New test.
---
gcc/c-family/c-opts.c | 5 ++++
gcc/c-family/c.opt | 4 +++
gcc/cp/typeck.c | 28 +++++++++++++++++++
gcc/doc/invoke.texi | 19 ++++++++++++-
gcc/testsuite/g++.dg/cpp2a/array-comp1.C | 34 +++++++++++++++++++++++
gcc/testsuite/g++.dg/cpp2a/array-comp2.C | 31 +++++++++++++++++++++
gcc/testsuite/g++.dg/cpp2a/array-comp3.C | 29 +++++++++++++++++++
gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C | 2 +-
8 files changed, 150 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp1.C
create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp2.C
create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp3.C
base-commit: ef37ddf477ac4b21ec4d1be9260cfd3b431fd4a9
Comments
On 9/30/21 10:50, Marek Polacek wrote:
> This patch addresses one of my leftovers from GCC 11. C++20 introduced
> [depr.array.comp]:
> "Equality and relational comparisons between two operands of array type are
> deprecated."
> so this patch adds -Wdeprecated-array-compare (enabled by default in C++20).
Why not enable it by default in all modes? It was always pretty dubious
code.
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>
> PR c++/97573
>
> gcc/c-family/ChangeLog:
>
> * c-opts.c (c_common_post_options): In C++20, turn on
> -Wdeprecated-array-compare.
> * c.opt (Wdeprecated-array-compare): New option.
>
> gcc/cp/ChangeLog:
>
> * typeck.c (do_warn_deprecated_array_compare): New.
> (cp_build_binary_op): Call it for equality and relational comparisons.
>
> gcc/ChangeLog:
>
> * doc/invoke.texi: Document -Wdeprecated-array-compare.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/tree-ssa/pr15791-1.C: Add dg-warning.
> * g++.dg/cpp2a/array-comp1.C: New test.
> * g++.dg/cpp2a/array-comp2.C: New test.
> * g++.dg/cpp2a/array-comp3.C: New test.
> ---
> gcc/c-family/c-opts.c | 5 ++++
> gcc/c-family/c.opt | 4 +++
> gcc/cp/typeck.c | 28 +++++++++++++++++++
> gcc/doc/invoke.texi | 19 ++++++++++++-
> gcc/testsuite/g++.dg/cpp2a/array-comp1.C | 34 +++++++++++++++++++++++
> gcc/testsuite/g++.dg/cpp2a/array-comp2.C | 31 +++++++++++++++++++++
> gcc/testsuite/g++.dg/cpp2a/array-comp3.C | 29 +++++++++++++++++++
> gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C | 2 +-
> 8 files changed, 150 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp3.C
>
> diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
> index 3eaab5e1530..00b52cc5e12 100644
> --- a/gcc/c-family/c-opts.c
> +++ b/gcc/c-family/c-opts.c
> @@ -962,6 +962,11 @@ c_common_post_options (const char **pfilename)
> warn_deprecated_enum_float_conv,
> cxx_dialect >= cxx20 && warn_deprecated);
>
> + /* -Wdeprecated-array-compare is enabled by default in C++20. */
> + SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> + warn_deprecated_array_compare,
> + cxx_dialect >= cxx20 && warn_deprecated);
> +
> /* Declone C++ 'structors if -Os. */
> if (flag_declone_ctor_dtor == -1)
> flag_declone_ctor_dtor = optimize_size;
> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index 9c151d19870..a4f0ea68594 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -540,6 +540,10 @@ Wdeprecated
> C C++ ObjC ObjC++ CPP(cpp_warn_deprecated) CppReason(CPP_W_DEPRECATED)
> ; Documented in common.opt
>
> +Wdeprecated-array-compare
> +C++ ObjC++ Var(warn_deprecated_array_compare) Warning
> +Warn about deprecated comparisons between two operands of array type.
> +
> Wdeprecated-copy
> C++ ObjC++ Var(warn_deprecated_copy) Warning LangEnabledBy(C++ ObjC++, Wextra)
> Mark implicitly-declared copy operations as deprecated if the class has a
> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> index a2398dbe660..1e3a41104d6 100644
> --- a/gcc/cp/typeck.c
> +++ b/gcc/cp/typeck.c
> @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
> #include "attribs.h"
> #include "asan.h"
> #include "gimplify.h"
> +#include "tree-pretty-print.h"
>
> static tree cp_build_addr_expr_strict (tree, tsubst_flags_t);
> static tree cp_build_function_call (tree, tree, tsubst_flags_t);
> @@ -4725,6 +4726,21 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
> }
> }
>
> +/* Warn about C++20 [depr.array.comp] array comparisons: "Equality
> + and relational comparisons between two operands of array type are
> + deprecated." */
> +
> +static inline void
> +do_warn_deprecated_array_compare (location_t location, tree_code code,
> + tree op0, tree op1)
> +{
> + if (warning_at (location, OPT_Wdeprecated_array_compare,
> + "comparison between two arrays is deprecated"))
> + inform (location, "use unary %<+%> which decays operands to pointers "
> + "or %<&%D[0] %s &%D[0]%> to compare the addresses",
> + op0, op_symbol_code (code), op1);
> +}
> +
> /* Build a binary-operation expression without default conversions.
> CODE is the kind of expression to build.
> LOCATION is the location_t of the operator in the source code.
> @@ -5289,6 +5305,11 @@ cp_build_binary_op (const op_location_t &location,
> warning_at (location, OPT_Waddress,
> "comparison with string literal results in "
> "unspecified behavior");
> + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
> + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE)
> + do_warn_deprecated_array_compare (location, code,
> + stripped_orig_op0,
> + stripped_orig_op1);
> }
>
> build_type = boolean_type_node;
> @@ -5559,6 +5580,13 @@ cp_build_binary_op (const op_location_t &location,
> "comparison with string literal results "
> "in unspecified behavior");
> }
> + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
> + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE
> + && code != SPACESHIP_EXPR
What happens if you try to compare them with <=>?
> + && (complain & tf_warning))
> + do_warn_deprecated_array_compare
> + (location, code, tree_strip_any_location_wrapper (orig_op0),
> + tree_strip_any_location_wrapper (orig_op1));
>
> if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1))
> {
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 5b016166972..a6c6a737639 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -249,7 +249,8 @@ in the following sections.
> -Wcomma-subscript -Wconditionally-supported @gol
> -Wno-conversion-null -Wctad-maybe-unsupported @gol
> -Wctor-dtor-privacy -Wno-delete-incomplete @gol
> --Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
> +-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare @gol
> +-Wdeprecated-copy -Wdeprecated-copy-dtor @gol
> -Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion @gol
> -Weffc++ -Wno-exceptions -Wextra-semi -Wno-inaccessible-base @gol
> -Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
> @@ -3521,6 +3522,22 @@ warning is enabled by @option{-Wextra}. With
> @option{-Wdeprecated-copy-dtor}, also deprecate if the class has a
> user-provided destructor.
>
> +@item -Wno-deprecated-array-compare @r{(C++ and Objective-C++ only)}
> +@opindex Wdeprecated-array-compare
> +@opindex Wno-deprecated-array-compare
> +Disable the warning about equality and relational comparisons between two
> +operands of array type. This comparison was deprecated in C++20. For
> +example:
> +
> +@smallexample
> +int arr1[5];
> +int arr2[5];
> +bool same = arr1 == arr2;
> +@end smallexample
> +
> +@option{-Wdeprecated-array-compare} is enabled by default with
> +@option{-std=c++20}.
> +
> @item -Wno-deprecated-enum-enum-conversion @r{(C++ and Objective-C++ only)}
> @opindex Wdeprecated-enum-enum-conversion
> @opindex Wno-deprecated-enum-enum-conversion
> diff --git a/gcc/testsuite/g++.dg/cpp2a/array-comp1.C b/gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> new file mode 100644
> index 00000000000..140d4d3c1dd
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> @@ -0,0 +1,34 @@
> +// PR c++/97573 - C++20 [depr.array.comp]
> +// { dg-do compile }
> +// No special options. In C++20 (only), we should get the deprecated warnings
> +// by default.
> +
> +int arr1[5];
> +int arr2[5];
> +int arr3[2][2];
> +int arr4[2][2];
> +
> +bool s1 = arr1 == arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s2 = arr1 != arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s3 = arr1 > arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s4 = arr1 >= arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s5 = arr1 < arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s6 = arr1 <= arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool ok1 = +arr1 == +arr2;
> +bool ok2 = +arr1 != +arr2;
> +bool ok3 = +arr1 > +arr2;
> +bool ok4 = +arr1 >= +arr2;
> +bool ok5 = +arr1 < +arr2;
> +bool ok6 = +arr1 <= +arr2;
> +bool ok7 = &arr1[0] == &arr2[0];
> +bool ok8 = &arr1[0] != &arr2[0];
> +bool ok9 = &arr1[0] > &arr2[0];
> +bool ok10 = &arr1[0] >= &arr2[0];
> +bool ok11 = &arr1[0] < &arr2[0];
> +bool ok12 = &arr1[0] <= &arr2[0];
> +
> +bool s7 = arr3 == arr4; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +
> +#if __cplusplus > 201703L
> +auto cmp = arr1 <=> arr2; // { dg-error "invalid operands" "" { target c++20 } }
> +#endif
> diff --git a/gcc/testsuite/g++.dg/cpp2a/array-comp2.C b/gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> new file mode 100644
> index 00000000000..b8409abb50a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> @@ -0,0 +1,31 @@
> +// PR c++/97573 - C++20 [depr.array.comp]
> +// { dg-do compile { target c++20 } }
> +// { dg-options "-Wno-deprecated" }
> +
> +int arr1[5];
> +int arr2[5];
> +int arr3[2][2];
> +int arr4[2][2];
> +
> +bool s1 = arr1 == arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s2 = arr1 != arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s3 = arr1 > arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s4 = arr1 >= arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s5 = arr1 < arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s6 = arr1 <= arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool ok1 = +arr1 == +arr2;
> +bool ok2 = +arr1 != +arr2;
> +bool ok3 = +arr1 > +arr2;
> +bool ok4 = +arr1 >= +arr2;
> +bool ok5 = +arr1 < +arr2;
> +bool ok6 = +arr1 <= +arr2;
> +bool ok7 = &arr1[0] == &arr2[0];
> +bool ok8 = &arr1[0] != &arr2[0];
> +bool ok9 = &arr1[0] > &arr2[0];
> +bool ok10 = &arr1[0] >= &arr2[0];
> +bool ok11 = &arr1[0] < &arr2[0];
> +bool ok12 = &arr1[0] <= &arr2[0];
> +
> +bool s7 = arr3 == arr4; // { dg-bogus "comparison between two arrays is deprecated" }
> +
> +auto cmp = arr1 <=> arr2; // { dg-error "invalid operands" }
> diff --git a/gcc/testsuite/g++.dg/cpp2a/array-comp3.C b/gcc/testsuite/g++.dg/cpp2a/array-comp3.C
> new file mode 100644
> index 00000000000..70a6b4cbfea
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/array-comp3.C
> @@ -0,0 +1,29 @@
> +// PR c++/97573 - C++20 [depr.array.comp]
> +// { dg-do compile { target { c++17_down } } }
> +// { dg-options "-Wdeprecated-array-compare" }
> +
> +int arr1[5];
> +int arr2[5];
> +int arr3[2][2];
> +int arr4[2][2];
> +
> +bool s1 = arr1 == arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s2 = arr1 != arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s3 = arr1 > arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s4 = arr1 >= arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s5 = arr1 < arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s6 = arr1 <= arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool ok1 = +arr1 == +arr2;
> +bool ok2 = +arr1 != +arr2;
> +bool ok3 = +arr1 > +arr2;
> +bool ok4 = +arr1 >= +arr2;
> +bool ok5 = +arr1 < +arr2;
> +bool ok6 = +arr1 <= +arr2;
> +bool ok7 = &arr1[0] == &arr2[0];
> +bool ok8 = &arr1[0] != &arr2[0];
> +bool ok9 = &arr1[0] > &arr2[0];
> +bool ok10 = &arr1[0] >= &arr2[0];
> +bool ok11 = &arr1[0] < &arr2[0];
> +bool ok12 = &arr1[0] <= &arr2[0];
> +
> +bool s7 = arr3 == arr4; // { dg-warning "comparison between two arrays is deprecated" }
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C b/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
> index 68f14adad00..5fc6a8ae5b3 100644
> --- a/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
> +++ b/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
> @@ -12,7 +12,7 @@ int main ()
> link_error ();
> if (b == &b[2])
> link_error ();
> - if (b != b)
> + if (b != b) // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> link_error ();
> if (&x.b[1] == &x.b[0])
> link_error ();
>
> base-commit: ef37ddf477ac4b21ec4d1be9260cfd3b431fd4a9
>
On Thu, Sep 30, 2021 at 03:34:24PM -0400, Jason Merrill wrote:
> On 9/30/21 10:50, Marek Polacek wrote:
> > This patch addresses one of my leftovers from GCC 11. C++20 introduced
> > [depr.array.comp]:
> > "Equality and relational comparisons between two operands of array type are
> > deprecated."
> > so this patch adds -Wdeprecated-array-compare (enabled by default in C++20).
>
> Why not enable it by default in all modes? It was always pretty dubious
> code.
Sure, it could be done, but it kind of complicates things: we'd probably
need a different option and a different message because it seems incorrect
to say "deprecated" in e.g. C++17 when this was only deprecated in C++20.
I'd rather not add another option; if it stays -Wdeprecated-array-compare
but -Wno-deprecated doesn't turn it off that also seems weird.
I could rename it to -Warray-compare, enable by -Wall, and only
append "is deprecated" to the warning message in C++20. Does that seem
better?
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> >
> > PR c++/97573
> >
> > gcc/c-family/ChangeLog:
> >
> > * c-opts.c (c_common_post_options): In C++20, turn on
> > -Wdeprecated-array-compare.
> > * c.opt (Wdeprecated-array-compare): New option.
> >
> > gcc/cp/ChangeLog:
> >
> > * typeck.c (do_warn_deprecated_array_compare): New.
> > (cp_build_binary_op): Call it for equality and relational comparisons.
> >
> > gcc/ChangeLog:
> >
> > * doc/invoke.texi: Document -Wdeprecated-array-compare.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/tree-ssa/pr15791-1.C: Add dg-warning.
> > * g++.dg/cpp2a/array-comp1.C: New test.
> > * g++.dg/cpp2a/array-comp2.C: New test.
> > * g++.dg/cpp2a/array-comp3.C: New test.
> > ---
> > gcc/c-family/c-opts.c | 5 ++++
> > gcc/c-family/c.opt | 4 +++
> > gcc/cp/typeck.c | 28 +++++++++++++++++++
> > gcc/doc/invoke.texi | 19 ++++++++++++-
> > gcc/testsuite/g++.dg/cpp2a/array-comp1.C | 34 +++++++++++++++++++++++
> > gcc/testsuite/g++.dg/cpp2a/array-comp2.C | 31 +++++++++++++++++++++
> > gcc/testsuite/g++.dg/cpp2a/array-comp3.C | 29 +++++++++++++++++++
> > gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C | 2 +-
> > 8 files changed, 150 insertions(+), 2 deletions(-)
> > create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> > create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> > create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp3.C
> >
> > diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
> > index 3eaab5e1530..00b52cc5e12 100644
> > --- a/gcc/c-family/c-opts.c
> > +++ b/gcc/c-family/c-opts.c
> > @@ -962,6 +962,11 @@ c_common_post_options (const char **pfilename)
> > warn_deprecated_enum_float_conv,
> > cxx_dialect >= cxx20 && warn_deprecated);
> > + /* -Wdeprecated-array-compare is enabled by default in C++20. */
> > + SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> > + warn_deprecated_array_compare,
> > + cxx_dialect >= cxx20 && warn_deprecated);
> > +
> > /* Declone C++ 'structors if -Os. */
> > if (flag_declone_ctor_dtor == -1)
> > flag_declone_ctor_dtor = optimize_size;
> > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> > index 9c151d19870..a4f0ea68594 100644
> > --- a/gcc/c-family/c.opt
> > +++ b/gcc/c-family/c.opt
> > @@ -540,6 +540,10 @@ Wdeprecated
> > C C++ ObjC ObjC++ CPP(cpp_warn_deprecated) CppReason(CPP_W_DEPRECATED)
> > ; Documented in common.opt
> > +Wdeprecated-array-compare
> > +C++ ObjC++ Var(warn_deprecated_array_compare) Warning
> > +Warn about deprecated comparisons between two operands of array type.
> > +
> > Wdeprecated-copy
> > C++ ObjC++ Var(warn_deprecated_copy) Warning LangEnabledBy(C++ ObjC++, Wextra)
> > Mark implicitly-declared copy operations as deprecated if the class has a
> > diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> > index a2398dbe660..1e3a41104d6 100644
> > --- a/gcc/cp/typeck.c
> > +++ b/gcc/cp/typeck.c
> > @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
> > #include "attribs.h"
> > #include "asan.h"
> > #include "gimplify.h"
> > +#include "tree-pretty-print.h"
> > static tree cp_build_addr_expr_strict (tree, tsubst_flags_t);
> > static tree cp_build_function_call (tree, tree, tsubst_flags_t);
> > @@ -4725,6 +4726,21 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
> > }
> > }
> > +/* Warn about C++20 [depr.array.comp] array comparisons: "Equality
> > + and relational comparisons between two operands of array type are
> > + deprecated." */
> > +
> > +static inline void
> > +do_warn_deprecated_array_compare (location_t location, tree_code code,
> > + tree op0, tree op1)
> > +{
> > + if (warning_at (location, OPT_Wdeprecated_array_compare,
> > + "comparison between two arrays is deprecated"))
> > + inform (location, "use unary %<+%> which decays operands to pointers "
> > + "or %<&%D[0] %s &%D[0]%> to compare the addresses",
> > + op0, op_symbol_code (code), op1);
> > +}
> > +
> > /* Build a binary-operation expression without default conversions.
> > CODE is the kind of expression to build.
> > LOCATION is the location_t of the operator in the source code.
> > @@ -5289,6 +5305,11 @@ cp_build_binary_op (const op_location_t &location,
> > warning_at (location, OPT_Waddress,
> > "comparison with string literal results in "
> > "unspecified behavior");
> > + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
> > + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE)
> > + do_warn_deprecated_array_compare (location, code,
> > + stripped_orig_op0,
> > + stripped_orig_op1);
> > }
> > build_type = boolean_type_node;
> > @@ -5559,6 +5580,13 @@ cp_build_binary_op (const op_location_t &location,
> > "comparison with string literal results "
> > "in unspecified behavior");
> > }
> > + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
> > + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE
> > + && code != SPACESHIP_EXPR
>
> What happens if you try to compare them with <=>?
That's always an error so printing a warning is redundant.
Marek
On 9/30/21 17:56, Marek Polacek wrote:
> On Thu, Sep 30, 2021 at 03:34:24PM -0400, Jason Merrill wrote:
>> On 9/30/21 10:50, Marek Polacek wrote:
>>> This patch addresses one of my leftovers from GCC 11. C++20 introduced
>>> [depr.array.comp]:
>>> "Equality and relational comparisons between two operands of array type are
>>> deprecated."
>>> so this patch adds -Wdeprecated-array-compare (enabled by default in C++20).
>>
>> Why not enable it by default in all modes? It was always pretty dubious
>> code.
>
> Sure, it could be done, but it kind of complicates things: we'd probably
> need a different option and a different message because it seems incorrect
> to say "deprecated" in e.g. C++17 when this was only deprecated in C++20.
The warning could say "deprecated in C++20", which is always true?
> I'd rather not add another option; if it stays -Wdeprecated-array-compare
> but -Wno-deprecated doesn't turn it off that also seems weird.
>
> I could rename it to -Warray-compare, enable by -Wall, and only
> append "is deprecated" to the warning message in C++20. Does that seem
> better?
That sounds fine too.
>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>>>
>>> PR c++/97573
>>>
>>> gcc/c-family/ChangeLog:
>>>
>>> * c-opts.c (c_common_post_options): In C++20, turn on
>>> -Wdeprecated-array-compare.
>>> * c.opt (Wdeprecated-array-compare): New option.
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> * typeck.c (do_warn_deprecated_array_compare): New.
>>> (cp_build_binary_op): Call it for equality and relational comparisons.
>>>
>>> gcc/ChangeLog:
>>>
>>> * doc/invoke.texi: Document -Wdeprecated-array-compare.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> * g++.dg/tree-ssa/pr15791-1.C: Add dg-warning.
>>> * g++.dg/cpp2a/array-comp1.C: New test.
>>> * g++.dg/cpp2a/array-comp2.C: New test.
>>> * g++.dg/cpp2a/array-comp3.C: New test.
>>> ---
>>> gcc/c-family/c-opts.c | 5 ++++
>>> gcc/c-family/c.opt | 4 +++
>>> gcc/cp/typeck.c | 28 +++++++++++++++++++
>>> gcc/doc/invoke.texi | 19 ++++++++++++-
>>> gcc/testsuite/g++.dg/cpp2a/array-comp1.C | 34 +++++++++++++++++++++++
>>> gcc/testsuite/g++.dg/cpp2a/array-comp2.C | 31 +++++++++++++++++++++
>>> gcc/testsuite/g++.dg/cpp2a/array-comp3.C | 29 +++++++++++++++++++
>>> gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C | 2 +-
>>> 8 files changed, 150 insertions(+), 2 deletions(-)
>>> create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp1.C
>>> create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp2.C
>>> create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp3.C
>>>
>>> diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
>>> index 3eaab5e1530..00b52cc5e12 100644
>>> --- a/gcc/c-family/c-opts.c
>>> +++ b/gcc/c-family/c-opts.c
>>> @@ -962,6 +962,11 @@ c_common_post_options (const char **pfilename)
>>> warn_deprecated_enum_float_conv,
>>> cxx_dialect >= cxx20 && warn_deprecated);
>>> + /* -Wdeprecated-array-compare is enabled by default in C++20. */
>>> + SET_OPTION_IF_UNSET (&global_options, &global_options_set,
>>> + warn_deprecated_array_compare,
>>> + cxx_dialect >= cxx20 && warn_deprecated);
>>> +
>>> /* Declone C++ 'structors if -Os. */
>>> if (flag_declone_ctor_dtor == -1)
>>> flag_declone_ctor_dtor = optimize_size;
>>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>>> index 9c151d19870..a4f0ea68594 100644
>>> --- a/gcc/c-family/c.opt
>>> +++ b/gcc/c-family/c.opt
>>> @@ -540,6 +540,10 @@ Wdeprecated
>>> C C++ ObjC ObjC++ CPP(cpp_warn_deprecated) CppReason(CPP_W_DEPRECATED)
>>> ; Documented in common.opt
>>> +Wdeprecated-array-compare
>>> +C++ ObjC++ Var(warn_deprecated_array_compare) Warning
>>> +Warn about deprecated comparisons between two operands of array type.
>>> +
>>> Wdeprecated-copy
>>> C++ ObjC++ Var(warn_deprecated_copy) Warning LangEnabledBy(C++ ObjC++, Wextra)
>>> Mark implicitly-declared copy operations as deprecated if the class has a
>>> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
>>> index a2398dbe660..1e3a41104d6 100644
>>> --- a/gcc/cp/typeck.c
>>> +++ b/gcc/cp/typeck.c
>>> @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
>>> #include "attribs.h"
>>> #include "asan.h"
>>> #include "gimplify.h"
>>> +#include "tree-pretty-print.h"
>>> static tree cp_build_addr_expr_strict (tree, tsubst_flags_t);
>>> static tree cp_build_function_call (tree, tree, tsubst_flags_t);
>>> @@ -4725,6 +4726,21 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
>>> }
>>> }
>>> +/* Warn about C++20 [depr.array.comp] array comparisons: "Equality
>>> + and relational comparisons between two operands of array type are
>>> + deprecated." */
>>> +
>>> +static inline void
>>> +do_warn_deprecated_array_compare (location_t location, tree_code code,
>>> + tree op0, tree op1)
>>> +{
>>> + if (warning_at (location, OPT_Wdeprecated_array_compare,
>>> + "comparison between two arrays is deprecated"))
>>> + inform (location, "use unary %<+%> which decays operands to pointers "
>>> + "or %<&%D[0] %s &%D[0]%> to compare the addresses",
>>> + op0, op_symbol_code (code), op1);
>>> +}
>>> +
>>> /* Build a binary-operation expression without default conversions.
>>> CODE is the kind of expression to build.
>>> LOCATION is the location_t of the operator in the source code.
>>> @@ -5289,6 +5305,11 @@ cp_build_binary_op (const op_location_t &location,
>>> warning_at (location, OPT_Waddress,
>>> "comparison with string literal results in "
>>> "unspecified behavior");
>>> + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
>>> + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE)
>>> + do_warn_deprecated_array_compare (location, code,
>>> + stripped_orig_op0,
>>> + stripped_orig_op1);
>>> }
>>> build_type = boolean_type_node;
>>> @@ -5559,6 +5580,13 @@ cp_build_binary_op (const op_location_t &location,
>>> "comparison with string literal results "
>>> "in unspecified behavior");
>>> }
>>> + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
>>> + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE
>>> + && code != SPACESHIP_EXPR
>>
>> What happens if you try to compare them with <=>?
>
> That's always an error so printing a warning is redundant.
>
> Marek
>
On 9/30/21 8:50 AM, Marek Polacek via Gcc-patches wrote:
> This patch addresses one of my leftovers from GCC 11. C++20 introduced
> [depr.array.comp]:
> "Equality and relational comparisons between two operands of array type are
> deprecated."
> so this patch adds -Wdeprecated-array-compare (enabled by default in C++20).
A warning like this would be useful in C as well even though there
array equality is not deprecated (though relational expressions
involving distinct objects are undefined). Recently, while working
on my -Waddress enhancement to "warn for more impossible null
pointer tests​, I noticed Clang warns for some of these equality
tests in both languages (it issues -Wtautological-compare).
Rather that referring to deprecation, if one is necessary, I would
suggest to choose a name for the option that reflects the problem
the warning (and presumably the deprecation in C++) tries to prevent.
That said, since GCC already has both -Waddress and -Wtautological-
compare for these problems, the warning could be issued under either
of these.
Martin
>
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>
> PR c++/97573
>
> gcc/c-family/ChangeLog:
>
> * c-opts.c (c_common_post_options): In C++20, turn on
> -Wdeprecated-array-compare.
> * c.opt (Wdeprecated-array-compare): New option.
>
> gcc/cp/ChangeLog:
>
> * typeck.c (do_warn_deprecated_array_compare): New.
> (cp_build_binary_op): Call it for equality and relational comparisons.
>
> gcc/ChangeLog:
>
> * doc/invoke.texi: Document -Wdeprecated-array-compare.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/tree-ssa/pr15791-1.C: Add dg-warning.
> * g++.dg/cpp2a/array-comp1.C: New test.
> * g++.dg/cpp2a/array-comp2.C: New test.
> * g++.dg/cpp2a/array-comp3.C: New test.
> ---
> gcc/c-family/c-opts.c | 5 ++++
> gcc/c-family/c.opt | 4 +++
> gcc/cp/typeck.c | 28 +++++++++++++++++++
> gcc/doc/invoke.texi | 19 ++++++++++++-
> gcc/testsuite/g++.dg/cpp2a/array-comp1.C | 34 +++++++++++++++++++++++
> gcc/testsuite/g++.dg/cpp2a/array-comp2.C | 31 +++++++++++++++++++++
> gcc/testsuite/g++.dg/cpp2a/array-comp3.C | 29 +++++++++++++++++++
> gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C | 2 +-
> 8 files changed, 150 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp3.C
>
> diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
> index 3eaab5e1530..00b52cc5e12 100644
> --- a/gcc/c-family/c-opts.c
> +++ b/gcc/c-family/c-opts.c
> @@ -962,6 +962,11 @@ c_common_post_options (const char **pfilename)
> warn_deprecated_enum_float_conv,
> cxx_dialect >= cxx20 && warn_deprecated);
>
> + /* -Wdeprecated-array-compare is enabled by default in C++20. */
> + SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> + warn_deprecated_array_compare,
> + cxx_dialect >= cxx20 && warn_deprecated);
> +
> /* Declone C++ 'structors if -Os. */
> if (flag_declone_ctor_dtor == -1)
> flag_declone_ctor_dtor = optimize_size;
> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index 9c151d19870..a4f0ea68594 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -540,6 +540,10 @@ Wdeprecated
> C C++ ObjC ObjC++ CPP(cpp_warn_deprecated) CppReason(CPP_W_DEPRECATED)
> ; Documented in common.opt
>
> +Wdeprecated-array-compare
> +C++ ObjC++ Var(warn_deprecated_array_compare) Warning
> +Warn about deprecated comparisons between two operands of array type.
> +
> Wdeprecated-copy
> C++ ObjC++ Var(warn_deprecated_copy) Warning LangEnabledBy(C++ ObjC++, Wextra)
> Mark implicitly-declared copy operations as deprecated if the class has a
> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> index a2398dbe660..1e3a41104d6 100644
> --- a/gcc/cp/typeck.c
> +++ b/gcc/cp/typeck.c
> @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
> #include "attribs.h"
> #include "asan.h"
> #include "gimplify.h"
> +#include "tree-pretty-print.h"
>
> static tree cp_build_addr_expr_strict (tree, tsubst_flags_t);
> static tree cp_build_function_call (tree, tree, tsubst_flags_t);
> @@ -4725,6 +4726,21 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
> }
> }
>
> +/* Warn about C++20 [depr.array.comp] array comparisons: "Equality
> + and relational comparisons between two operands of array type are
> + deprecated." */
> +
> +static inline void
> +do_warn_deprecated_array_compare (location_t location, tree_code code,
> + tree op0, tree op1)
> +{
> + if (warning_at (location, OPT_Wdeprecated_array_compare,
> + "comparison between two arrays is deprecated"))
> + inform (location, "use unary %<+%> which decays operands to pointers "
> + "or %<&%D[0] %s &%D[0]%> to compare the addresses",
> + op0, op_symbol_code (code), op1);
> +}
> +
> /* Build a binary-operation expression without default conversions.
> CODE is the kind of expression to build.
> LOCATION is the location_t of the operator in the source code.
> @@ -5289,6 +5305,11 @@ cp_build_binary_op (const op_location_t &location,
> warning_at (location, OPT_Waddress,
> "comparison with string literal results in "
> "unspecified behavior");
> + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
> + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE)
> + do_warn_deprecated_array_compare (location, code,
> + stripped_orig_op0,
> + stripped_orig_op1);
> }
>
> build_type = boolean_type_node;
> @@ -5559,6 +5580,13 @@ cp_build_binary_op (const op_location_t &location,
> "comparison with string literal results "
> "in unspecified behavior");
> }
> + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
> + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE
> + && code != SPACESHIP_EXPR
> + && (complain & tf_warning))
> + do_warn_deprecated_array_compare
> + (location, code, tree_strip_any_location_wrapper (orig_op0),
> + tree_strip_any_location_wrapper (orig_op1));
>
> if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1))
> {
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 5b016166972..a6c6a737639 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -249,7 +249,8 @@ in the following sections.
> -Wcomma-subscript -Wconditionally-supported @gol
> -Wno-conversion-null -Wctad-maybe-unsupported @gol
> -Wctor-dtor-privacy -Wno-delete-incomplete @gol
> --Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
> +-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare @gol
> +-Wdeprecated-copy -Wdeprecated-copy-dtor @gol
> -Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion @gol
> -Weffc++ -Wno-exceptions -Wextra-semi -Wno-inaccessible-base @gol
> -Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
> @@ -3521,6 +3522,22 @@ warning is enabled by @option{-Wextra}. With
> @option{-Wdeprecated-copy-dtor}, also deprecate if the class has a
> user-provided destructor.
>
> +@item -Wno-deprecated-array-compare @r{(C++ and Objective-C++ only)}
> +@opindex Wdeprecated-array-compare
> +@opindex Wno-deprecated-array-compare
> +Disable the warning about equality and relational comparisons between two
> +operands of array type. This comparison was deprecated in C++20. For
> +example:
> +
> +@smallexample
> +int arr1[5];
> +int arr2[5];
> +bool same = arr1 == arr2;
> +@end smallexample
> +
> +@option{-Wdeprecated-array-compare} is enabled by default with
> +@option{-std=c++20}.
> +
> @item -Wno-deprecated-enum-enum-conversion @r{(C++ and Objective-C++ only)}
> @opindex Wdeprecated-enum-enum-conversion
> @opindex Wno-deprecated-enum-enum-conversion
> diff --git a/gcc/testsuite/g++.dg/cpp2a/array-comp1.C b/gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> new file mode 100644
> index 00000000000..140d4d3c1dd
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> @@ -0,0 +1,34 @@
> +// PR c++/97573 - C++20 [depr.array.comp]
> +// { dg-do compile }
> +// No special options. In C++20 (only), we should get the deprecated warnings
> +// by default.
> +
> +int arr1[5];
> +int arr2[5];
> +int arr3[2][2];
> +int arr4[2][2];
> +
> +bool s1 = arr1 == arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s2 = arr1 != arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s3 = arr1 > arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s4 = arr1 >= arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s5 = arr1 < arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool s6 = arr1 <= arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +bool ok1 = +arr1 == +arr2;
> +bool ok2 = +arr1 != +arr2;
> +bool ok3 = +arr1 > +arr2;
> +bool ok4 = +arr1 >= +arr2;
> +bool ok5 = +arr1 < +arr2;
> +bool ok6 = +arr1 <= +arr2;
> +bool ok7 = &arr1[0] == &arr2[0];
> +bool ok8 = &arr1[0] != &arr2[0];
> +bool ok9 = &arr1[0] > &arr2[0];
> +bool ok10 = &arr1[0] >= &arr2[0];
> +bool ok11 = &arr1[0] < &arr2[0];
> +bool ok12 = &arr1[0] <= &arr2[0];
> +
> +bool s7 = arr3 == arr4; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> +
> +#if __cplusplus > 201703L
> +auto cmp = arr1 <=> arr2; // { dg-error "invalid operands" "" { target c++20 } }
> +#endif
> diff --git a/gcc/testsuite/g++.dg/cpp2a/array-comp2.C b/gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> new file mode 100644
> index 00000000000..b8409abb50a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> @@ -0,0 +1,31 @@
> +// PR c++/97573 - C++20 [depr.array.comp]
> +// { dg-do compile { target c++20 } }
> +// { dg-options "-Wno-deprecated" }
> +
> +int arr1[5];
> +int arr2[5];
> +int arr3[2][2];
> +int arr4[2][2];
> +
> +bool s1 = arr1 == arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s2 = arr1 != arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s3 = arr1 > arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s4 = arr1 >= arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s5 = arr1 < arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool s6 = arr1 <= arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> +bool ok1 = +arr1 == +arr2;
> +bool ok2 = +arr1 != +arr2;
> +bool ok3 = +arr1 > +arr2;
> +bool ok4 = +arr1 >= +arr2;
> +bool ok5 = +arr1 < +arr2;
> +bool ok6 = +arr1 <= +arr2;
> +bool ok7 = &arr1[0] == &arr2[0];
> +bool ok8 = &arr1[0] != &arr2[0];
> +bool ok9 = &arr1[0] > &arr2[0];
> +bool ok10 = &arr1[0] >= &arr2[0];
> +bool ok11 = &arr1[0] < &arr2[0];
> +bool ok12 = &arr1[0] <= &arr2[0];
> +
> +bool s7 = arr3 == arr4; // { dg-bogus "comparison between two arrays is deprecated" }
> +
> +auto cmp = arr1 <=> arr2; // { dg-error "invalid operands" }
> diff --git a/gcc/testsuite/g++.dg/cpp2a/array-comp3.C b/gcc/testsuite/g++.dg/cpp2a/array-comp3.C
> new file mode 100644
> index 00000000000..70a6b4cbfea
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/array-comp3.C
> @@ -0,0 +1,29 @@
> +// PR c++/97573 - C++20 [depr.array.comp]
> +// { dg-do compile { target { c++17_down } } }
> +// { dg-options "-Wdeprecated-array-compare" }
> +
> +int arr1[5];
> +int arr2[5];
> +int arr3[2][2];
> +int arr4[2][2];
> +
> +bool s1 = arr1 == arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s2 = arr1 != arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s3 = arr1 > arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s4 = arr1 >= arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s5 = arr1 < arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool s6 = arr1 <= arr2; // { dg-warning "comparison between two arrays is deprecated" }
> +bool ok1 = +arr1 == +arr2;
> +bool ok2 = +arr1 != +arr2;
> +bool ok3 = +arr1 > +arr2;
> +bool ok4 = +arr1 >= +arr2;
> +bool ok5 = +arr1 < +arr2;
> +bool ok6 = +arr1 <= +arr2;
> +bool ok7 = &arr1[0] == &arr2[0];
> +bool ok8 = &arr1[0] != &arr2[0];
> +bool ok9 = &arr1[0] > &arr2[0];
> +bool ok10 = &arr1[0] >= &arr2[0];
> +bool ok11 = &arr1[0] < &arr2[0];
> +bool ok12 = &arr1[0] <= &arr2[0];
> +
> +bool s7 = arr3 == arr4; // { dg-warning "comparison between two arrays is deprecated" }
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C b/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
> index 68f14adad00..5fc6a8ae5b3 100644
> --- a/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
> +++ b/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
> @@ -12,7 +12,7 @@ int main ()
> link_error ();
> if (b == &b[2])
> link_error ();
> - if (b != b)
> + if (b != b) // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> link_error ();
> if (&x.b[1] == &x.b[0])
> link_error ();
>
> base-commit: ef37ddf477ac4b21ec4d1be9260cfd3b431fd4a9
>
On Fri, Oct 01, 2021 at 09:16:53AM -0600, Martin Sebor wrote:
> On 9/30/21 8:50 AM, Marek Polacek via Gcc-patches wrote:
> > This patch addresses one of my leftovers from GCC 11. C++20 introduced
> > [depr.array.comp]:
> > "Equality and relational comparisons between two operands of array type are
> > deprecated."
> > so this patch adds -Wdeprecated-array-compare (enabled by default in C++20).
>
> A warning like this would be useful in C as well even though there
> array equality is not deprecated (though relational expressions
> involving distinct objects are undefined). Recently, while working
> on my -Waddress enhancement to "warn for more impossible null
> pointer tests​, I noticed Clang warns for some of these equality
> tests in both languages (it issues -Wtautological-compare).
I'll look into adding this warning to the C FE; it should be trivial.
> Rather that referring to deprecation, if one is necessary, I would
> suggest to choose a name for the option that reflects the problem
> the warning (and presumably the deprecation in C++) tries to prevent.
> That said, since GCC already has both -Waddress and -Wtautological-
> compare for these problems, the warning could be issued under either
> of these.
In my previous email I suggested -Warray-compare -- I wanted to avoid
the "deprecated" part outside C++20.
I also noticed the -Wtautological warning clang emits but I don't have
time to look into it. It probably won't warn for arrays declared with
__attribute__((weak)) so -Warray-compare still makes sense.
> > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
> >
> > PR c++/97573
> >
> > gcc/c-family/ChangeLog:
> >
> > * c-opts.c (c_common_post_options): In C++20, turn on
> > -Wdeprecated-array-compare.
> > * c.opt (Wdeprecated-array-compare): New option.
> >
> > gcc/cp/ChangeLog:
> >
> > * typeck.c (do_warn_deprecated_array_compare): New.
> > (cp_build_binary_op): Call it for equality and relational comparisons.
> >
> > gcc/ChangeLog:
> >
> > * doc/invoke.texi: Document -Wdeprecated-array-compare.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/tree-ssa/pr15791-1.C: Add dg-warning.
> > * g++.dg/cpp2a/array-comp1.C: New test.
> > * g++.dg/cpp2a/array-comp2.C: New test.
> > * g++.dg/cpp2a/array-comp3.C: New test.
> > ---
> > gcc/c-family/c-opts.c | 5 ++++
> > gcc/c-family/c.opt | 4 +++
> > gcc/cp/typeck.c | 28 +++++++++++++++++++
> > gcc/doc/invoke.texi | 19 ++++++++++++-
> > gcc/testsuite/g++.dg/cpp2a/array-comp1.C | 34 +++++++++++++++++++++++
> > gcc/testsuite/g++.dg/cpp2a/array-comp2.C | 31 +++++++++++++++++++++
> > gcc/testsuite/g++.dg/cpp2a/array-comp3.C | 29 +++++++++++++++++++
> > gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C | 2 +-
> > 8 files changed, 150 insertions(+), 2 deletions(-)
> > create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> > create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> > create mode 100644 gcc/testsuite/g++.dg/cpp2a/array-comp3.C
> >
> > diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
> > index 3eaab5e1530..00b52cc5e12 100644
> > --- a/gcc/c-family/c-opts.c
> > +++ b/gcc/c-family/c-opts.c
> > @@ -962,6 +962,11 @@ c_common_post_options (const char **pfilename)
> > warn_deprecated_enum_float_conv,
> > cxx_dialect >= cxx20 && warn_deprecated);
> > + /* -Wdeprecated-array-compare is enabled by default in C++20. */
> > + SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> > + warn_deprecated_array_compare,
> > + cxx_dialect >= cxx20 && warn_deprecated);
> > +
> > /* Declone C++ 'structors if -Os. */
> > if (flag_declone_ctor_dtor == -1)
> > flag_declone_ctor_dtor = optimize_size;
> > diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> > index 9c151d19870..a4f0ea68594 100644
> > --- a/gcc/c-family/c.opt
> > +++ b/gcc/c-family/c.opt
> > @@ -540,6 +540,10 @@ Wdeprecated
> > C C++ ObjC ObjC++ CPP(cpp_warn_deprecated) CppReason(CPP_W_DEPRECATED)
> > ; Documented in common.opt
> > +Wdeprecated-array-compare
> > +C++ ObjC++ Var(warn_deprecated_array_compare) Warning
> > +Warn about deprecated comparisons between two operands of array type.
> > +
> > Wdeprecated-copy
> > C++ ObjC++ Var(warn_deprecated_copy) Warning LangEnabledBy(C++ ObjC++, Wextra)
> > Mark implicitly-declared copy operations as deprecated if the class has a
> > diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> > index a2398dbe660..1e3a41104d6 100644
> > --- a/gcc/cp/typeck.c
> > +++ b/gcc/cp/typeck.c
> > @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
> > #include "attribs.h"
> > #include "asan.h"
> > #include "gimplify.h"
> > +#include "tree-pretty-print.h"
> > static tree cp_build_addr_expr_strict (tree, tsubst_flags_t);
> > static tree cp_build_function_call (tree, tree, tsubst_flags_t);
> > @@ -4725,6 +4726,21 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
> > }
> > }
> > +/* Warn about C++20 [depr.array.comp] array comparisons: "Equality
> > + and relational comparisons between two operands of array type are
> > + deprecated." */
> > +
> > +static inline void
> > +do_warn_deprecated_array_compare (location_t location, tree_code code,
> > + tree op0, tree op1)
> > +{
> > + if (warning_at (location, OPT_Wdeprecated_array_compare,
> > + "comparison between two arrays is deprecated"))
> > + inform (location, "use unary %<+%> which decays operands to pointers "
> > + "or %<&%D[0] %s &%D[0]%> to compare the addresses",
> > + op0, op_symbol_code (code), op1);
> > +}
> > +
> > /* Build a binary-operation expression without default conversions.
> > CODE is the kind of expression to build.
> > LOCATION is the location_t of the operator in the source code.
> > @@ -5289,6 +5305,11 @@ cp_build_binary_op (const op_location_t &location,
> > warning_at (location, OPT_Waddress,
> > "comparison with string literal results in "
> > "unspecified behavior");
> > + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
> > + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE)
> > + do_warn_deprecated_array_compare (location, code,
> > + stripped_orig_op0,
> > + stripped_orig_op1);
> > }
> > build_type = boolean_type_node;
> > @@ -5559,6 +5580,13 @@ cp_build_binary_op (const op_location_t &location,
> > "comparison with string literal results "
> > "in unspecified behavior");
> > }
> > + else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
> > + && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE
> > + && code != SPACESHIP_EXPR
> > + && (complain & tf_warning))
> > + do_warn_deprecated_array_compare
> > + (location, code, tree_strip_any_location_wrapper (orig_op0),
> > + tree_strip_any_location_wrapper (orig_op1));
> > if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1))
> > {
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index 5b016166972..a6c6a737639 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -249,7 +249,8 @@ in the following sections.
> > -Wcomma-subscript -Wconditionally-supported @gol
> > -Wno-conversion-null -Wctad-maybe-unsupported @gol
> > -Wctor-dtor-privacy -Wno-delete-incomplete @gol
> > --Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
> > +-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare @gol
> > +-Wdeprecated-copy -Wdeprecated-copy-dtor @gol
> > -Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion @gol
> > -Weffc++ -Wno-exceptions -Wextra-semi -Wno-inaccessible-base @gol
> > -Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
> > @@ -3521,6 +3522,22 @@ warning is enabled by @option{-Wextra}. With
> > @option{-Wdeprecated-copy-dtor}, also deprecate if the class has a
> > user-provided destructor.
> > +@item -Wno-deprecated-array-compare @r{(C++ and Objective-C++ only)}
> > +@opindex Wdeprecated-array-compare
> > +@opindex Wno-deprecated-array-compare
> > +Disable the warning about equality and relational comparisons between two
> > +operands of array type. This comparison was deprecated in C++20. For
> > +example:
> > +
> > +@smallexample
> > +int arr1[5];
> > +int arr2[5];
> > +bool same = arr1 == arr2;
> > +@end smallexample
> > +
> > +@option{-Wdeprecated-array-compare} is enabled by default with
> > +@option{-std=c++20}.
> > +
> > @item -Wno-deprecated-enum-enum-conversion @r{(C++ and Objective-C++ only)}
> > @opindex Wdeprecated-enum-enum-conversion
> > @opindex Wno-deprecated-enum-enum-conversion
> > diff --git a/gcc/testsuite/g++.dg/cpp2a/array-comp1.C b/gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> > new file mode 100644
> > index 00000000000..140d4d3c1dd
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp2a/array-comp1.C
> > @@ -0,0 +1,34 @@
> > +// PR c++/97573 - C++20 [depr.array.comp]
> > +// { dg-do compile }
> > +// No special options. In C++20 (only), we should get the deprecated warnings
> > +// by default.
> > +
> > +int arr1[5];
> > +int arr2[5];
> > +int arr3[2][2];
> > +int arr4[2][2];
> > +
> > +bool s1 = arr1 == arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> > +bool s2 = arr1 != arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> > +bool s3 = arr1 > arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> > +bool s4 = arr1 >= arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> > +bool s5 = arr1 < arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> > +bool s6 = arr1 <= arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> > +bool ok1 = +arr1 == +arr2;
> > +bool ok2 = +arr1 != +arr2;
> > +bool ok3 = +arr1 > +arr2;
> > +bool ok4 = +arr1 >= +arr2;
> > +bool ok5 = +arr1 < +arr2;
> > +bool ok6 = +arr1 <= +arr2;
> > +bool ok7 = &arr1[0] == &arr2[0];
> > +bool ok8 = &arr1[0] != &arr2[0];
> > +bool ok9 = &arr1[0] > &arr2[0];
> > +bool ok10 = &arr1[0] >= &arr2[0];
> > +bool ok11 = &arr1[0] < &arr2[0];
> > +bool ok12 = &arr1[0] <= &arr2[0];
> > +
> > +bool s7 = arr3 == arr4; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> > +
> > +#if __cplusplus > 201703L
> > +auto cmp = arr1 <=> arr2; // { dg-error "invalid operands" "" { target c++20 } }
> > +#endif
> > diff --git a/gcc/testsuite/g++.dg/cpp2a/array-comp2.C b/gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> > new file mode 100644
> > index 00000000000..b8409abb50a
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp2a/array-comp2.C
> > @@ -0,0 +1,31 @@
> > +// PR c++/97573 - C++20 [depr.array.comp]
> > +// { dg-do compile { target c++20 } }
> > +// { dg-options "-Wno-deprecated" }
> > +
> > +int arr1[5];
> > +int arr2[5];
> > +int arr3[2][2];
> > +int arr4[2][2];
> > +
> > +bool s1 = arr1 == arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> > +bool s2 = arr1 != arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> > +bool s3 = arr1 > arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> > +bool s4 = arr1 >= arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> > +bool s5 = arr1 < arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> > +bool s6 = arr1 <= arr2; // { dg-bogus "comparison between two arrays is deprecated" }
> > +bool ok1 = +arr1 == +arr2;
> > +bool ok2 = +arr1 != +arr2;
> > +bool ok3 = +arr1 > +arr2;
> > +bool ok4 = +arr1 >= +arr2;
> > +bool ok5 = +arr1 < +arr2;
> > +bool ok6 = +arr1 <= +arr2;
> > +bool ok7 = &arr1[0] == &arr2[0];
> > +bool ok8 = &arr1[0] != &arr2[0];
> > +bool ok9 = &arr1[0] > &arr2[0];
> > +bool ok10 = &arr1[0] >= &arr2[0];
> > +bool ok11 = &arr1[0] < &arr2[0];
> > +bool ok12 = &arr1[0] <= &arr2[0];
> > +
> > +bool s7 = arr3 == arr4; // { dg-bogus "comparison between two arrays is deprecated" }
> > +
> > +auto cmp = arr1 <=> arr2; // { dg-error "invalid operands" }
> > diff --git a/gcc/testsuite/g++.dg/cpp2a/array-comp3.C b/gcc/testsuite/g++.dg/cpp2a/array-comp3.C
> > new file mode 100644
> > index 00000000000..70a6b4cbfea
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp2a/array-comp3.C
> > @@ -0,0 +1,29 @@
> > +// PR c++/97573 - C++20 [depr.array.comp]
> > +// { dg-do compile { target { c++17_down } } }
> > +// { dg-options "-Wdeprecated-array-compare" }
> > +
> > +int arr1[5];
> > +int arr2[5];
> > +int arr3[2][2];
> > +int arr4[2][2];
> > +
> > +bool s1 = arr1 == arr2; // { dg-warning "comparison between two arrays is deprecated" }
> > +bool s2 = arr1 != arr2; // { dg-warning "comparison between two arrays is deprecated" }
> > +bool s3 = arr1 > arr2; // { dg-warning "comparison between two arrays is deprecated" }
> > +bool s4 = arr1 >= arr2; // { dg-warning "comparison between two arrays is deprecated" }
> > +bool s5 = arr1 < arr2; // { dg-warning "comparison between two arrays is deprecated" }
> > +bool s6 = arr1 <= arr2; // { dg-warning "comparison between two arrays is deprecated" }
> > +bool ok1 = +arr1 == +arr2;
> > +bool ok2 = +arr1 != +arr2;
> > +bool ok3 = +arr1 > +arr2;
> > +bool ok4 = +arr1 >= +arr2;
> > +bool ok5 = +arr1 < +arr2;
> > +bool ok6 = +arr1 <= +arr2;
> > +bool ok7 = &arr1[0] == &arr2[0];
> > +bool ok8 = &arr1[0] != &arr2[0];
> > +bool ok9 = &arr1[0] > &arr2[0];
> > +bool ok10 = &arr1[0] >= &arr2[0];
> > +bool ok11 = &arr1[0] < &arr2[0];
> > +bool ok12 = &arr1[0] <= &arr2[0];
> > +
> > +bool s7 = arr3 == arr4; // { dg-warning "comparison between two arrays is deprecated" }
> > diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C b/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
> > index 68f14adad00..5fc6a8ae5b3 100644
> > --- a/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
> > +++ b/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C
> > @@ -12,7 +12,7 @@ int main ()
> > link_error ();
> > if (b == &b[2])
> > link_error ();
> > - if (b != b)
> > + if (b != b) // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
> > link_error ();
> > if (&x.b[1] == &x.b[0])
> > link_error ();
> >
> > base-commit: ef37ddf477ac4b21ec4d1be9260cfd3b431fd4a9
> >
>
Marek
On Fri, Oct 01, 2021 at 09:30:41AM -0400, Jason Merrill wrote:
> On 9/30/21 17:56, Marek Polacek wrote:
> > On Thu, Sep 30, 2021 at 03:34:24PM -0400, Jason Merrill wrote:
> > > On 9/30/21 10:50, Marek Polacek wrote:
> > > > This patch addresses one of my leftovers from GCC 11. C++20 introduced
> > > > [depr.array.comp]:
> > > > "Equality and relational comparisons between two operands of array type are
> > > > deprecated."
> > > > so this patch adds -Wdeprecated-array-compare (enabled by default in C++20).
> > >
> > > Why not enable it by default in all modes? It was always pretty dubious
> > > code.
> >
> > Sure, it could be done, but it kind of complicates things: we'd probably
> > need a different option and a different message because it seems incorrect
> > to say "deprecated" in e.g. C++17 when this was only deprecated in C++20.
>
> The warning could say "deprecated in C++20", which is always true?
>
> > I'd rather not add another option; if it stays -Wdeprecated-array-compare
> > but -Wno-deprecated doesn't turn it off that also seems weird.
> >
> > I could rename it to -Warray-compare, enable by -Wall, and only
> > append "is deprecated" to the warning message in C++20. Does that seem
> > better?
>
> That sounds fine too.
I did this so that I can add the warning to the C FE too. Please
take a look at
<https://gcc.gnu.org/pipermail/gcc-patches/2021-October/580766.html>
if you get the chance, thanks.
So consider this patch discarded. I wonder what I could do so that
Patchwork marks it as such, too.
Marek
On 10/1/21 16:14, Marek Polacek wrote:
> On Fri, Oct 01, 2021 at 09:30:41AM -0400, Jason Merrill wrote:
>> On 9/30/21 17:56, Marek Polacek wrote:
>>> On Thu, Sep 30, 2021 at 03:34:24PM -0400, Jason Merrill wrote:
>>>> On 9/30/21 10:50, Marek Polacek wrote:
>>>>> This patch addresses one of my leftovers from GCC 11. C++20 introduced
>>>>> [depr.array.comp]:
>>>>> "Equality and relational comparisons between two operands of array type are
>>>>> deprecated."
>>>>> so this patch adds -Wdeprecated-array-compare (enabled by default in C++20).
>>>>
>>>> Why not enable it by default in all modes? It was always pretty dubious
>>>> code.
>>>
>>> Sure, it could be done, but it kind of complicates things: we'd probably
>>> need a different option and a different message because it seems incorrect
>>> to say "deprecated" in e.g. C++17 when this was only deprecated in C++20.
>>
>> The warning could say "deprecated in C++20", which is always true?
>>
>>> I'd rather not add another option; if it stays -Wdeprecated-array-compare
>>> but -Wno-deprecated doesn't turn it off that also seems weird.
>>>
>>> I could rename it to -Warray-compare, enable by -Wall, and only
>>> append "is deprecated" to the warning message in C++20. Does that seem
>>> better?
>>
>> That sounds fine too.
>
> I did this so that I can add the warning to the C FE too. Please
> take a look at
> <https://gcc.gnu.org/pipermail/gcc-patches/2021-October/580766.html>
> if you get the chance, thanks.
>
> So consider this patch discarded. I wonder what I could do so that
> Patchwork marks it as such, too.
Yes, I'm surprised that there don't seem to be any support for email
annotations to direct patchwork, only someone with maintainer privs can
retire a patch.
Jason
@@ -962,6 +962,11 @@ c_common_post_options (const char **pfilename)
warn_deprecated_enum_float_conv,
cxx_dialect >= cxx20 && warn_deprecated);
+ /* -Wdeprecated-array-compare is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_array_compare,
+ cxx_dialect >= cxx20 && warn_deprecated);
+
/* Declone C++ 'structors if -Os. */
if (flag_declone_ctor_dtor == -1)
flag_declone_ctor_dtor = optimize_size;
@@ -540,6 +540,10 @@ Wdeprecated
C C++ ObjC ObjC++ CPP(cpp_warn_deprecated) CppReason(CPP_W_DEPRECATED)
; Documented in common.opt
+Wdeprecated-array-compare
+C++ ObjC++ Var(warn_deprecated_array_compare) Warning
+Warn about deprecated comparisons between two operands of array type.
+
Wdeprecated-copy
C++ ObjC++ Var(warn_deprecated_copy) Warning LangEnabledBy(C++ ObjC++, Wextra)
Mark implicitly-declared copy operations as deprecated if the class has a
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "asan.h"
#include "gimplify.h"
+#include "tree-pretty-print.h"
static tree cp_build_addr_expr_strict (tree, tsubst_flags_t);
static tree cp_build_function_call (tree, tree, tsubst_flags_t);
@@ -4725,6 +4726,21 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
}
}
+/* Warn about C++20 [depr.array.comp] array comparisons: "Equality
+ and relational comparisons between two operands of array type are
+ deprecated." */
+
+static inline void
+do_warn_deprecated_array_compare (location_t location, tree_code code,
+ tree op0, tree op1)
+{
+ if (warning_at (location, OPT_Wdeprecated_array_compare,
+ "comparison between two arrays is deprecated"))
+ inform (location, "use unary %<+%> which decays operands to pointers "
+ "or %<&%D[0] %s &%D[0]%> to compare the addresses",
+ op0, op_symbol_code (code), op1);
+}
+
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the location_t of the operator in the source code.
@@ -5289,6 +5305,11 @@ cp_build_binary_op (const op_location_t &location,
warning_at (location, OPT_Waddress,
"comparison with string literal results in "
"unspecified behavior");
+ else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE)
+ do_warn_deprecated_array_compare (location, code,
+ stripped_orig_op0,
+ stripped_orig_op1);
}
build_type = boolean_type_node;
@@ -5559,6 +5580,13 @@ cp_build_binary_op (const op_location_t &location,
"comparison with string literal results "
"in unspecified behavior");
}
+ else if (TREE_CODE (TREE_TYPE (orig_op0)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (orig_op1)) == ARRAY_TYPE
+ && code != SPACESHIP_EXPR
+ && (complain & tf_warning))
+ do_warn_deprecated_array_compare
+ (location, code, tree_strip_any_location_wrapper (orig_op0),
+ tree_strip_any_location_wrapper (orig_op1));
if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1))
{
@@ -249,7 +249,8 @@ in the following sections.
-Wcomma-subscript -Wconditionally-supported @gol
-Wno-conversion-null -Wctad-maybe-unsupported @gol
-Wctor-dtor-privacy -Wno-delete-incomplete @gol
--Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
+-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare @gol
+-Wdeprecated-copy -Wdeprecated-copy-dtor @gol
-Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion @gol
-Weffc++ -Wno-exceptions -Wextra-semi -Wno-inaccessible-base @gol
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
@@ -3521,6 +3522,22 @@ warning is enabled by @option{-Wextra}. With
@option{-Wdeprecated-copy-dtor}, also deprecate if the class has a
user-provided destructor.
+@item -Wno-deprecated-array-compare @r{(C++ and Objective-C++ only)}
+@opindex Wdeprecated-array-compare
+@opindex Wno-deprecated-array-compare
+Disable the warning about equality and relational comparisons between two
+operands of array type. This comparison was deprecated in C++20. For
+example:
+
+@smallexample
+int arr1[5];
+int arr2[5];
+bool same = arr1 == arr2;
+@end smallexample
+
+@option{-Wdeprecated-array-compare} is enabled by default with
+@option{-std=c++20}.
+
@item -Wno-deprecated-enum-enum-conversion @r{(C++ and Objective-C++ only)}
@opindex Wdeprecated-enum-enum-conversion
@opindex Wno-deprecated-enum-enum-conversion
new file mode 100644
@@ -0,0 +1,34 @@
+// PR c++/97573 - C++20 [depr.array.comp]
+// { dg-do compile }
+// No special options. In C++20 (only), we should get the deprecated warnings
+// by default.
+
+int arr1[5];
+int arr2[5];
+int arr3[2][2];
+int arr4[2][2];
+
+bool s1 = arr1 == arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
+bool s2 = arr1 != arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
+bool s3 = arr1 > arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
+bool s4 = arr1 >= arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
+bool s5 = arr1 < arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
+bool s6 = arr1 <= arr2; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
+bool ok1 = +arr1 == +arr2;
+bool ok2 = +arr1 != +arr2;
+bool ok3 = +arr1 > +arr2;
+bool ok4 = +arr1 >= +arr2;
+bool ok5 = +arr1 < +arr2;
+bool ok6 = +arr1 <= +arr2;
+bool ok7 = &arr1[0] == &arr2[0];
+bool ok8 = &arr1[0] != &arr2[0];
+bool ok9 = &arr1[0] > &arr2[0];
+bool ok10 = &arr1[0] >= &arr2[0];
+bool ok11 = &arr1[0] < &arr2[0];
+bool ok12 = &arr1[0] <= &arr2[0];
+
+bool s7 = arr3 == arr4; // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
+
+#if __cplusplus > 201703L
+auto cmp = arr1 <=> arr2; // { dg-error "invalid operands" "" { target c++20 } }
+#endif
new file mode 100644
@@ -0,0 +1,31 @@
+// PR c++/97573 - C++20 [depr.array.comp]
+// { dg-do compile { target c++20 } }
+// { dg-options "-Wno-deprecated" }
+
+int arr1[5];
+int arr2[5];
+int arr3[2][2];
+int arr4[2][2];
+
+bool s1 = arr1 == arr2; // { dg-bogus "comparison between two arrays is deprecated" }
+bool s2 = arr1 != arr2; // { dg-bogus "comparison between two arrays is deprecated" }
+bool s3 = arr1 > arr2; // { dg-bogus "comparison between two arrays is deprecated" }
+bool s4 = arr1 >= arr2; // { dg-bogus "comparison between two arrays is deprecated" }
+bool s5 = arr1 < arr2; // { dg-bogus "comparison between two arrays is deprecated" }
+bool s6 = arr1 <= arr2; // { dg-bogus "comparison between two arrays is deprecated" }
+bool ok1 = +arr1 == +arr2;
+bool ok2 = +arr1 != +arr2;
+bool ok3 = +arr1 > +arr2;
+bool ok4 = +arr1 >= +arr2;
+bool ok5 = +arr1 < +arr2;
+bool ok6 = +arr1 <= +arr2;
+bool ok7 = &arr1[0] == &arr2[0];
+bool ok8 = &arr1[0] != &arr2[0];
+bool ok9 = &arr1[0] > &arr2[0];
+bool ok10 = &arr1[0] >= &arr2[0];
+bool ok11 = &arr1[0] < &arr2[0];
+bool ok12 = &arr1[0] <= &arr2[0];
+
+bool s7 = arr3 == arr4; // { dg-bogus "comparison between two arrays is deprecated" }
+
+auto cmp = arr1 <=> arr2; // { dg-error "invalid operands" }
new file mode 100644
@@ -0,0 +1,29 @@
+// PR c++/97573 - C++20 [depr.array.comp]
+// { dg-do compile { target { c++17_down } } }
+// { dg-options "-Wdeprecated-array-compare" }
+
+int arr1[5];
+int arr2[5];
+int arr3[2][2];
+int arr4[2][2];
+
+bool s1 = arr1 == arr2; // { dg-warning "comparison between two arrays is deprecated" }
+bool s2 = arr1 != arr2; // { dg-warning "comparison between two arrays is deprecated" }
+bool s3 = arr1 > arr2; // { dg-warning "comparison between two arrays is deprecated" }
+bool s4 = arr1 >= arr2; // { dg-warning "comparison between two arrays is deprecated" }
+bool s5 = arr1 < arr2; // { dg-warning "comparison between two arrays is deprecated" }
+bool s6 = arr1 <= arr2; // { dg-warning "comparison between two arrays is deprecated" }
+bool ok1 = +arr1 == +arr2;
+bool ok2 = +arr1 != +arr2;
+bool ok3 = +arr1 > +arr2;
+bool ok4 = +arr1 >= +arr2;
+bool ok5 = +arr1 < +arr2;
+bool ok6 = +arr1 <= +arr2;
+bool ok7 = &arr1[0] == &arr2[0];
+bool ok8 = &arr1[0] != &arr2[0];
+bool ok9 = &arr1[0] > &arr2[0];
+bool ok10 = &arr1[0] >= &arr2[0];
+bool ok11 = &arr1[0] < &arr2[0];
+bool ok12 = &arr1[0] <= &arr2[0];
+
+bool s7 = arr3 == arr4; // { dg-warning "comparison between two arrays is deprecated" }
@@ -12,7 +12,7 @@ int main ()
link_error ();
if (b == &b[2])
link_error ();
- if (b != b)
+ if (b != b) // { dg-warning "comparison between two arrays is deprecated" "" { target c++20 } }
link_error ();
if (&x.b[1] == &x.b[0])
link_error ();