https://github.com/AmrDeveloper created 
https://github.com/llvm/llvm-project/pull/118031

Currently, we support `-wdeprecated-array-compare` for C++20 or above and don't 
report any warning for older versions, this PR supports `-Warray-compare` for 
older versions and for GCC compatibility.

Fixes #114770

>From 9451a1e4f5db18d579b5f7eb206482708c9adc70 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Tue, 26 Nov 2024 22:28:16 +0100
Subject: [PATCH 1/4] Add support for '-Warray-compare' compiler flag

---
 clang/include/clang/Basic/DiagnosticGroups.td    |  1 +
 clang/include/clang/Basic/DiagnosticSemaKinds.td |  5 +++++
 clang/lib/Sema/SemaExpr.cpp                      | 14 ++++++++++----
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index df9bf94b5d0398..0b57d41c617963 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -699,6 +699,7 @@ def GNUStatementExpressionFromMacroExpansion :
 def GNUStatementExpression : DiagGroup<"gnu-statement-expression",
                                        
[GNUStatementExpressionFromMacroExpansion]>;
 def StringConcatation : DiagGroup<"string-concatenation">;
+def ArrayCompare : DiagGroup<"array-compare">;
 def StringCompare : DiagGroup<"string-compare">;
 def StringPlusInt : DiagGroup<"string-plus-int">;
 def StringPlusChar : DiagGroup<"string-plus-char">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 834e588c18e376..a96fddcc797d36 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10264,6 +10264,11 @@ def warn_depr_array_comparison : Warning<
   "to compare array addresses, use unary '+' to decay operands to pointers">,
   InGroup<DeprecatedArrayCompare>;
 
+def warn_array_comparison : Warning<
+  "comparison between two arrays; "
+  "to compare array addresses, use unary '+' to decay operands to pointers">,
+  InGroup<ArrayCompare>;
+
 def warn_stringcompare : Warning<
   "result of comparison against %select{a string literal|@encode}0 is "
   "unspecified (use an explicit string comparison function instead)">,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c9d7444d5865a5..d51aca4fbaf492 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11857,11 +11857,17 @@ static void diagnoseTautologicalComparison(Sema &S, 
SourceLocation Loc,
   // C++2a [depr.array.comp]:
   //   Equality and relational comparisons ([expr.eq], [expr.rel]) between two
   //   operands of array type are deprecated.
-  if (S.getLangOpts().CPlusPlus20 && LHSStripped->getType()->isArrayType() &&
+  if (LHSStripped->getType()->isArrayType() &&
       RHSStripped->getType()->isArrayType()) {
-    S.Diag(Loc, diag::warn_depr_array_comparison)
-        << LHS->getSourceRange() << RHS->getSourceRange()
-        << LHSStripped->getType() << RHSStripped->getType();
+    auto IsDeprArrayComparionIgnored =
+        S.getDiagnostics().isIgnored(diag::warn_depr_array_comparison, Loc);
+    auto IsDeprArrayComparion =
+        !S.getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored;
+
+    auto DiagID = IsDeprArrayComparion ? diag::warn_array_comparison
+                                       : diag::warn_depr_array_comparison;
+    S.Diag(Loc, DiagID) << LHS->getSourceRange() << RHS->getSourceRange()
+                        << LHSStripped->getType() << RHSStripped->getType();
     // Carry on to produce the tautological comparison warning, if this
     // expression is potentially-evaluated, we can resolve the array to a
     // non-weak declaration, and so on.

>From 6de4cba4dc9edae545efe85d2435d1f4430968af Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Wed, 27 Nov 2024 21:17:21 +0100
Subject: [PATCH 2/4] Add lit test for array-comparison

---
 clang/test/SemaCXX/deprecated.cpp            | 12 +++++++-----
 clang/test/SemaCXX/warn-self-comparisons.cpp |  6 +++---
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/clang/test/SemaCXX/deprecated.cpp 
b/clang/test/SemaCXX/deprecated.cpp
index 667f4d7d3edb03..03f3b2b8ff06be 100644
--- a/clang/test/SemaCXX/deprecated.cpp
+++ b/clang/test/SemaCXX/deprecated.cpp
@@ -246,17 +246,19 @@ namespace ArithConv {
 
 namespace ArrayComp {
   int arr1[3], arr2[4];
-  bool b1 = arr1 == arr2; // expected-warning {{array comparison always 
evaluates to false}} cxx20-warning {{comparison between two arrays is 
deprecated}}
-  bool b2 = arr1 < arr2; // expected-warning {{array comparison always 
evaluates to a constant}} cxx20-warning {{comparison between two arrays is 
deprecated}}
+  bool b1 = arr1 == arr2; // not-cxx20-warning {{comparison between two 
arrays}} cxx20-warning {{comparison between two arrays is deprecated}}
+                          // expected-warning@-1 {{array comparison always 
evaluates to false}} 
+  bool b2 = arr1 < arr2; // not-cxx20-warning {{comparison between two 
arrays;}} cxx20-warning {{comparison between two arrays is deprecated}}
+                         // expected-warning@-1 {{array comparison always 
evaluates to a constant}}
   __attribute__((weak)) int arr3[3];
