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@-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-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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits