[clang-tools-extra] [clang-tidy] Add replace_ to llvm-use-ranges (PR #177457)
Jakub Kuderski via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 22 16:59:32 PST 2026
https://github.com/kuhar updated https://github.com/llvm/llvm-project/pull/177457
>From 9f2582dee9857f653fcefd3745e2589b079872d8 Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Thu, 22 Jan 2026 15:28:32 -0500
Subject: [PATCH 1/4] [clang-tidy] Add replace_ to llvm-use-ranges
---
.../clang-tidy/llvm/UseRangesCheck.cpp | 51 ++++++++++++-------
.../clang-tidy/checkers/llvm/use-ranges.cpp | 24 +++++++--
2 files changed, 53 insertions(+), 22 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
index 0d09210c86df5..06c73feba9dd1 100644
--- a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
@@ -50,28 +50,43 @@ utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const {
const auto AddStdToLLVM =
[&Results](llvm::IntrusiveRefCntPtr<Replacer> Replacer,
std::initializer_list<StringRef> Names) {
- for (const auto &Name : Names)
+ for (StringRef Name : Names)
Results.try_emplace(("::std::" + Name).str(), Replacer);
};
- // Single range algorithms
+ // Single range algorithms.
AddStdToLLVM(llvm::makeIntrusiveRefCnt<StdToLLVMReplacer>(SingleSig),
- {"all_of", "any_of",
- "none_of", "for_each",
- "find", "find_if",
- "find_if_not", "fill",
- "count", "count_if",
- "copy", "copy_if",
- "transform", "replace",
- "remove_if", "stable_sort",
- "partition", "partition_point",
- "is_sorted", "min_element",
- "max_element", "binary_search",
- "lower_bound", "upper_bound",
- "unique", "uninitialized_copy",
- "adjacent_find"});
-
- // Two range algorithms
+ {"adjacent_find",
+ "all_of",
+ "any_of",
+ "binary_search",
+ "copy",
+ "copy_if",
+ "count",
+ "count_if",
+ "fill",
+ "find",
+ "find_if",
+ "find_if_not",
+ "for_each",
+ "is_sorted",
+ "lower_bound",
+ "max_element",
+ "min_element",
+ "none_of",
+ "partition",
+ "partition_point",
+ "remove_if",
+ "replace",
+ "replace_copy",
+ "replace_copy_if",
+ "stable_sort",
+ "transform",
+ "uninitialized_copy",
+ "unique",
+ "upper_bound"});
+
+ // Two range algorithms.
AddStdToLLVM(llvm::makeIntrusiveRefCnt<StdToLLVMReplacer>(TwoSig),
{"equal", "mismatch", "includes", "search"});
diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp
index 9a52cdae2c2bc..58cdeb440eaa3 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp
@@ -66,6 +66,14 @@ bool is_sorted(ForwardIt first, ForwardIt last);
template <class InputIt1, class InputIt2>
bool includes(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2);
+template <class InputIt, class OutputIt, class T>
+OutputIt replace_copy(InputIt first, InputIt last, OutputIt d_first,
+ const T& old_value, const T& new_value);
+
+template <class InputIt, class OutputIt, class UnaryPredicate, class T>
+OutputIt replace_copy_if(InputIt first, InputIt last, OutputIt d_first,
+ UnaryPredicate p, const T& new_value);
+
} // namespace std
bool is_even(int x);
@@ -74,7 +82,7 @@ void double_ref(int& x);
void test_positive() {
std::vector<int> vec;
int arr[5] = {1, 2, 3, 4, 5};
-
+
auto it1 = std::find(vec.begin(), vec.end(), 3);
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use an LLVM range-based algorithm
// CHECK-FIXES: auto it1 = llvm::find(vec, 3);
@@ -111,7 +119,7 @@ void test_positive() {
std::fill(vec.begin(), vec.end(), 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use an LLVM range-based algorithm
// CHECK-FIXES: llvm::fill(vec, 0);
-
+
auto last = std::unique(vec.begin(), vec.end());
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use an LLVM range-based algorithm
// CHECK-FIXES: auto last = llvm::unique(vec);
@@ -123,18 +131,26 @@ void test_positive() {
std::includes(vec.begin(), vec.end(), std::begin(arr), std::end(arr));
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use an LLVM range-based algorithm
// CHECK-FIXES: llvm::includes(vec, arr);
+
+ std::replace_copy(vec.begin(), vec.end(), vec2.begin(), 1, 2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use an LLVM range-based algorithm
+ // CHECK-FIXES: llvm::replace_copy(vec, vec2.begin(), 1, 2);
+
+ std::replace_copy_if(vec.begin(), vec.end(), vec2.begin(), is_even, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use an LLVM range-based algorithm
+ // CHECK-FIXES: llvm::replace_copy_if(vec, vec2.begin(), is_even, 0);
}
void test_negative() {
std::vector<int> v;
-
+
// can not use `llvm::sort` because of potential different ordering from `std::sort`.
std::sort(v.begin(), v.end());
//non-begin/end iterators
auto it1 = std::find(v.begin() + 1, v.end(), 2);
auto it2 = std::find(v.begin(), v.end() - 1, 2);
-
+
// Using different containers (3-arg equal)
std::vector<int> v2;
bool eq = std::equal(v.begin(), v.end(), v2.begin());
>From 2402b7ce5cfb40df38798f2aea767390ddc137c6 Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Thu, 22 Jan 2026 19:31:20 -0500
Subject: [PATCH 2/4] Add const
---
clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
index 06c73feba9dd1..70d8e75405e91 100644
--- a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
@@ -50,7 +50,7 @@ utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const {
const auto AddStdToLLVM =
[&Results](llvm::IntrusiveRefCntPtr<Replacer> Replacer,
std::initializer_list<StringRef> Names) {
- for (StringRef Name : Names)
+ for (const StringRef Name : Names)
Results.try_emplace(("::std::" + Name).str(), Replacer);
};
>From 9b5b284266cfcd9fad793c8f099101c7baf0ae45 Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Thu, 22 Jan 2026 19:38:37 -0500
Subject: [PATCH 3/4] Update docs
---
clang-tools-extra/docs/ReleaseNotes.rst | 4 ++++
.../docs/clang-tidy/checks/llvm/use-ranges.rst | 14 +++++++++-----
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 5af634c77f54d..e8e08080b8525 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -137,6 +137,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:`llvm-use-ranges
+ <clang-tidy/checks/llvm/use-ranges>` check by adding support for the following
+ algorithms: ``std::replace_copy`` and ``std::replace_copy_if``.
+
Removed checks
^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst
index 1a0454703822e..6ef7f476ba2ff 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst
@@ -27,18 +27,19 @@ Supported algorithms
Calls to the following STL algorithms are checked:
+``std::adjacent_find``,
``std::all_of``,
``std::any_of``,
``std::binary_search``,
-``std::copy``,
``std::copy_if``,
-``std::count``,
+``std::copy``,
``std::count_if``,
+``std::count``,
``std::equal``,
``std::fill``,
-``std::find``,
-``std::find_if``,
``std::find_if_not``,
+``std::find_if``,
+``std::find``,
``std::for_each``,
``std::includes``,
``std::is_sorted``,
@@ -47,10 +48,13 @@ Calls to the following STL algorithms are checked:
``std::min_element``,
``std::mismatch``,
``std::none_of``,
-``std::partition``,
``std::partition_point``,
+``std::partition``,
``std::remove_if``,
+``std::replace_copy_if``,
+``std::replace_copy``,
``std::replace``,
+``std::search``,
``std::stable_sort``,
``std::transform``,
``std::uninitialized_copy``,
>From 120ecb4905293110b45d30c3e3ff02fb1e07794a Mon Sep 17 00:00:00 2001
From: Jakub Kuderski <jakub at nod-labs.com>
Date: Thu, 22 Jan 2026 19:59:09 -0500
Subject: [PATCH 4/4] Reorder
---
clang-tools-extra/docs/ReleaseNotes.rst | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index e8e08080b8525..099a9fa9c2a19 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -114,6 +114,10 @@ Changes in existing checks
``std::get_temporary_buffer`` to the default list of unsafe functions. (This
function is unsafe, useless, deprecated in C++17 and removed in C++20).
+- Improved :doc:`llvm-use-ranges
+ <clang-tidy/checks/llvm/use-ranges>` check by adding support for the following
+ algorithms: ``std::replace_copy`` and ``std::replace_copy_if``.
+
- Improved :doc:`misc-const-correctness
<clang-tidy/checks/misc/const-correctness>` check:
@@ -137,10 +141,6 @@ 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:`llvm-use-ranges
- <clang-tidy/checks/llvm/use-ranges>` check by adding support for the following
- algorithms: ``std::replace_copy`` and ``std::replace_copy_if``.
-
Removed checks
^^^^^^^^^^^^^^
More information about the cfe-commits
mailing list