[clang] [Clang] Add '-Warray-compare' flag for C++ below version 20 (PR #118031)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 28 12:09:26 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Amr Hesham (AmrDeveloper)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/118031.diff
6 Files Affected:
- (modified) clang/include/clang/Basic/DiagnosticGroups.td (+1)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5)
- (modified) clang/lib/Sema/SemaExpr.cpp (+13-4)
- (modified) clang/test/SemaCXX/deprecated.cpp (+7-5)
- (added) clang/test/SemaCXX/warn-array-comparion.cpp (+21)
- (modified) clang/test/SemaCXX/warn-self-comparisons.cpp (+3-3)
``````````diff
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..e30587459b8aff 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11854,14 +11854,23 @@ 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 (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.
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 at -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 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;}} 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-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}}
+}
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}}
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/118031
More information about the cfe-commits
mailing list