https://github.com/unterumarmung created https://github.com/llvm/llvm-project/pull/196036
Preserve used iterator results for remove, partition, stable_partition, and rotate-style replacements by appending .begin() where the ranges algorithm returns a subrange. Fix #124794 Assisted by Codex. >From 4e67380300697ba93a907b2eb8ae43cb3bb2edf9 Mon Sep 17 00:00:00 2001 From: Daniil Dudkin <[email protected]> Date: Wed, 6 May 2026 00:27:35 +0300 Subject: [PATCH] [clang-tidy] `use-ranges`: preserve remove iterator results Preserve used iterator results for remove, partition, stable_partition, and rotate-style replacements by appending .begin() where the ranges algorithm returns a subrange. Fix #124794 Assisted by Codex. --- .../clang-tidy/modernize/UseRangesCheck.cpp | 12 ++++----- clang-tools-extra/docs/ReleaseNotes.rst | 4 +++ .../modernize/Inputs/use-ranges/fake_std.h | 16 ++++++++++++ .../checkers/modernize/use-ranges.cpp | 25 +++++++++++++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp index 27fc52d95921e..e36ce3adeb15f 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp @@ -37,8 +37,6 @@ static constexpr const char *SingleRangeNames[] = { "replace", "replace_if", "generate", - "remove", - "remove_if", "remove_copy", "remove_copy_if", "unique_copy", @@ -59,9 +57,7 @@ static constexpr const char *SingleRangeNames[] = { "shift_left", "shift_right", "is_partitioned", - "partition", "partition_copy", - "stable_partition", "sort", "stable_sort", "is_sorted", @@ -79,7 +75,8 @@ static constexpr const char *SingleRangeNames[] = { "destroy", }; -static constexpr const char *SingleRangeBeginResultNames[] = {"unique"}; +static constexpr const char *SingleRangeBeginResultNames[] = { + "remove", "remove_if", "stable_partition", "partition", "unique"}; static constexpr const char *TwoRangeNames[] = { "equal", @@ -97,9 +94,11 @@ static constexpr const char *TwoRangeNames[] = { "is_permutation", }; -static constexpr const char *SinglePivotRangeNames[] = {"rotate", "rotate_copy", +static constexpr const char *SinglePivotRangeNames[] = {"rotate_copy", "inplace_merge"}; +static constexpr const char *SinglePivotRangeBeginResultNames[] = {"rotate"}; + namespace { class StdReplacer : public utils::UseRangesCheck::Replacer { public: @@ -176,6 +175,7 @@ utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const { {SingleRangeFunc, SingleRangeBeginResultNames, BeginResultPolicy}, {TwoRangeFunc, TwoRangeNames, DefaultPolicy}, {SinglePivotFunc, SinglePivotRangeNames, DefaultPolicy}, + {SinglePivotFunc, SinglePivotRangeBeginResultNames, BeginResultPolicy}, }; SmallString<64> Buff; for (const auto &[Signatures, Values, Policy] : AlgorithmNames) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 62aada7cf3a82..9742b71df4e64 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -438,6 +438,10 @@ Changes in existing checks - Preserved used iterator results when replacing ``std::unique`` calls with ``std::ranges::unique``. + - Preserved used iterator results when replacing ``std::remove``, + ``std::remove_if``, ``std::partition``, ``std::stable_partition``, and + ``std::rotate`` calls with their ``std::ranges`` counterparts. + - Improved :doc:`modernize-use-std-format <clang-tidy/checks/modernize/use-std-format>` check: diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/use-ranges/fake_std.h b/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/use-ranges/fake_std.h index 648a399f9fcff..23ca215268c0c 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/use-ranges/fake_std.h +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/use-ranges/fake_std.h @@ -92,6 +92,22 @@ void iota(ForwardIt first, ForwardIt last, T value); template <class ForwardIt> ForwardIt unique(ForwardIt first, ForwardIt last); +template <class ForwardIt, class T> +ForwardIt remove(ForwardIt first, ForwardIt last, const T &value); +template <class ForwardIt, class UnaryPred> +ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPred pred) { + return first; +} + +template <class ForwardIt, class UnaryPred> +ForwardIt partition(ForwardIt first, ForwardIt last, UnaryPred pred) { + return first; +} +template <class BidirIt, class UnaryPred> +BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPred pred) { + return first; +} + template <class ForwardIt> ForwardIt rotate(ForwardIt first, ForwardIt middle, ForwardIt last); } // namespace _V1 diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp index be293e19a65a6..c48db04c483b8 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp @@ -55,6 +55,27 @@ void Positives() { // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm // CHECK-FIXES: std::ranges::unique(I); + I.erase(std::remove(I.begin(), I.end(), 0), I.end()); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use a ranges version of this algorithm + // CHECK-FIXES: I.erase(std::ranges::remove(I, 0).begin(), I.end()); + + I.erase(std::remove_if(I.begin(), I.end(), [](int N) { return N == 0; }), + I.end()); + // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use a ranges version of this algorithm + // CHECK-FIXES: I.erase(std::ranges::remove_if(I, [](int N) { return N == 0; }).begin(), + + auto PartitionPoint = + std::partition(I.begin(), I.end(), [](int N) { return N == 0; }); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use a ranges version of this algorithm + // CHECK-FIXES: auto PartitionPoint = + // CHECK-FIXES-NEXT: std::ranges::partition(I, [](int N) { return N == 0; }).begin(); + + auto StablePartitionPoint = + std::stable_partition(I.begin(), I.end(), [](int N) { return N == 0; }); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use a ranges version of this algorithm + // CHECK-FIXES: auto StablePartitionPoint = + // CHECK-FIXES-NEXT: std::ranges::stable_partition(I, [](int N) { return N == 0; }).begin(); + std::includes(I.begin(), I.end(), I.begin(), I.end()); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm // CHECK-FIXES: std::ranges::includes(I, I); @@ -83,6 +104,10 @@ void Positives() { // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm // CHECK-FIXES: std::ranges::rotate(I, I.begin() + 2); + auto RotatePoint = std::rotate(I.begin(), I.begin() + 2, I.end()); + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use a ranges version of this algorithm + // CHECK-FIXES: auto RotatePoint = std::ranges::rotate(I, I.begin() + 2).begin(); + using std::find; namespace my_std = std; _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
