https://github.com/hjanuschka updated https://github.com/llvm/llvm-project/pull/182065
>From 8d328d49e8a2cc08b7f390d39cdaab481aff5dae Mon Sep 17 00:00:00 2001 From: Helmut Januschka <[email protected]> Date: Wed, 18 Feb 2026 18:03:47 +0100 Subject: [PATCH] [clang-tidy] Add none_of suggestion to readability-use-anyofallof --- .../readability/UseAnyOfAllOfCheck.cpp | 29 +++++++++++++++++-- clang-tools-extra/docs/ReleaseNotes.rst | 4 +++ .../checks/readability/use-anyofallof.rst | 5 ++-- .../checkers/readability/use-anyofallof.cpp | 11 ++++++- 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp index 63649150b17e3..7d5f3f547e610 100644 --- a/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp @@ -84,6 +84,26 @@ static bool isViableLoop(const CXXForRangeStmt &S, ASTContext &Context) { }); } +/// For the all_of_loop pattern (returns false inside, true after), check +/// whether the if-condition is negated. If it is, the loop is an all_of; +/// otherwise it is a none_of. +static bool isNoneOfPattern(const CXXForRangeStmt &Loop) { + const Stmt *Body = Loop.getBody(); + const IfStmt *If = nullptr; + if (const auto *Compound = dyn_cast<CompoundStmt>(Body)) { + if (Compound->size() == 1) + If = dyn_cast<IfStmt>(Compound->body_front()); + } else { + If = dyn_cast<IfStmt>(Body); + } + if (!If) + return false; + // If the condition is not negated (no leading !), it's a none_of pattern. + const Expr *Cond = If->getCond()->IgnoreParenImpCasts(); + const auto *UO = dyn_cast<UnaryOperator>(Cond); + return !UO || UO->getOpcode() != UO_LNot; +} + void UseAnyOfAllOfCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *S = Result.Nodes.getNodeAs<CXXForRangeStmt>("any_of_loop")) { if (!isViableLoop(*S, *Result.Context)) @@ -96,8 +116,13 @@ void UseAnyOfAllOfCheck::check(const MatchFinder::MatchResult &Result) { if (!isViableLoop(*S, *Result.Context)) return; - diag(S->getForLoc(), "replace loop by 'std%select{|::ranges}0::all_of()'") - << getLangOpts().CPlusPlus20; + if (isNoneOfPattern(*S)) + diag(S->getForLoc(), + "replace loop by 'std%select{|::ranges}0::none_of()'") + << getLangOpts().CPlusPlus20; + else + diag(S->getForLoc(), "replace loop by 'std%select{|::ranges}0::all_of()'") + << getLangOpts().CPlusPlus20; } } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 68bab88146241..35423b88aeb8f 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -242,6 +242,10 @@ Changes in existing checks now uses separate note diagnostics for each uninitialized enumerator, making it easier to see which specific enumerators need explicit initialization. +- Improved :doc:`readability-use-anyofallof + <clang-tidy/checks/readability/use-anyofallof>` check by adding support for + ``std::none_of`` suggestions when the loop condition is not negated. + - Improved :doc:`readability-non-const-parameter <clang-tidy/checks/readability/non-const-parameter>` check by avoiding false positives on parameters used in dependent expressions (e.g. inside generic diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst index cfbc551bf07c0..e93620e74074a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst @@ -4,8 +4,9 @@ readability-use-anyofallof ========================== Finds range-based for loops that can be replaced by a call to -``std::any_of`` or ``std::all_of``. In C++20 mode, suggests -``std::ranges::any_of`` or ``std::ranges::all_of``. +``std::any_of``, ``std::all_of``, or ``std::none_of``. In C++20 mode, suggests +``std::ranges::any_of``, ``std::ranges::all_of``, or +``std::ranges::none_of``. Example: diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-anyofallof.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-anyofallof.cpp index 7f8f16488d37a..3fa1512ae65be 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-anyofallof.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-anyofallof.cpp @@ -174,11 +174,20 @@ bool bad_any_of7() { return false; } +bool good_none_of() { + int v[] = {1, 2, 3}; + // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: replace loop by 'std::none_of()' [readability-use-anyofallof] + for (int i : v) + if (i) + return false; + return true; +} + bool good_all_of() { int v[] = {1, 2, 3}; // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: replace loop by 'std::all_of()' [readability-use-anyofallof] for (int i : v) - if (i) + if (!cond(i)) return false; return true; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
