public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: Implement C++20 -Wdeprecated-array-compare [PR97573]
@ 2021-09-30 14:50 Marek Polacek
  2021-09-30 19:34 ` Jason Merrill
  2021-10-01 15:16 ` Martin Sebor
  0 siblings, 2 replies; 8+ messages in thread
From: Marek Polacek @ 2021-09-30 14:50 UTC (permalink / raw)
  To: GCC Patches, Jason Merrill

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

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
-- 
2.31.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-10-05 19:05 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-30 14:50 [PATCH] c++: Implement C++20 -Wdeprecated-array-compare [PR97573] Marek Polacek
2021-09-30 19:34 ` Jason Merrill
2021-09-30 21:56   ` Marek Polacek
2021-10-01 13:30     ` Jason Merrill
2021-10-01 20:14       ` Marek Polacek
2021-10-05 19:05         ` Jason Merrill
2021-10-01 15:16 ` Martin Sebor
2021-10-01 15:43   ` Marek Polacek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).