From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ot1-x32e.google.com (mail-ot1-x32e.google.com [IPv6:2607:f8b0:4864:20::32e]) by sourceware.org (Postfix) with ESMTPS id 007583858406 for ; Fri, 1 Oct 2021 15:16:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 007583858406 Received: by mail-ot1-x32e.google.com with SMTP id e66-20020a9d2ac8000000b0054da8bdf2aeso9672856otb.12 for ; Fri, 01 Oct 2021 08:16:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=JJF7P+C9ZstC3oLgtQbewhbm0nv9Jnc97Lor5neClVk=; b=MQ02Jl0IKzBC1GNQHXEW8bC4pVfdifF9CaTvWV8lavF5hypOIeFsL+UYJvxW6+A3o0 fo4tRn6/YN+fRE8uJ8Jo+46u2LSBzXSciaYwtw8QTeVRhdPbm/VM4pJoAzPKiShHSaXr yXm4l5H9nMt+DCzDtg5GpBwIWqOdRuY/LSOv8IJe7Pa3y/K/Gpzb2aYPdTtIJFivuV8C oWQPlJtcSzDbtKcWWlr7TJyeWd5ykhCyu9ZhGNrD5Gj4naysWd9Wek1jSMfTqX0S9iAN AhkJU5XPOkCuYc1v9c0f5ego4nhMeh5jwgIYh4+htVUpYhtkZlXE+5INqVrqNZ9Kysjj VqYQ== X-Gm-Message-State: AOAM532tdTrnvCAuuKSSoIHgHDV0m19SiTDWPibXWJ4eGAxy3kZ3f3EV +7Hjsvyao15tztdFc1bkckYAo6IlaGM= X-Google-Smtp-Source: ABdhPJwG/124qSSDb4ZbZzF7CWIB7/L8xGvZ5jqxz+zfG1AFHHN3MeFzbgDQ62O7NPw68MahBC3/UQ== X-Received: by 2002:a9d:4f12:: with SMTP id d18mr10680398otl.169.1633101417235; Fri, 01 Oct 2021 08:16:57 -0700 (PDT) Received: from [192.168.0.41] (97-118-96-133.hlrn.qwest.net. [97.118.96.133]) by smtp.gmail.com with ESMTPSA id e6sm1209246otr.79.2021.10.01.08.16.55 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 01 Oct 2021 08:16:56 -0700 (PDT) Subject: Re: [PATCH] c++: Implement C++20 -Wdeprecated-array-compare [PR97573] To: Marek Polacek , GCC Patches , Jason Merrill References: <20210930145031.23104-1-polacek@redhat.com> From: Martin Sebor Message-ID: <0a1b41b6-f79c-e84d-03a7-2b5d8dfed035@gmail.com> Date: Fri, 1 Oct 2021 09:16:53 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 In-Reply-To: <20210930145031.23104-1-polacek@redhat.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Oct 2021 15:17:00 -0000 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 >