[libcxx-commits] [libcxx] 971e9c8 - [libc++] Implement std::boyer_moore{, _horspool}_searcher

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jun 17 10:09:52 PDT 2022


Author: Nikolas Klauser
Date: 2022-06-17T19:09:40+02:00
New Revision: 971e9c80e9660285e0620682f4e470a41967391f

URL: https://github.com/llvm/llvm-project/commit/971e9c80e9660285e0620682f4e470a41967391f
DIFF: https://github.com/llvm/llvm-project/commit/971e9c80e9660285e0620682f4e470a41967391f.diff

LOG: [libc++] Implement std::boyer_moore{, _horspool}_searcher

This mostly copys the `<experimental/functional>` stuff and updates the code to current libc++ style.

Reviewed By: ldionne, #libc

Spies: nlopes, adamdebreceni, arichardson, libcxx-commits, mgorny

Differential Revision: https://reviews.llvm.org/D121074

Added: 
    libcxx/include/__functional/boyer_moore_searcher.h

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/docs/ReleaseNotes.rst
    libcxx/include/CMakeLists.txt
    libcxx/include/__config
    libcxx/include/__memory/construct_at.h
    libcxx/include/__memory/shared_ptr.h
    libcxx/include/__memory/uninitialized_algorithms.h
    libcxx/include/__type_traits/is_bounded_array.h
    libcxx/include/__type_traits/is_unbounded_array.h
    libcxx/include/experimental/functional
    libcxx/include/functional
    libcxx/include/module.modulemap.in
    libcxx/include/version
    libcxx/test/libcxx/private_headers.verify.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/default.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pred.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/pred.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/default.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pred.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/pred.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pred.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pass.cpp
    libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pred.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bm/default.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pred.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bm/pred.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/default.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pred.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/pred.pass.cpp
    libcxx/test/std/utilities/optional/optional.hash/enabled_hash.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 481507750b735..020ef2aae7448 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -84,7 +84,7 @@ Status
     ------------------------------------------------- -----------------
     ``__cpp_lib_bool_constant``                       ``201505L``
     ------------------------------------------------- -----------------
-    ``__cpp_lib_boyer_moore_searcher``                *unimplemented*
+    ``__cpp_lib_boyer_moore_searcher``                ``201603L``
     ------------------------------------------------- -----------------
     ``__cpp_lib_byte``                                ``201603L``
     ------------------------------------------------- -----------------

diff  --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index d2084aeab7da4..ba780d8ae9d95 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -142,6 +142,10 @@ API Changes
   ``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS``, this ensures that the members of
   ``allocator<void>`` removed in C++20 can be accessed.
 
+- The experimental versions of ``boyer_moore_searcher`` and ``boyer_moore_horspool_searcher``
+  will be removed in LLVM 17. You can disable the deprecation warnings by defining
+  ``_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS``.
+
 ABI Changes
 -----------
 

diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index c47323829133e..a9f3387e1f998 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -258,6 +258,7 @@ set(files
   __functional/bind_front.h
   __functional/binder1st.h
   __functional/binder2nd.h
+  __functional/boyer_moore_searcher.h
   __functional/compose.h
   __functional/default_searcher.h
   __functional/function.h

diff  --git a/libcxx/include/__config b/libcxx/include/__config
index e9d24efd93f7b..bb20b2c956ea9 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -789,13 +789,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
 #  if !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS)
 #    if __has_attribute(deprecated)
 #      define _LIBCPP_DEPRECATED __attribute__((deprecated))
+#      define _LIBCPP_DEPRECATED_(m) __attribute__((deprected(m)))
 #    elif _LIBCPP_STD_VER > 11
 #      define _LIBCPP_DEPRECATED [[deprecated]]
+#      define _LIBCPP_DEPRECATED_(m) [[deprecated(m)]]
 #    else
 #      define _LIBCPP_DEPRECATED
+#      define _LIBCPP_DEPRECATED_(m)
 #    endif
 #  else
 #    define _LIBCPP_DEPRECATED
+#    define _LIBCPP_DEPRECATED_(m)
 #  endif
 
 #  if !defined(_LIBCPP_CXX03_LANG)
@@ -895,8 +899,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
 #  endif
 
 #  ifndef _LIBCPP_HAS_NO_ASAN
-extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container(const void*, const void*, const void*,
-                                                                           const void*);
+    extern "C" _LIBCPP_FUNC_VIS void
+    __sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*);
 #  endif
 
 // Try to find out if RTTI is disabled.

