From patchwork Thu Sep 30 14:50:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 45606 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AE4853858013 for ; Thu, 30 Sep 2021 14:51:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AE4853858013 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1633013478; bh=YDKtMhgKh9V9YszcE7uLf/KxUq7YqgllXbbTf3loIdU=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=huIR/pk04ftOcppQp86DosirHdLXlmrXdek77nckowNb+TFczFd3jUWy47eeF3c4x /Z/bAWMNeLM/sSDKTI56k9vyxBjPqjLysH0AUWQnfwN7G5+H0NIo+iuudGKWOxtHbi GLlwpkPiz3RfX1adh/Cxjha7rE9Dp5hOnomamGsk= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id 521AA3857C4E for ; Thu, 30 Sep 2021 14:50:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 521AA3857C4E Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-451-yJO15SDiM5ylYEIICsC0DQ-1; Thu, 30 Sep 2021 10:50:45 -0400 X-MC-Unique: yJO15SDiM5ylYEIICsC0DQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8F63A835DE1 for ; Thu, 30 Sep 2021 14:50:44 +0000 (UTC) Received: from pdp-11.hsd1.ma.comcast.net (unknown [10.22.34.85]) by smtp.corp.redhat.com (Postfix) with ESMTP id D26DC604CC; Thu, 30 Sep 2021 14:50:36 +0000 (UTC) To: GCC Patches , Jason Merrill Subject: [PATCH] c++: Implement C++20 -Wdeprecated-array-compare [PR97573] Date: Thu, 30 Sep 2021 10:50:31 -0400 Message-Id: <20210930145031.23104-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, 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-Patchwork-Original-From: Marek Polacek via Gcc-patches From: Marek Polacek Reply-To: Marek Polacek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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 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 ();