[clang] 7347e5e - [Clang] Add '-Warray-compare' flag for C++ below version 20 (#118031)

via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 4 10:33:29 PST 2024


Author: Amr Hesham
Date: 2024-12-04T19:33:25+01:00
New Revision: 7347e5e89a671d675ba144e181e3d24bd072f527

URL: https://github.com/llvm/llvm-project/commit/7347e5e89a671d675ba144e181e3d24bd072f527
DIFF: https://github.com/llvm/llvm-project/commit/7347e5e89a671d675ba144e181e3d24bd072f527.diff

LOG: [Clang] Add '-Warray-compare' flag for C++ below version 20 (#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

Added: 
    clang/test/SemaCXX/warn-array-comparion.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaExpr.cpp
    clang/test/Analysis/reference.cpp
    clang/test/Sema/warn-stringcompare.c
    clang/test/SemaCXX/deprecated.cpp
    clang/test/SemaCXX/warn-self-comparisons.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7f7d077e284af3..16c7f770f9b858 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -419,6 +419,9 @@ New Compiler Flags
   existing ``-fno-c++-static-destructors`` flag) skips all static
   destructors registration.
 
+- The ``-Warray-compare`` warning has been added to warn about array comparison
+  on versions older than C++20.
+
 Deprecated Compiler Flags
 -------------------------
 

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8020be6c57bcfb..2137cb713164ad 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10269,6 +10269,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 compare their addresses and will be deprecated in c++20; "
+  "to compare array addresses, use unary '+' to decay operands to pointers">,
+  InGroup<DiagGroup<"array-compare">>;
+
 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 adad14cc0f1f6b..4ffce2c1236610 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11833,14 +11833,21 @@ 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.
-  if (S.getLangOpts().CPlusPlus20 && LHSStripped->getType()->isArrayType() &&
+  if (S.getLangOpts().CPlusPlus && 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 DiagID = !S.getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored
+                      ? 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.

diff  --git a/clang/test/Analysis/reference.cpp b/clang/test/Analysis/reference.cpp
index b893aec2a7d542..91ba3cd23249a3 100644
--- a/clang/test/Analysis/reference.cpp
+++ b/clang/test/Analysis/reference.cpp
@@ -89,8 +89,8 @@ namespace PR13440 {
     S s = { a };
     S2 s2 = { a };
 
-    if (s.x != a) return;
-    if (s2.x != a) return;
+    if (s.x != a) return;  // expected-warning {{comparison between two arrays}}
+    if (s2.x != a) return; // expected-warning {{comparison between two arrays}}
 
     a[0] = 42;
     clang_analyzer_eval(s.x[0] == 42); // expected-warning{{TRUE}}

diff  --git a/clang/test/Sema/warn-stringcompare.c b/clang/test/Sema/warn-stringcompare.c
index 77876ad6abd6e7..78145cf42578a4 100644
--- a/clang/test/Sema/warn-stringcompare.c
+++ b/clang/test/Sema/warn-stringcompare.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -x c -fsyntax-only -verify %s
-// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cxx %s
 
 #define DELIM "/"
 #define DOT "."
@@ -15,15 +15,15 @@ void test(const char *d) {
   if (NULL == "/")
     return;
   if ("/" != DELIM) // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}}
-    return;
+    return;         // cxx-warning at -1 {{comparison between two arrays}}
   if (DELIM == "/") // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}}
-    return;
+    return;         // cxx-warning at -1 {{comparison between two arrays}}
   if (DELIM != NULL)
     return;
   if (NULL == DELIM)
     return;
   if (DOT != DELIM) // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}}
-    return;
+    return;         // cxx-warning at -1 {{comparison between two arrays}}
   if (DELIM == DOT) // expected-warning {{result of comparison against a string literal is unspecified (use an explicit string comparison function instead)}}
-    return;
+    return;         // cxx-warning at -1 {{comparison between two arrays}}
 }

diff  --git a/clang/test/SemaCXX/deprecated.cpp b/clang/test/SemaCXX/deprecated.cpp
index 667f4d7d3edb03..4282239af81b4c 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 compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
+                          // expected-warning at -1 {{array comparison always evaluates to false}} 
+  bool b2 = arr1 < arr2; // not-cxx20-warning {{comparison between two arrays compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
+                         // expected-warning at -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 compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
+  bool b4 = arr1 < arr3; // not-cxx20-warning {{comparison between two arrays compare their addresses}} 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 compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
   bool b7 = arr1 == +f();
 }
 

diff  --git a/clang/test/SemaCXX/warn-array-comparion.cpp b/clang/test/SemaCXX/warn-array-comparion.cpp
new file mode 100644
index 00000000000000..a6eaaab22fc16d
--- /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 compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
+    return false;
+  if (obj1.id != obj2.id) // not-cxx20-warning {{comparison between two arrays compare their addresses}} 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 compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
+}

diff  --git a/clang/test/SemaCXX/warn-self-comparisons.cpp b/clang/test/SemaCXX/warn-self-comparisons.cpp
index 2e8d130bcd5a0a..3847c2d918bf61 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 compare their addresses}} cxx20-warning {{comparison between two arrays is deprecated}}
 }


        


More information about the cfe-commits mailing list