diff  --git a/libcxx/include/__functional/boyer_moore_searcher.h b/libcxx/include/__functional/boyer_moore_searcher.h
new file mode 100644
index 0000000000000..20e554408ff01
--- /dev/null
+++ b/libcxx/include/__functional/boyer_moore_searcher.h
@@ -0,0 +1,313 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H
+#define _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+#include <__algorithm/fill_n.h>
+#include <__config>
+#include <__functional/hash.h>
+#include <__functional/operations.h>
+#include <__iterator/distance.h>
+#include <__iterator/iterator_traits.h>
+#include <__memory/shared_ptr.h>
+#include <__utility/pair.h>
+#include <array>
+#include <unordered_map>
+#include <vector>
+
+#if _LIBCPP_STD_VER > 14
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Key,
+          class _Value,
+          class _Hash,
+          class _BinaryPredicate,
+          bool /*useArray*/>
+class _BMSkipTable;
+
+// General case for BM data searching; use a map
+template <class _Key,
+          class _Value,
+          class _Hash,
+          class _BinaryPredicate>
+class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, false> {
+private:
+  using value_type = _Value;
+  using key_type = _Key;
+
+  const value_type __default_value_;
+  unordered_map<_Key, _Value, _Hash, _BinaryPredicate> __table_;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI
+  explicit _BMSkipTable(size_t __sz, value_type __default_value, _Hash __hash, _BinaryPredicate __pred)
+      : __default_value_(__default_value),
+        __table_(__sz, __hash, __pred) {}
+
+  _LIBCPP_HIDE_FROM_ABI void insert(const key_type& __key, value_type __val) {
+    __table_[__key] = __val;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI value_type operator[](const key_type& __key) const {
+    auto __it = __table_.find(__key);
+    return __it == __table_.end() ? __default_value_ : __it->second;
+  }
+};
+
+// Special case small numeric values; use an array
+template <class _Key,
+          class _Value,
+          class _Hash,
+          class _BinaryPredicate>
+class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, true> {
+private:
+  using value_type = _Value;
+  using key_type = _Key;
+
+  using unsigned_key_type = make_unsigned_t<key_type>;
+  std::array<value_type, 256> __table_;
+  static_assert(numeric_limits<unsigned_key_type>::max() < 256);
+
+public:
+  _LIBCPP_HIDE_FROM_ABI explicit _BMSkipTable(size_t, value_type __default_value, _Hash, _BinaryPredicate) {
+    std::fill_n(__table_.data(), __table_.size(), __default_value);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI void insert(key_type __key, value_type __val) {
+    __table_[static_cast<unsigned_key_type>(__key)] = __val;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI value_type operator[](key_type __key) const {
+    return __table_[static_cast<unsigned_key_type>(__key)];
+  }
+};
+
+template <class _RandomAccessIterator1,
+          class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
+          class _BinaryPredicate = equal_to<>>
+class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
+private:
+  using 
diff erence_type = typename std::iterator_traits<_RandomAccessIterator1>::
diff erence_type;
+  using value_type = typename std::iterator_traits<_RandomAccessIterator1>::value_type;
+  using __skip_table_type = _BMSkipTable<value_type,
+                                         
diff erence_type,
+                                         _Hash,
+                                         _BinaryPredicate,
+                                         is_integral_v<value_type>
+                                      && sizeof(value_type) == 1
+                                      && is_same_v<_Hash, hash<value_type>>
+                                      && is_same_v<_BinaryPredicate, equal_to<>>>;
+
+public:
+  boyer_moore_searcher(_RandomAccessIterator1 __first,
+                       _RandomAccessIterator1 __last,
+                       _Hash __hash = _Hash(),
+                       _BinaryPredicate __pred = _BinaryPredicate())
+    : __first_(__first),
+      __last_(__last),
+      __pred_(__pred),
+      __pattern_length_(__last - __first),
+      __skip_table_(std::make_shared<__skip_table_type>(__pattern_length_, -1, __hash, __pred_)),
+      __suffix_(std::__allocate_shared_unbounded_array<
diff erence_type[]>(
+          allocator<
diff erence_type>(), __pattern_length_ + 1)) {
+    
diff erence_type __i = 0;
+    while (__first != __last) {
+      __skip_table_->insert(*__first, __i);
+      ++__first;
+      ++__i;
+    }
+    __build_suffix_table(__first_, __last_, __pred_);
+  }
+
+  template <class _RandomAccessIterator2>
+  pair<_RandomAccessIterator2, _RandomAccessIterator2>
+  operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const {
+    static_assert(__is_same_uncvref<typename iterator_traits<_RandomAccessIterator1>::value_type,
+                                    typename iterator_traits<_RandomAccessIterator2>::value_type>::value,
+                  "Corpus and Pattern iterators must point to the same type");
+    if (__first == __last)
+      return std::make_pair(__last, __last);
+    if (__first_ == __last_)
+      return std::make_pair(__first, __first);
+
+    if (__pattern_length_ > (__last - __first))
+      return std::make_pair(__last, __last);
+    return __search(__first, __last);
+  }
+
+private:
+  _RandomAccessIterator1 __first_;
+  _RandomAccessIterator1 __last_;
+  _BinaryPredicate __pred_;
+  
diff erence_type __pattern_length_;
+  shared_ptr<__skip_table_type> __skip_table_;
+  shared_ptr<
diff erence_type[]> __suffix_;
+
+  template <class _RandomAccessIterator2>
+  pair<_RandomAccessIterator2, _RandomAccessIterator2>
+  __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const {
+    _RandomAccessIterator2 __current = __f;
+    const _RandomAccessIterator2 __last = __l - __pattern_length_;
+    const __skip_table_type& __skip_table = *__skip_table_;
+
+    while (__current <= __last) {
+      
diff erence_type __j = __pattern_length_;
+      while (__pred_(__first_[__j - 1], __current[__j - 1])) {
+        --__j;
+        if (__j == 0)
+          return std::make_pair(__current, __current + __pattern_length_);
+      }
+
+      
diff erence_type __k = __skip_table[__current[__j - 1]];
+      
diff erence_type __m = __j - __k - 1;
+      if (__k < __j && __m > __suffix_[__j])
+        __current += __m;
+      else
+        __current += __suffix_[__j];
+    }
+    return std::make_pair(__l, __l);
+  }
+
+  template <class _Iterator, class _Container>
+  void __compute_bm_prefix(_Iterator __first, _Iterator __last, _BinaryPredicate __pred, _Container& __prefix) {
+    const size_t __count = __last - __first;
+
+    __prefix[0] = 0;
+    size_t __k = 0;
+
+    for (size_t __i = 1; __i != __count; ++__i) {
+      while (__k > 0 && !__pred(__first[__k], __first[__i]))
+        __k = __prefix[__k - 1];
+
+      if (__pred(__first[__k], __first[__i]))
+        ++__k;
+      __prefix[__i] = __k;
+    }
+  }
+
+  void __build_suffix_table(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _BinaryPredicate __pred) {
+    const size_t __count = __last - __first;
+
+    if (__count == 0)
+      return;
+
+    vector<
diff erence_type> __scratch(__count);
+
+    __compute_bm_prefix(__first, __last, __pred, __scratch);
+    for (size_t __i = 0; __i <= __count; ++__i)
+      __suffix_[__i] = __count - __scratch[__count - 1];
+
+    using _ReverseIter = reverse_iterator<_RandomAccessIterator1>;
+    __compute_bm_prefix(_ReverseIter(__last), _ReverseIter(__first), __pred, __scratch);
+
+    for (size_t __i = 0; __i != __count; ++__i) {
+      const size_t __j = __count - __scratch[__i];
+      const 
diff erence_type __k = __i - __scratch[__i] + 1;
+
+      if (__suffix_[__j] > __k)
+        __suffix_[__j] = __k;
+    }
+  }
+};
+
+template <class _RandomAccessIterator1,
+          class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
+          class _BinaryPredicate = equal_to<>>
+class _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
+private:
+  using 
diff erence_type = typename iterator_traits<_RandomAccessIterator1>::
diff erence_type;
+  using value_type = typename iterator_traits<_RandomAccessIterator1>::value_type;
+  using __skip_table_type = _BMSkipTable<value_type,
+                                         
diff erence_type,
+                                         _Hash,
+                                         _BinaryPredicate,
+                                         is_integral_v<value_type>
+                                      && sizeof(value_type) == 1
+                                      && is_same_v<_Hash, hash<value_type>>
+                                      && is_same_v<_BinaryPredicate, equal_to<>>>;
+public:
+  boyer_moore_horspool_searcher(_RandomAccessIterator1 __first,
+                                _RandomAccessIterator1 __last,
+                                _Hash __hash = _Hash(),
+                                _BinaryPredicate __pred = _BinaryPredicate())
+    : __first_(__first),
+      __last_(__last),
+      __pred_(__pred),
+      __pattern_length_(__last - __first),
+      __skip_table_(std::make_shared<__skip_table_type>(__pattern_length_, __pattern_length_, __hash, __pred_)) {
+    if (__first == __last)
+      return;
+    --__last;
+    
diff erence_type __i = 0;
+    while (__first != __last) {
+      __skip_table_->insert(*__first, __pattern_length_ - 1 - __i);
+      ++__first;
+      ++__i;
+    }
+  }
+
+  template <class _RandomAccessIterator2>
+  pair<_RandomAccessIterator2, _RandomAccessIterator2>
+  operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const {
+    static_assert(__is_same_uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type,
+                                    typename std::iterator_traits<_RandomAccessIterator2>::value_type>::value,
+                  "Corpus and Pattern iterators must point to the same type");
+    if (__first == __last)
+      return std::make_pair(__last, __last);
+    if (__first_ == __last_)
+      return std::make_pair(__first, __first);
+
+    if (__pattern_length_ > __last - __first)
+      return std::make_pair(__last, __last);
+
+    return __search(__first, __last);
+  }
+
+private:
+  _RandomAccessIterator1 __first_;
+  _RandomAccessIterator1 __last_;
+  _BinaryPredicate __pred_;
+  
diff erence_type __pattern_length_;
+  shared_ptr<__skip_table_type> __skip_table_;
+
+  template <class _RandomAccessIterator2>
+  pair<_RandomAccessIterator2, _RandomAccessIterator2>
+  __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const {
+    _RandomAccessIterator2 __current = __f;
+    const _RandomAccessIterator2 __last = __l - __pattern_length_;
+    const __skip_table_type& __skip_table = *__skip_table_;
+
+    while (__current <= __last) {
+      
diff erence_type __j = __pattern_length_;
+      while (__pred_(__first_[__j - 1], __current[__j - 1])) {
+        --__j;
+        if (__j == 0)
+          return std::make_pair(__current, __current + __pattern_length_);
+      }
+      __current += __skip_table[__current[__pattern_length_ - 1]];
+    }
+    return std::make_pair(__l, __l);
+  }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP_STD_VER > 14
+
+#endif // _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H

diff  --git a/libcxx/include/__memory/construct_at.h b/libcxx/include/__memory/construct_at.h
index bcca0fdb18edc..bfa20a149d51c 100644
--- a/libcxx/include/__memory/construct_at.h
+++ b/libcxx/include/__memory/construct_at.h
@@ -29,17 +29,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER > 17
 
-template<class _Tp, class ..._Args, class = decltype(
-    ::new (declval<void*>()) _Tp(declval<_Args>()...)
-)>
-_LIBCPP_HIDE_FROM_ABI
-constexpr _Tp* construct_at(_Tp* __location, _Args&& ...__args) {
-    _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at");
-    return ::new (_VSTD::__voidify(*__location)) _Tp(_VSTD::forward<_Args>(__args)...);
+template <class _Tp, class... _Args, class = decltype(::new(declval<void*>()) _Tp(declval<_Args>()...))>
+_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) {
+  _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at");
+  return ::new (_VSTD::__voidify(*__location)) _Tp(_VSTD::forward<_Args>(__args)...);
 }
 
 #endif
 
+template <class _Tp, class... _Args, class = decltype(::new(declval<void*>()) _Tp(declval<_Args>()...))>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __construct_at(_Tp* __location, _Args&&... __args) {
+#if _LIBCPP_STD_VER > 17
+  return std::construct_at(__location, std::forward<_Args>(__args)...);
+#else
+  return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...);
+#endif
+}
+
 // destroy_at
 
 // The internal functions are available regardless of the language version (with the exception of the `__destroy_at`

diff  --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index c1f6248523197..25aa9bada5344 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -964,7 +964,7 @@ shared_ptr<_Tp> make_shared(_Args&& ...__args)
     return _VSTD::allocate_shared<_Tp>(allocator<_Tp>(), _VSTD::forward<_Args>(__args)...);
 }
 