-  bool b3 = arr1 == arr3; // cxx20-warning {{comparison between two arrays is 
deprecated}}
-  bool b4 = arr1 < arr3; // cxx20-warning {{comparison between two arrays is 
deprecated}}
+  bool b3 = arr1 == arr3; // not-cxx20-warning {{comparison between two 
arrays;}} cxx20-warning {{comparison between two arrays is deprecated}}
+  bool b4 = arr1 < arr3; // not-cxx20-warning {{comparison between two 
arrays;}} cxx20-warning {{comparison between two arrays is deprecated}}
 #if __cplusplus > 201703L
   bool b5 = arr1 <=> arr2; // cxx20-error {{invalid operands}}
 #endif
 
   int (&f())[3];
-  bool b6 = arr1 == f(); // cxx20-warning {{comparison between two arrays is 
deprecated}}
+  bool b6 = arr1 == f(); // not-cxx20-warning {{comparison between two 
arrays;}} cxx20-warning {{comparison between two arrays is deprecated}}
   bool b7 = arr1 == +f();
 }
 
diff --git a/clang/test/SemaCXX/warn-self-comparisons.cpp 
b/clang/test/SemaCXX/warn-self-comparisons.cpp
index 2e8d130bcd5a0a..daf546d5858074 100644
--- a/clang/test/SemaCXX/warn-self-comparisons.cpp
+++ b/clang/test/SemaCXX/warn-self-comparisons.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s 
-verify=expected,not-cxx20
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wdeprecated -verify %s 
-verify=expected,cxx20
 
 void f(int (&array1)[2], int (&array2)[2]) {
-  if (array1 == array2) { } // no warning
+  if (array1 == array2) { } // not-cxx20-warning {{comparison between two 
arrays;}} cxx20-warning {{comparison between two arrays is deprecated}}
 }

>From fe4fab80606ecc7cdbf5eb6bfa1465b96fd867e5 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Wed, 27 Nov 2024 22:43:29 +0100
Subject: [PATCH 3/4] Add test file to handle warn array comparion cases

---
 clang/test/SemaCXX/warn-array-comparion.cpp | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 clang/test/SemaCXX/warn-array-comparion.cpp

diff --git a/clang/test/SemaCXX/warn-array-comparion.cpp 
b/clang/test/SemaCXX/warn-array-comparion.cpp
new file mode 100644
index 00000000000000..bda6b6969400f1
--- /dev/null
+++ b/clang/test/SemaCXX/warn-array-comparion.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s 
-verify=expected,not-cxx20
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wno-deprecated-array-compare 
-verify %s -verify=expected,not-cxx20
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -Wdeprecated -verify %s 
-verify=expected,cxx20
+
+typedef struct {
+  char str[16];
+  int id[16];
+} Object;
+
+bool object_equal(const Object &obj1, const Object &obj2) {
+  if (obj1.str != obj2.str) // not-cxx20-warning {{comparison between two 
arrays;}} cxx20-warning {{comparison between two arrays is deprecated}}
+    return false;
+  if (obj1.id != obj2.id) // not-cxx20-warning {{comparison between two 
arrays;}} cxx20-warning {{comparison between two arrays is deprecated}}
+    return false;
+  return true;
+}
+
+
+void foo(int (&array1)[2], int (&array2)[2]) {
+  if (array1 == array2) { } // not-cxx20-warning {{comparison between two 
arrays;}} cxx20-warning {{comparison between two arrays is deprecated}}
+}

>From bece93792867375d0112d5686b00be21110f4da1 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Wed, 27 Nov 2024 22:45:48 +0100
Subject: [PATCH 4/4] Update comment to add warning case in C++1a versions

---
 clang/lib/Sema/SemaExpr.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d51aca4fbaf492..e30587459b8aff 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11854,6 +11854,9 @@ static void diagnoseTautologicalComparison(Sema &S, 
SourceLocation Loc,
     AlwaysEqual, // std::strong_ordering::equal from operator<=>
   };
 
+  // C++1a [array.comp]:
+  //   Equality and relational comparisons ([expr.eq], [expr.rel]) between two
+  //   operands of array type.
   // C++2a [depr.array.comp]:
   //   Equality and relational comparisons ([expr.eq], [expr.rel]) between two
   //   operands of array type are deprecated.

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to