https://github.com/denzor200 updated 
https://github.com/llvm/llvm-project/pull/171666

>From 8a87ecbc298fbc62d8b0d82d677a87ac074ea6c7 Mon Sep 17 00:00:00 2001
From: denzor200 <[email protected]>
Date: Wed, 10 Dec 2025 21:12:34 +0300
Subject: [PATCH 1/2] Add llvm::search and llvm::adjacent_find

---
 .../clang-tidy/llvm/UseRangesCheck.cpp        |   5 +-
 llvm/include/llvm/ADT/STLExtras.h             |  27 +++
 llvm/unittests/ADT/STLExtrasTest.cpp          | 156 ++++++++++++++++++
 3 files changed, 186 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
index 2c7a644b7a793..420cf63c033a1 100644
--- a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
@@ -69,11 +69,12 @@ utils::UseRangesCheck::ReplacerMap 
UseRangesCheck::getReplacerMap() const {
                 "is_sorted",   "min_element",
                 "max_element", "binary_search",
                 "lower_bound", "upper_bound",
-                "unique",      "uninitialized_copy"});
+                "unique",      "uninitialized_copy",
+                "adjacent_find"});
 
   // Two range algorithms
   AddStdToLLVM(llvm::makeIntrusiveRefCnt<StdToLLVMReplacer>(TwoSig),
-               {"equal", "mismatch", "includes"});
+               {"equal", "mismatch", "includes", "search"});
 
   return Results;
 }
diff --git a/llvm/include/llvm/ADT/STLExtras.h 
b/llvm/include/llvm/ADT/STLExtras.h
index af0e4a36be1b1..560edbee5ac1c 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1778,6 +1778,33 @@ OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate 
P) {
   return std::copy_if(adl_begin(Range), adl_end(Range), Out, P);
 }
 
+/// Wrapper for std::search.
+template <typename R1, typename R2>
+auto search(R1 &&Range1, R2 &&Range2) {
+  return std::search(adl_begin(Range1), adl_end(Range1), adl_begin(Range2),
+                     adl_end(Range2));
+}
+
+/// Wrapper for std::search.
+template <typename R1, typename R2, typename BinaryPredicate>
+auto search(R1 &&Range1, R2 &&Range2, BinaryPredicate P) {
+  return std::search(adl_begin(Range1), adl_end(Range1), adl_begin(Range2),
+                     adl_end(Range2), P);
+}
+
+/// Wrapper for std::adjacent_find.
+template <typename R>
+auto adjacent_find(R &&Range) {
+  return std::adjacent_find(adl_begin(Range), adl_end(Range));
+}
+
+/// Wrapper for std::adjacent_find.
+template <typename R, typename BinaryPredicate>
+auto adjacent_find(R &&Range, BinaryPredicate P) {
+  return std::adjacent_find(adl_begin(Range), adl_end(Range),
+                            P);
+}
+
 /// Return the single value in \p Range that satisfies
 /// \p P(<member of \p Range> *, AllowRepeats)->T * returning nullptr
 /// when no values or multiple values were found.
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp 
b/llvm/unittests/ADT/STLExtrasTest.cpp
index 85567775e4ebd..73127bf9cf64c 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -1699,4 +1699,160 @@ struct Bar {};
 static_assert(is_incomplete_v<Foo>, "Foo is incomplete");
 static_assert(!is_incomplete_v<Bar>, "Bar is defined");
 
