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

Reply via email to