-#if _LIBCPP_STD_VER > 17
+#if _LIBCPP_STD_VER > 14
 
 template <size_t _Alignment>
 struct __sp_aligned_storage {
@@ -1042,7 +1042,7 @@ template<class _Array, class _Alloc, class... _Arg>
 _LIBCPP_HIDE_FROM_ABI
 shared_ptr<_Array> __allocate_shared_unbounded_array(const _Alloc& __a, size_t __n, _Arg&& ...__arg)
 {
-    static_assert(is_unbounded_array_v<_Array>);
+    static_assert(__libcpp_is_unbounded_array<_Array>::value);
     // We compute the number of bytes necessary to hold the control block and the
     // array elements. Then, we allocate an array of properly-aligned dummy structs
     // large enough to hold the control block and array. This allows shifting the
@@ -1052,7 +1052,7 @@ shared_ptr<_Array> __allocate_shared_unbounded_array(const _Alloc& __a, size_t _
     using _StorageAlloc = __allocator_traits_rebind_t<_Alloc, _AlignedStorage>;
     __allocation_guard<_StorageAlloc> __guard(__a, _ControlBlock::__bytes_for(__n) / sizeof(_AlignedStorage));
     _ControlBlock* __control_block = reinterpret_cast<_ControlBlock*>(std::addressof(*__guard.__get()));
-    std::construct_at(__control_block, __a, __n, std::forward<_Arg>(__arg)...);
+    std::__construct_at(__control_block, __a, __n, std::forward<_Arg>(__arg)...);
     __guard.__release_ptr();
     return shared_ptr<_Array>::__create_with_control_block(__control_block->__get_data(), __control_block);
 }
@@ -1105,17 +1105,21 @@ template<class _Array, class _Alloc, class... _Arg>
 _LIBCPP_HIDE_FROM_ABI
 shared_ptr<_Array> __allocate_shared_bounded_array(const _Alloc& __a, _Arg&& ...__arg)
 {
-    static_assert(is_bounded_array_v<_Array>);
+    static_assert(__libcpp_is_bounded_array<_Array>::value);
     using _ControlBlock = __bounded_array_control_block<_Array, _Alloc>;
     using _ControlBlockAlloc = __allocator_traits_rebind_t<_Alloc, _ControlBlock>;
 
     __allocation_guard<_ControlBlockAlloc> __guard(__a, 1);
     _ControlBlock* __control_block = reinterpret_cast<_ControlBlock*>(std::addressof(*__guard.__get()));
-    std::construct_at(__control_block, __a, std::forward<_Arg>(__arg)...);
+    std::__construct_at(__control_block, __a, std::forward<_Arg>(__arg)...);
     __guard.__release_ptr();
     return shared_ptr<_Array>::__create_with_control_block(__control_block->__get_data(), __control_block);
 }
 
+#endif // _LIBCPP_STD_VER > 14
+
+#if _LIBCPP_STD_VER > 17
+
 template<class _Tp, class _Alloc, class = __enable_if_t<is_bounded_array<_Tp>::value>>
 _LIBCPP_HIDE_FROM_ABI
 shared_ptr<_Tp> allocate_shared(const _Alloc& __a)

diff  --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h
index dfdfdf4eddf1d..3a8560f080c69 100644
--- a/libcxx/include/__memory/uninitialized_algorithms.h
+++ b/libcxx/include/__memory/uninitialized_algorithms.h
@@ -347,10 +347,6 @@ uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofir
                                                    __unreachable_sentinel(), __iter_move);
 }
 