+TEST(STLExtrasTest, Search) {
+  // Test finding a subsequence in the middle
+  std::vector<int> Haystack = {1, 2, 3, 4, 5, 6, 7, 8};
+  std::vector<int> Needle = {4, 5, 6};
+  auto It = llvm::search(Haystack, Needle);
+  EXPECT_NE(It, Haystack.end());
+  EXPECT_EQ(It, Haystack.begin() + 3);
+  EXPECT_THAT(std::vector<int>(It, It + 3), ElementsAre(4, 5, 6));
+
+  // Test finding at the beginning
+  std::vector<int> Needle2 = {1, 2, 3};
+  auto It2 = llvm::search(Haystack, Needle2);
+  EXPECT_NE(It2, Haystack.end());
+  EXPECT_EQ(It2, Haystack.begin());
+  EXPECT_THAT(std::vector<int>(It2, It2 + 3), ElementsAre(1, 2, 3));
+
+  // Test finding at the end
+  std::vector<int> Needle3 = {6, 7, 8};
+  auto It3 = llvm::search(Haystack, Needle3);
+  EXPECT_NE(It3, Haystack.end());
+  EXPECT_EQ(It3, Haystack.begin() + 5);
+  EXPECT_THAT(std::vector<int>(It3, It3 + 3), ElementsAre(6, 7, 8));
+
+  // Test not finding a subsequence
+  std::vector<int> Needle4 = {9, 10, 11};
+  auto It4 = llvm::search(Haystack, Needle4);
+  EXPECT_EQ(It4, Haystack.end());
+
+  // Test with empty needle (should find at beginning)
+  std::vector<int> EmptyNeedle;
+  auto It5 = llvm::search(Haystack, EmptyNeedle);
+  EXPECT_NE(It5, Haystack.end());
+  EXPECT_EQ(It5, Haystack.begin());
+
+  // Test with empty haystack
+  std::vector<int> EmptyHaystack;
+  auto It6 = llvm::search(EmptyHaystack, Needle);
+  EXPECT_EQ(It6, EmptyHaystack.end());
+  // Test with both empty
+  auto It7 = llvm::search(EmptyHaystack, EmptyNeedle);
+  EXPECT_EQ(It7, EmptyHaystack.end());
+  EXPECT_EQ(It7, EmptyHaystack.begin());
+
+  // Test with predicate version
+  std::vector<int> Haystack2 = {10, 20, 30, 40, 50};
+  std::vector<int> Needle5 = {20, 30};
+  std::vector<int> Needle6 = {200, 300};
+  auto It8 = llvm::search(Haystack2, Needle5,
+                          [](int a, int b) { return a == b; });
+  EXPECT_NE(It8, Haystack2.end());
+  EXPECT_EQ(It8, Haystack2.begin() + 1);
+
+  // Test with predicate that doesn't match
+  auto It9 = llvm::search(Haystack2, Needle6,
+                          [](int a, int b) { return a == b; });
+  EXPECT_EQ(It9, Haystack2.end());
+
+  // Test with StringRef
+  StringRef Str = "Hello, World!";
+  StringRef Sub = "World";
+  auto It10 = llvm::search(Str, Sub);
+  EXPECT_NE(It10, Str.end());
+  EXPECT_EQ(*It10, 'W');
+
+  // Test with ArrayRef
+  ArrayRef<int> ArrRef = Haystack;
+  ArrayRef<int> NeedleRef = Needle;
+  auto It11 = llvm::search(ArrRef, NeedleRef);
+  EXPECT_NE(It11, ArrRef.end());
+  EXPECT_EQ(It11, ArrRef.begin() + 3);
+}
+
+TEST(STLExtrasTest, AdjacentFind) {
+  // Test finding adjacent equal elements
+  std::vector<int> V = {1, 2, 3, 3, 4, 5};
+  auto It = llvm::adjacent_find(V);
+  EXPECT_NE(It, V.end());
+  EXPECT_EQ(It, V.begin() + 2);
+  EXPECT_EQ(*It, 3);
+  EXPECT_EQ(*(It + 1), 3);
+
+  // Test not finding adjacent equal elements
+  std::vector<int> V2 = {1, 2, 3, 4, 5};
+  auto It2 = llvm::adjacent_find(V2);
+  EXPECT_EQ(It2, V2.end());
+
+  // Test finding at the beginning
+  std::vector<int> V3 = {1, 1, 2, 3, 4};
+  auto It3 = llvm::adjacent_find(V3);
+  EXPECT_NE(It3, V3.end());
+  EXPECT_EQ(It3, V3.begin());
+  EXPECT_EQ(*It3, 1);
+  EXPECT_EQ(*(It3 + 1), 1);
+
+  // Test finding at the end
+  std::vector<int> V4 = {1, 2, 3, 4, 5, 5};
+  auto It4 = llvm::adjacent_find(V4);
+  EXPECT_NE(It4, V4.end());
+  EXPECT_EQ(It4, V4.begin() + 4);
+  EXPECT_EQ(*It4, 5);
+  EXPECT_EQ(*(It4 + 1), 5);
+
+  // Test with empty range
+  std::vector<int> Empty;
+  auto It5 = llvm::adjacent_find(Empty);
+  EXPECT_EQ(It5, Empty.end());
+
+  // Test with single element
+  std::vector<int> Single = {42};
+  auto It6 = llvm::adjacent_find(Single);
+  EXPECT_EQ(It6, Single.end());
+
+  // Test with predicate version - finding adjacent elements that satisfy 
predicate
+  std::vector<int> V5 = {1, 2, 4, 3, 5, 6};
+  auto It7 = llvm::adjacent_find(V5, [](int a, int b) { return a > b; });
+  EXPECT_NE(It7, V5.end());
+  EXPECT_EQ(It7, V5.begin() + 2);
+  EXPECT_EQ(*It7, 4);
+  EXPECT_EQ(*(It7 + 1), 3);
+
+  // Test with predicate that doesn't match
+  std::vector<int> V6 = {1, 2, 3, 4, 5};
+  auto It8 = llvm::adjacent_find(V6, [](int a, int b) { return a > b; });
+  EXPECT_EQ(It8, V6.end());
+
+  // Test with predicate finding equal elements
+  std::vector<int> V7 = {1, 2, 3, 3, 4};
+  auto It9 = llvm::adjacent_find(V7, [](int a, int b) { return a == b; });
+  EXPECT_NE(It9, V7.end());
+  EXPECT_EQ(It9, V7.begin() + 2);
+
+  // Test with StringRef
+  StringRef Str = "Helo";
+  auto It10 = llvm::adjacent_find(Str);
+  EXPECT_EQ(It10, Str.end());
+
+  StringRef Str2 = "Helllo";
+  auto It11 = llvm::adjacent_find(Str2);
+  EXPECT_NE(It11, Str2.end());
+  EXPECT_EQ(*It11, 'l');
+  EXPECT_EQ(*(It11 + 1), 'l');
+
+  // Test with ArrayRef
+  ArrayRef<int> ArrRef = V;
+  auto It12 = llvm::adjacent_find(ArrRef);
+  EXPECT_NE(It12, ArrRef.end());
+  EXPECT_EQ(It12, ArrRef.begin() + 2);
+
+  // Test with list (non-random access iterator)
+  std::list<int> L = {1, 2, 3, 3, 4, 5};
+  auto It13 = llvm::adjacent_find(L);
+  EXPECT_NE(It13, L.end());
+  EXPECT_EQ(*It13, 3);
+  EXPECT_EQ(*std::next(It13), 3);
+}
+
 } // namespace

