[llvm-branch-commits] [clang-tools-extra] [clang-tidy] `use-ranges`: preserve remove iterator results (PR #196036)
Daniil Dudkin via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed May 6 03:00:54 PDT 2026
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 <unterumarmung at yandex.ru>
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;
More information about the llvm-branch-commits
mailing list