-#endif // _LIBCPP_STD_VER > 14
-
-#if _LIBCPP_STD_VER > 17
-
 // Destroys every element in the range [first, last) FROM RIGHT TO LEFT using allocator
 // destruction. If elements are themselves C-style arrays, they are recursively destroyed
 // in the same manner.
@@ -370,7 +366,7 @@ constexpr void __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter
         return;
 
     if constexpr (is_array_v<_ValueType>) {
-        static_assert(!is_unbounded_array_v<_ValueType>,
+        static_assert(!__libcpp_is_unbounded_array<_ValueType>::value,
             "arrays of unbounded arrays don't exist, but if they did we would mess up here");
 
         using _Element = remove_extent_t<_ValueType>;
@@ -494,7 +490,7 @@ constexpr void __uninitialized_allocator_value_construct_n(_Alloc& __alloc, _Bid
     __guard.__complete();
 }
 
-#endif // _LIBCPP_STD_VER > 17
+#endif // _LIBCPP_STD_VER > 14
 
 _LIBCPP_END_NAMESPACE_STD
 

diff  --git a/libcxx/include/__type_traits/is_bounded_array.h b/libcxx/include/__type_traits/is_bounded_array.h
index f6e800d723bd1..27de9dfd38642 100644
--- a/libcxx/include/__type_traits/is_bounded_array.h
+++ b/libcxx/include/__type_traits/is_bounded_array.h
@@ -19,6 +19,9 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+template <class>                 struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array           : false_type {};
+template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array<_Tp[_Np]> : true_type {};
+
 #if _LIBCPP_STD_VER > 17
 
 template <class>                 struct _LIBCPP_TEMPLATE_VIS is_bounded_array           : false_type {};

diff  --git a/libcxx/include/__type_traits/is_unbounded_array.h b/libcxx/include/__type_traits/is_unbounded_array.h
index 9e857533c6fd9..11a12607e1e07 100644
--- a/libcxx/include/__type_traits/is_unbounded_array.h
+++ b/libcxx/include/__type_traits/is_unbounded_array.h
@@ -18,6 +18,9 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+template <class>     struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array        : false_type {};
+template <class _Tp> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array<_Tp[]> : true_type {};
+
 #if _LIBCPP_STD_VER > 17
 
 template <class>     struct _LIBCPP_TEMPLATE_VIS is_unbounded_array        : false_type {};

diff  --git a/libcxx/include/experimental/functional b/libcxx/include/experimental/functional
index 0da5fced22eab..04f195d3cf24b 100644
--- a/libcxx/include/experimental/functional
+++ b/libcxx/include/experimental/functional
@@ -79,10 +79,20 @@ _LIBCPP_PUSH_MACROS
 
 _LIBCPP_BEGIN_NAMESPACE_LFTS
 
+#ifdef _LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
+#  define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER
+#  define _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER
+#  define _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER
+#else
+#  define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_DEPRECATED_("std::exprerimental::default_searcher will be removed in LLVM 17. Use std::default_searcher instead")
+#  define _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_DEPRECATED_("std::exprerimental::boyer_moore_searcher will be removed in LLVM 17. Use std::boyer_moore_searcher instead")
+#  define _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_DEPRECATED_("std::exprerimental::boyer_moore_horspool_searcher will be removed in LLVM 17. Use std::boyer_moore_horspool_searcher instead")
+#endif
+
 #if _LIBCPP_STD_VER > 11
 // default searcher
 template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
-class _LIBCPP_TEMPLATE_VIS default_searcher {
+class _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_TEMPLATE_VIS default_searcher {
 public:
     _LIBCPP_INLINE_VISIBILITY
     default_searcher(_ForwardIterator __f, _ForwardIterator __l,
@@ -106,7 +116,7 @@ private:
     };
 
 template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_INLINE_VISIBILITY
 default_searcher<_ForwardIterator, _BinaryPredicate>
 make_default_searcher( _ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate ())
 {
@@ -152,7 +162,7 @@ private:
     typedef _Key   key_type;
 
     typedef typename make_unsigned<key_type>::type unsigned_key_type;
-    typedef std::array<value_type, numeric_limits<unsigned_key_type>::max()> skip_map;
+    typedef std::array<value_type, 256> skip_map;
     skip_map __table;
 
 public:
@@ -179,7 +189,7 @@ public:
 template <class _RandomAccessIterator1,
           class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
           class _BinaryPredicate = equal_to<>>
-class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
+class _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
 private:
     typedef typename std::iterator_traits<_RandomAccessIterator1>::
diff erence_type 
diff erence_type;
     typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type      value_type;
@@ -291,7 +301,7 @@ private:
         vector<
diff erence_type> & __suffix = *__suffix_.get();
         if (__count > 0)
         {
-            vector<value_type> __scratch(__count);
+            vector<
diff erence_type> __scratch(__count);
 
             __compute_bm_prefix(__f, __l, __pred, __scratch);
             for ( size_t __i = 0; __i <= __count; __i++ )
@@ -316,7 +326,7 @@ private:
 template<class _RandomAccessIterator,
          class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
          class _BinaryPredicate = equal_to<>>
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_INLINE_VISIBILITY
 boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
 make_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
                     _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())
@@ -328,7 +338,7 @@ make_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
 template <class _RandomAccessIterator1,
           class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
           class _BinaryPredicate = equal_to<>>
-class _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
+class _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
 private:
     typedef typename std::iterator_traits<_RandomAccessIterator1>::
diff erence_type 
diff erence_type;
     typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type      value_type;
@@ -409,7 +419,7 @@ private:
 template<class _RandomAccessIterator,
          class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>,
          class _BinaryPredicate = equal_to<>>
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_INLINE_VISIBILITY
 boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>
 make_boyer_moore_horspool_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l,
                     _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ())

diff  --git a/libcxx/include/functional b/libcxx/include/functional
index 7430551c65783..dd39e274a56b1 100644
--- a/libcxx/include/functional
+++ b/libcxx/include/functional
@@ -502,6 +502,7 @@ POLICY:  For non-variadic implementations, the number of arguments is limited
 #include <__functional/bind_front.h>
 #include <__functional/binder1st.h>
 #include <__functional/binder2nd.h>
+#include <__functional/boyer_moore_searcher.h>
 #include <__functional/compose.h>
 #include <__functional/default_searcher.h>
 #include <__functional/function.h>

diff  --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 45641e6bac0e4..f0e51fafe49c4 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -624,6 +624,7 @@ module std [system] {
       module bind_front                 { private header "__functional/bind_front.h" }
       module binder1st                  { private header "__functional/binder1st.h" }
       module binder2nd                  { private header "__functional/binder2nd.h" }
+      module boyer_moore_searcher       { private header "__functional/boyer_moore_searcher.h" }
       module compose                    { private header "__functional/compose.h" }
       module default_searcher           { private header "__functional/default_searcher.h" }
       module function                   { private header "__functional/function.h" }

diff  --git a/libcxx/include/version b/libcxx/include/version
index 59c955a672ace..dcebba4d6d50a 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -237,7 +237,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # define __cpp_lib_as_const                             201510L
 # define __cpp_lib_atomic_is_always_lock_free           201603L
 # define __cpp_lib_bool_constant                        201505L
-// # define __cpp_lib_boyer_moore_searcher                 201603L
+# define __cpp_lib_boyer_moore_searcher                 201603L
 # define __cpp_lib_byte                                 201603L
 # define __cpp_lib_chrono                               201611L
 # define __cpp_lib_clamp                                201603L

diff  --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp
index 5829ac98c047b..f0f442bd80b82 100644
--- a/libcxx/test/libcxx/private_headers.verify.cpp
+++ b/libcxx/test/libcxx/private_headers.verify.cpp
@@ -290,6 +290,7 @@ END-SCRIPT
 #include <__functional/bind_front.h> // expected-error@*:* {{use of private header from outside its module: '__functional/bind_front.h'}}
 #include <__functional/binder1st.h> // expected-error@*:* {{use of private header from outside its module: '__functional/binder1st.h'}}
 #include <__functional/binder2nd.h> // expected-error@*:* {{use of private header from outside its module: '__functional/binder2nd.h'}}
+#include <__functional/boyer_moore_searcher.h> // expected-error@*:* {{use of private header from outside its module: '__functional/boyer_moore_searcher.h'}}
 #include <__functional/compose.h> // expected-error@*:* {{use of private header from outside its module: '__functional/compose.h'}}
 #include <__functional/default_searcher.h> // expected-error@*:* {{use of private header from outside its module: '__functional/default_searcher.h'}}
 #include <__functional/function.h> // expected-error@*:* {{use of private header from outside its module: '__functional/function.h'}}

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/default.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/default.pass.cpp
index 7624142ea2e2b..d5acb8f74e747 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/default.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/default.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 
@@ -34,6 +35,7 @@
 #include <experimental/algorithm>
 #include <experimental/functional>
 #include <cassert>
+#include <string>
 
 #include "test_macros.h"
 #include "test_iterators.h"
@@ -122,9 +124,32 @@ test2()
     do_search(Iter1(ij), Iter1(ij+sj), Iter2(ik), Iter2(ik+sk), Iter1(ij+6));
 }
 
+template <class Iter1, class Iter2>
+void test_large_str() {
+    std::vector<signed char> data(257, 'a');
+    data[254] = 'b';
+    data[255] = 'b';
+    data[256] = 'b';
+    const signed char find[] = {'b', 'b', 'b'};
+    do_search(Iter1(data.data()), Iter1(data.data() + data.size()),
+              Iter2(find), Iter2(find + 3),
+              Iter1(data.data() + 254));
+}
+
+void test_custom_pred() {
+    std::string long_string(1024, '0');
+    auto searcher = std::experimental::make_boyer_moore_searcher(std::begin(long_string), std::end(long_string));
+    const char str[] = "1234";
+    auto ret = searcher(std::begin(str), std::end(str));
+    assert(ret.first == std::end(str));
+    assert(ret.second == std::end(str));
+}
+
 int main(int, char**) {
     test<random_access_iterator<const int*>, random_access_iterator<const int*> >();
     test2<random_access_iterator<const char*>, random_access_iterator<const char*> >();
+    test_large_str<random_access_iterator<const signed char*>, random_access_iterator<const signed char*>>();
+    test_custom_pred();
 
   return 0;
 }

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pass.cpp
index b9baba6fdd440..5933b61ed3a0f 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pred.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pred.pass.cpp
index a5d02dd45c52f..ef3315f31a201 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pred.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/hash.pred.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/pred.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/pred.pass.cpp
index 68617ffc776ed..86aa18eebdc3e 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/pred.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore/pred.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/default.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/default.pass.cpp
index a9034f9cc909a..440bc05d90e78 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/default.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/default.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pass.cpp
index fa624c0dcffb7..4677c3a0f9e20 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pred.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pred.pass.cpp
index c7d6bcd1ec52d..2191ad1e91666 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pred.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/hash.pred.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/pred.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/pred.pass.cpp
index 5068d60a31d6a..b97f52b35d2b2 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/pred.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.boyer_moore_horspool/pred.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pass.cpp
index a31b413309429..99cc8c3fd90cc 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pred.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pred.pass.cpp
index 226118f56e035..5901dfb32a340 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pred.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/default.pred.pass.cpp
@@ -9,6 +9,7 @@
 // <functional>
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // default searcher
 // template<class _ForwardIterator, class _BinaryPredicate = equal_to<>>

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pass.cpp
index 4893169f79764..f5ec9ff0711c9 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pred.pass.cpp b/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pred.pass.cpp
index cfa5fea8f37d4..196d0281dac1e 100644
--- a/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pred.pass.cpp
+++ b/libcxx/test/std/experimental/func/func.searchers/func.searchers.default/func.searchers.default.creation/make_default_searcher.pred.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS
 
 // <functional>
 

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
index 193bb6f158bec..0f9b668fe700a 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp
@@ -150,17 +150,11 @@
 #   error "__cpp_lib_bind_front should not be defined before c++20"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should be defined in c++17"
-#   endif
-#   if __cpp_lib_boyer_moore_searcher != 201603L
-#     error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++17"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_boyer_moore_searcher
+#   error "__cpp_lib_boyer_moore_searcher should be defined in c++17"
+# endif
+# if __cpp_lib_boyer_moore_searcher != 201603L
+#   error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++17"
 # endif
 
 # ifdef __cpp_lib_constexpr_functional
@@ -224,17 +218,11 @@
 #   error "__cpp_lib_bind_front should have the value 201907L in c++20"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should be defined in c++20"
-#   endif
-#   if __cpp_lib_boyer_moore_searcher != 201603L
-#     error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++20"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_boyer_moore_searcher
+#   error "__cpp_lib_boyer_moore_searcher should be defined in c++20"
+# endif
+# if __cpp_lib_boyer_moore_searcher != 201603L
+#   error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++20"
 # endif
 
 # ifndef __cpp_lib_constexpr_functional
@@ -322,17 +310,11 @@
 #   error "__cpp_lib_bind_front should have the value 201907L in c++2b"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should be defined in c++2b"
-#   endif
-#   if __cpp_lib_boyer_moore_searcher != 201603L
-#     error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++2b"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_boyer_moore_searcher
+#   error "__cpp_lib_boyer_moore_searcher should be defined in c++2b"
+# endif
+# if __cpp_lib_boyer_moore_searcher != 201603L
+#   error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++2b"
 # endif
 
 # ifndef __cpp_lib_constexpr_functional

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 9c6697ceb4e0f..57022878f9873 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -1618,17 +1618,11 @@
 #   error "__cpp_lib_bounded_array_traits should not be defined before c++20"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should be defined in c++17"
-#   endif
-#   if __cpp_lib_boyer_moore_searcher != 201603L
-#     error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++17"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_boyer_moore_searcher
+#   error "__cpp_lib_boyer_moore_searcher should be defined in c++17"
+# endif
+# if __cpp_lib_boyer_moore_searcher != 201603L
+#   error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++17"
 # endif
 
 # ifndef __cpp_lib_byte
@@ -2579,17 +2573,11 @@
 #   error "__cpp_lib_bounded_array_traits should have the value 201902L in c++20"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should be defined in c++20"
-#   endif
-#   if __cpp_lib_boyer_moore_searcher != 201603L
-#     error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++20"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_boyer_moore_searcher
+#   error "__cpp_lib_boyer_moore_searcher should be defined in c++20"
+# endif
+# if __cpp_lib_boyer_moore_searcher != 201603L
+#   error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++20"
 # endif
 
 # ifndef __cpp_lib_byte
@@ -3801,17 +3789,11 @@
 #   error "__cpp_lib_bounded_array_traits should have the value 201902L in c++2b"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should be defined in c++2b"
-#   endif
-#   if __cpp_lib_boyer_moore_searcher != 201603L
-#     error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++2b"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_boyer_moore_searcher
-#     error "__cpp_lib_boyer_moore_searcher should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_boyer_moore_searcher
+#   error "__cpp_lib_boyer_moore_searcher should be defined in c++2b"
+# endif
+# if __cpp_lib_boyer_moore_searcher != 201603L
+#   error "__cpp_lib_boyer_moore_searcher should have the value 201603L in c++2b"
 # endif
 
 # ifndef __cpp_lib_byte

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/default.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/default.pass.cpp
index 8bcd525f9a148..b37a2b96b9996 100644
--- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/default.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/default.pass.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14
-// XFAIL: stdlib=libc++
 
 // <functional>
 
@@ -33,8 +32,9 @@
 
 
 #include <algorithm>
-#include <functional>
 #include <cassert>
+#include <functional>
+#include <string>
 
 #include "test_macros.h"
 #include "test_iterators.h"
@@ -123,9 +123,19 @@ test2()
     do_search(Iter1(ij), Iter1(ij+sj), Iter2(ik), Iter2(ik+sk), Iter1(ij+6));
 }
 
+void test_custom_pred() {
+    std::string long_string(1024, '0');
+    std::boyer_moore_searcher searcher(std::begin(long_string), std::end(long_string));
+    const char str[] = "1234";
+    auto ret = searcher(std::begin(str), std::end(str));
+    assert(ret.first == std::end(str));
+    assert(ret.second == std::end(str));
+}
+
 int main(int, char**) {
     test<random_access_iterator<const int*>, random_access_iterator<const int*> >();
     test2<random_access_iterator<const char*>, random_access_iterator<const char*> >();
+    test_custom_pred();
 
   return 0;
 }

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pass.cpp
index 3ff0f0d27f675..a7665f181ccd9 100644
--- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pass.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14
-// XFAIL: stdlib=libc++
 
 // <functional>
 
@@ -33,8 +32,8 @@
 
 
 #include <algorithm>
-#include <functional>
 #include <cassert>
+#include <functional>
 
 #include "test_macros.h"
 #include "test_iterators.h"

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pred.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pred.pass.cpp
index e4e72be2b6b37..c70782c8c78aa 100644
--- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pred.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/hash.pred.pass.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14
-// XFAIL: stdlib=libc++
 
 // <functional>
 
@@ -33,8 +32,8 @@
 
 
 #include <algorithm>
-#include <functional>
 #include <cassert>
+#include <functional>
 
 #include "test_macros.h"
 #include "test_iterators.h"

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/pred.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/pred.pass.cpp
index f6f88518c8889..396e2847928b0 100644
--- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/pred.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/pred.pass.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14
-// XFAIL: stdlib=libc++
 
 // <functional>
 
@@ -33,8 +32,8 @@
 
 
 #include <algorithm>
-#include <functional>
 #include <cassert>
+#include <functional>
 
 #include "test_macros.h"
 #include "test_iterators.h"

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/default.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/default.pass.cpp
index 828d6fc72157e..d8e986ec413a1 100644
--- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/default.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/default.pass.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14
-// XFAIL: stdlib=libc++
 
 // <functional>
 

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pass.cpp
index 904623ff27819..8ada7ef1d9e80 100644
--- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pass.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14
-// XFAIL: stdlib=libc++
 
 // <functional>
 

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pred.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pred.pass.cpp
index 53700884cd446..ec74f53850d1b 100644
--- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pred.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/hash.pred.pass.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14
-// XFAIL: stdlib=libc++
 
 // <functional>
 

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/pred.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/pred.pass.cpp
index 137d1a66ad32c..9f6dcbd2f2423 100644
--- a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/pred.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/pred.pass.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14
-// XFAIL: stdlib=libc++
 
 // <functional>
 

diff  --git a/libcxx/test/std/utilities/optional/optional.hash/enabled_hash.pass.cpp b/libcxx/test/std/utilities/optional/optional.hash/enabled_hash.pass.cpp
index ca618ba6a615d..be11fec570f79 100644
--- a/libcxx/test/std/utilities/optional/optional.hash/enabled_hash.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.hash/enabled_hash.pass.cpp
@@ -13,6 +13,7 @@
 // Test that <optional> provides all of the arithmetic, enum, and pointer
 // hash specializations.
 
+#include <functional>
 #include <optional>
 
 #include "poisoned_hash_helper.h"

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 60de8170616b3..f1977b58b704a 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -176,7 +176,6 @@ def add_version_header(tc):
     "name": "__cpp_lib_boyer_moore_searcher",
     "values": { "c++17": 201603 },
     "headers": ["functional"],
-    "unimplemented": True,
   }, {
     "name": "__cpp_lib_byte",
     "values": { "c++17": 201603 },


        


More information about the libcxx-commits mailing list