>From cd55badfb2f491a4621776a2ba1b3eece7d27d81 Mon Sep 17 00:00:00 2001
From: denzor200 <[email protected]>
Date: Wed, 10 Dec 2025 22:08:53 +0300
Subject: [PATCH 2/2] format

---
 .../clang-tidy/llvm/UseRangesCheck.cpp        | 26 +++++++++----------
 llvm/include/llvm/ADT/STLExtras.h             |  9 +++----
 llvm/unittests/ADT/STLExtrasTest.cpp          | 11 ++++----
 3 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp 
b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
index 420cf63c033a1..5e7392b09fb33 100644
--- a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp
@@ -57,19 +57,19 @@ utils::UseRangesCheck::ReplacerMap 
UseRangesCheck::getReplacerMap() const {
 
   // 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",
+               {"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
diff --git a/llvm/include/llvm/ADT/STLExtras.h 
b/llvm/include/llvm/ADT/STLExtras.h
index 560edbee5ac1c..9b358b0ac39f6 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1779,8 +1779,7 @@ OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate 
P) {
 }
 
 /// Wrapper for std::search.
-template <typename R1, typename R2>
-auto search(R1 &&Range1, R2 &&Range2) {
+template <typename R1, typename R2> auto search(R1 &&Range1, R2 &&Range2) {
   return std::search(adl_begin(Range1), adl_end(Range1), adl_begin(Range2),
                      adl_end(Range2));
 }
@@ -1793,16 +1792,14 @@ auto search(R1 &&Range1, R2 &&Range2, BinaryPredicate 
P) {
 }
 
 /// Wrapper for std::adjacent_find.
-template <typename R>
-auto adjacent_find(R &&Range) {
+template <typename R> auto adjacent_find(R &&Range) {
   return std::adjacent_find(adl_begin(Range), adl_end(Range));
 }
 
 /// Wrapper for std::adjacent_find.
 template <typename R, typename BinaryPredicate>
 auto adjacent_find(R &&Range, BinaryPredicate P) {
-  return std::adjacent_find(adl_begin(Range), adl_end(Range),
-                            P);
+  return std::adjacent_find(adl_begin(Range), adl_end(Range), P);
 }
 
 /// Return the single value in \p Range that satisfies
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp 
b/llvm/unittests/ADT/STLExtrasTest.cpp
index 73127bf9cf64c..e91412f88e315 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -1746,14 +1746,14 @@ TEST(STLExtrasTest, Search) {
   std::vector<int> Haystack2 = {10, 20, 30, 40, 50};
   std::vector<int> Needle5 = {20, 30};
   std::vector<int> Needle6 = {200, 300};
-  auto It8 = llvm::search(Haystack2, Needle5,
-                          [](int a, int b) { return a == b; });
+  auto It8 =
+      llvm::search(Haystack2, Needle5, [](int a, int b) { return a == b; });
   EXPECT_NE(It8, Haystack2.end());
   EXPECT_EQ(It8, Haystack2.begin() + 1);
 
   // Test with predicate that doesn't match
-  auto It9 = llvm::search(Haystack2, Needle6,
-                          [](int a, int b) { return a == b; });
+  auto It9 =
+      llvm::search(Haystack2, Needle6, [](int a, int b) { return a == b; });
   EXPECT_EQ(It9, Haystack2.end());
 
   // Test with StringRef
@@ -1811,7 +1811,8 @@ TEST(STLExtrasTest, AdjacentFind) {
   auto It6 = llvm::adjacent_find(Single);
   EXPECT_EQ(It6, Single.end());
 
-  // Test with predicate version - finding adjacent elements that satisfy 
predicate
+  // Test with predicate version - finding adjacent elements that satisfy
+  // predicate
   std::vector<int> V5 = {1, 2, 4, 3, 5, 6};
   auto It7 = llvm::adjacent_find(V5, [](int a, int b) { return a > b; });
   EXPECT_NE(It7, V5.end());

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to