[libcxx-commits] [libcxx] [String] Allow fancy pointer as pointer type of basic_string allocator (PR #71182)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Dec 19 08:56:15 PST 2023


https://github.com/bemerybmw updated https://github.com/llvm/llvm-project/pull/71182

>From c7b8f8f9dfc2c8ddd730dbad1594e0d7f6ee12a4 Mon Sep 17 00:00:00 2001
From: Brendan Emery <brendan.be.emery at bmw.de>
Date: Fri, 3 Nov 2023 08:36:55 +0100
Subject: [PATCH] [String] Allow fancy pointer as pointer type of basic_string
 allocator

Currently, basic_string does not support custom allocators which use
fancy pointers that are not trivially constructible and destructible as
the pointer type. This is due to requirements of the internal string
representation, __rep. In order to use a pointer type which is not
trivially constructible, __rep should:

- be a literal type (required by the implementation). This requires that
__rep has at least one constexpr constructor and that its destructor is
trivial.
- provide an explicit constructor, copy constructor and copy assignment
operator (default special member functions are deleted since __long, a
variant member of __rep, is not trivially constructible as it contains a
fancy pointer as a member variable).

This change allows the use of fancy pointers which are not trivially
constructible by adding an explicit and constexpr constructor, copy
constructor and copy assignment operator.

Addresses bug report: https://bugs.llvm.org/show_bug.cgi?id=20508
---
 libcxx/include/string                         | 107 ++++++++++
 .../basic.string/alignof.compile.pass.cpp     |  15 ++
 .../basic.string/sizeof.compile.pass.cpp      |  35 ++++
 .../string.access/assert.back.pass.cpp        |   2 +
 .../string.access/assert.cback.pass.cpp       |   2 +
 .../string.access/assert.cfront.pass.cpp      |   2 +
 .../string.access/assert.cindex.pass.cpp      |   2 +
 .../string.access/assert.front.pass.cpp       |   2 +
 .../string.access/assert.index.pass.cpp       |   2 +
 .../string.capacity/PR53170.pass.cpp          |   2 +
 .../string.cons/copy_shrunk_long.pass.cpp     |   9 +-
 .../debug.iterator.add.pass.cpp               |   2 +
 .../debug.iterator.compare.pass.cpp           |   2 +
 .../debug.iterator.decrement.pass.cpp         |   2 +
 .../debug.iterator.dereference.pass.cpp       |   2 +
 .../debug.iterator.increment.pass.cpp         |   2 +
 .../debug.iterator.index.pass.cpp             |   2 +
 .../debug.iterator.subtract.pass.cpp          |   2 +
 .../assert.erase_iter.null.pass.cpp           |   2 +
 .../string.modifiers/assert.pop_back.pass.cpp |   2 +
 .../debug.erase.iter.pass.cpp                 |   2 +
 .../debug.erase.iter_iter.pass.cpp            |   2 +
 .../debug.insert.iter_char.pass.cpp           |   2 +
 .../debug.insert.iter_iter_iter.pass.cpp      |   2 +
 .../debug.insert.iter_size_char.pass.cpp      |   2 +
 .../resize_default_initialized.pass.cpp       |   6 +
 .../basic.string.hash/enabled_hashes.pass.cpp |   1 +
 .../basic.string/string.access/at.pass.cpp    |   2 +
 .../basic.string/string.access/back.pass.cpp  |   2 +
 .../basic.string/string.access/front.pass.cpp |   2 +
 .../basic.string/string.access/index.pass.cpp |   3 +
 .../string.capacity/clear.pass.cpp            |   2 +
 .../string.capacity/empty.pass.cpp            |   2 +
 .../string.capacity/length.pass.cpp           |   2 +
 .../string.capacity/max_size.pass.cpp         |   2 +
 .../string.capacity/over_max_size.pass.cpp    |   2 +
 .../string.capacity/reserve.pass.cpp          |   2 +
 .../string.capacity/reserve_size.pass.cpp     |   2 +
 .../resize_and_overwrite.pass.cpp             |  18 ++
 .../string.capacity/resize_size.pass.cpp      |   2 +
 .../string.capacity/resize_size_char.pass.cpp |   2 +
 .../string.capacity/shrink_to_fit.pass.cpp    |   2 +
 .../string.capacity/size.pass.cpp             |   2 +
 .../string.cons/T_size_size.pass.cpp          |   1 +
 .../basic.string/string.cons/alloc.pass.cpp   |   2 +
 .../string.cons/char_assignment.pass.cpp      |   2 +
 .../basic.string/string.cons/copy.pass.cpp    |   1 +
 .../string.cons/copy_alloc.pass.cpp           |   1 -
 .../string.cons/copy_assignment.pass.cpp      |   2 +
 .../basic.string/string.cons/default.pass.cpp |   3 +
 .../basic.string/string.cons/dtor.pass.cpp    |   3 +
 .../string.cons/initializer_list.pass.cpp     |   1 +
 .../initializer_list_assignment.pass.cpp      |   2 +
 .../string.cons/iter_alloc.pass.cpp           |   1 +
 .../string.cons/iter_alloc_deduction.pass.cpp |  20 ++
 .../basic.string/string.cons/move.pass.cpp    |   1 +
 .../string.cons/move_alloc.pass.cpp           |  12 ++
 .../string.cons/move_assign_noexcept.pass.cpp |   4 +
 .../string.cons/move_assignment.pass.cpp      |   1 +
 .../string.cons/move_noexcept.pass.cpp        |   4 +
 .../string.cons/pointer_alloc.pass.cpp        |   1 +
 .../string.cons/pointer_assignment.pass.cpp   |   2 +
 .../string.cons/pointer_size_alloc.pass.cpp   |   1 +
 .../string.cons/size_char_alloc.pass.cpp      |   1 +
 .../string.cons/string_view.pass.cpp          |   1 +
 .../string_view_assignment.pass.cpp           |   2 +
 .../string_view_deduction.pass.cpp            |  40 ++++
 .../string_view_size_size_deduction.pass.cpp  |  40 ++++
 .../basic.string/string.cons/substr.pass.cpp  |   1 +
 .../string.cons/substr_rvalue.pass.cpp        |   1 +
 .../string.contains/contains.char.pass.cpp    |   2 +
 .../string.contains/contains.ptr.pass.cpp     |   2 +
 .../contains.string_view.pass.cpp             |   2 +
 .../string.ends_with/ends_with.char.pass.cpp  |   2 +
 .../string.ends_with/ends_with.ptr.pass.cpp   |   2 +
 .../ends_with.string_view.pass.cpp            |   2 +
 .../string.iterators/begin.pass.cpp           |   2 +
 .../string.iterators/cbegin.pass.cpp          |   2 +
 .../string.iterators/cend.pass.cpp            |   2 +
 .../string.iterators/crbegin.pass.cpp         |   2 +
 .../string.iterators/crend.pass.cpp           |   2 +
 .../string.iterators/end.pass.cpp             |   2 +
 .../string.iterators/rbegin.pass.cpp          |   2 +
 .../string.iterators/rend.pass.cpp            |   2 +
 .../robust_against_adl.pass.cpp               |   4 +
 .../string_append/T_size_size.pass.cpp        |   2 +
 .../string_append/initializer_list.pass.cpp   |   2 +
 .../string_append/iterator.pass.cpp           |   2 +
 .../string_append/pointer.pass.cpp            |   2 +
 .../string_append/pointer_size.pass.cpp       |   2 +
 .../string_append/push_back.pass.cpp          |   2 +
 .../string_append/size_char.pass.cpp          |   2 +
 .../string_append/string.pass.cpp             |   2 +
 .../string_append/string_size_size.pass.cpp   |   2 +
 .../string_append/string_view.pass.cpp        |   2 +
 .../string_assign/T_size_size.pass.cpp        |   2 +
 .../string_assign/initializer_list.pass.cpp   |   4 +-
 .../string_assign/iterator.pass.cpp           |   2 +
 .../string_assign/pointer.pass.cpp            |   2 +
 .../string_assign/pointer_size.pass.cpp       |   2 +
 .../string_assign/rv_string.pass.cpp          |   2 +
 .../string_assign/size_char.pass.cpp          |   2 +
 .../string_assign/string.pass.cpp             |   8 +
 .../string_assign/string_size_size.pass.cpp   |   2 +
 .../string_assign/string_view.pass.cpp        |   1 +
 .../string_copy/copy.pass.cpp                 |   2 +
 .../string_erase/iter.pass.cpp                |   2 +
 .../string_erase/iter_iter.pass.cpp           |   2 +
 .../string_erase/pop_back.pass.cpp            |   2 +
 .../string_erase/size_size.pass.cpp           |   2 +
 .../string_insert/iter_char.pass.cpp          |   2 +
 .../iter_initializer_list.pass.cpp            |   2 +
 .../string_insert/iter_iter_iter.pass.cpp     |   2 +
 .../string_insert/iter_size_char.pass.cpp     |   2 +
 .../string_insert/size_T_size_size.pass.cpp   |   3 +
 .../string_insert/size_pointer.pass.cpp       |   2 +
 .../string_insert/size_pointer_size.pass.cpp  |   3 +
 .../string_insert/size_size_char.pass.cpp     |   2 +
 .../string_insert/size_string.pass.cpp        |   2 +
 .../size_string_size_size.pass.cpp            |   2 +
 .../string_insert/string_view.pass.cpp        |   2 +
 .../string_op_plus_equal/char.pass.cpp        |   2 +
 .../initializer_list.pass.cpp                 |   2 +
 .../string_op_plus_equal/pointer.pass.cpp     |   2 +
 .../string_op_plus_equal/string.pass.cpp      |   2 +
 .../iter_iter_initializer_list.pass.cpp       |   2 +
 .../iter_iter_iter_iter.pass.cpp              |   2 +
 .../string_replace/iter_iter_pointer.pass.cpp |   2 +
 .../iter_iter_pointer_size.pass.cpp           |   2 +
 .../iter_iter_size_char.pass.cpp              |   4 +-
 .../string_replace/iter_iter_string.pass.cpp  |   2 +
 .../iter_iter_string_view.pass.cpp            |   2 +
 .../size_size_T_size_size.pass.cpp            |   2 +
 .../string_replace/size_size_pointer.pass.cpp |   2 +
 .../size_size_pointer_size.pass.cpp           |   2 +
 .../size_size_size_char.pass.cpp              |   2 +
 .../string_replace/size_size_string.pass.cpp  |   2 +
 .../size_size_string_size_size.pass.cpp       |   2 +
 .../size_size_string_view.pass.cpp            |   2 +
 .../string_swap/swap.pass.cpp                 |   2 +
 .../string.io/get_line.pass.cpp               |   2 +
 .../string.io/get_line_delim.pass.cpp         |   2 +
 .../string.io/get_line_delim_rv.pass.cpp      |   2 +
 .../string.io/get_line_rv.pass.cpp            |   4 +
 .../string.io/stream_extract.pass.cpp         |   2 +
 .../string.io/stream_insert.pass.cpp          |   2 +
 .../string.special/swap.pass.cpp              |   2 +
 .../string_op!=/pointer_string.pass.cpp       |   2 +
 .../string_op!=/string_pointer.pass.cpp       |   2 +
 .../string_op!=/string_string.pass.cpp        |   2 +
 .../string_op!=/string_string_view.pass.cpp   |   2 +
 .../string_op!=/string_view_string.pass.cpp   |   2 +
 .../string_op+/char_string.pass.cpp           |   2 +
 .../string_op+/pointer_string.pass.cpp        |   2 +
 .../string_op+/string_char.pass.cpp           |   2 +
 .../string_op+/string_pointer.pass.cpp        |   2 +
 .../string_op+/string_string.pass.cpp         |   2 +
 .../string_operator==/pointer_string.pass.cpp |   2 +
 .../string_operator==/string_pointer.pass.cpp |   2 +
 .../string_operator==/string_string.pass.cpp  |   2 +
 .../string_string_view.pass.cpp               |   2 +
 .../string_view_string.pass.cpp               |   2 +
 .../string_opgt/pointer_string.pass.cpp       |   2 +
 .../string_opgt/string_pointer.pass.cpp       |   2 +
 .../string_opgt/string_string.pass.cpp        |   2 +
 .../string_opgt/string_string_view.pass.cpp   |   2 +
 .../string_opgt/string_view_string.pass.cpp   |   2 +
 .../string_opgt=/pointer_string.pass.cpp      |   2 +
 .../string_opgt=/string_pointer.pass.cpp      |   2 +
 .../string_opgt=/string_string.pass.cpp       |   2 +
 .../string_opgt=/string_string_view.pass.cpp  |   2 +
 .../string_opgt=/string_view_string.pass.cpp  |   2 +
 .../string_oplt/pointer_string.pass.cpp       |   2 +
 .../string_oplt/string_pointer.pass.cpp       |   2 +
 .../string_oplt/string_string.pass.cpp        |   2 +
 .../string_oplt/string_string_view.pass.cpp   |   2 +
 .../string_oplt/string_view_string.pass.cpp   |   2 +
 .../string_oplt=/pointer_string.pass.cpp      |   2 +
 .../string_oplt=/string_pointer.pass.cpp      |   2 +
 .../string_oplt=/string_string.pass.cpp       |   2 +
 .../string_oplt=/string_string_view.pass.cpp  |   2 +
 .../string_oplt=/string_view_string.pass.cpp  |   2 +
 .../string.accessors/c_str.pass.cpp           |   2 +
 .../string.ops/string.accessors/data.pass.cpp |   2 +
 .../string.accessors/get_allocator.pass.cpp   |   1 +
 .../string_compare/pointer.pass.cpp           |   2 +
 .../size_size_T_size_size.pass.cpp            |   2 +
 .../string_compare/size_size_pointer.pass.cpp |   2 +
 .../size_size_pointer_size.pass.cpp           |   2 +
 .../string_compare/size_size_string.pass.cpp  |   2 +
 .../size_size_string_size_size.pass.cpp       |   2 +
 .../size_size_string_view.pass.cpp            |   2 +
 .../string.ops/string_compare/string.pass.cpp |   2 +
 .../string_compare/string_view.pass.cpp       |   2 +
 .../char_size.pass.cpp                        |   2 +
 .../pointer_size.pass.cpp                     |   2 +
 .../pointer_size_size.pass.cpp                |   2 +
 .../string_size.pass.cpp                      |   2 +
 .../string_view_size.pass.cpp                 |   2 +
 .../string_find.first.of/char_size.pass.cpp   |   2 +
 .../pointer_size.pass.cpp                     |   2 +
 .../pointer_size_size.pass.cpp                |   2 +
 .../string_find.first.of/string_size.pass.cpp |   2 +
 .../string_view_size.pass.cpp                 |   2 +
 .../char_size.pass.cpp                        |   2 +
 .../pointer_size.pass.cpp                     |   2 +
 .../pointer_size_size.pass.cpp                |   2 +
 .../string_size.pass.cpp                      |   2 +
 .../string_view_size.pass.cpp                 |   2 +
 .../string_find.last.of/char_size.pass.cpp    |   2 +
 .../string_find.last.of/pointer_size.pass.cpp |   2 +
 .../pointer_size_size.pass.cpp                |   2 +
 .../string_find.last.of/string_size.pass.cpp  |   2 +
 .../string_view_size.pass.cpp                 |   2 +
 .../string.ops/string_find/char_size.pass.cpp |   2 +
 .../string_find/pointer_size.pass.cpp         |   2 +
 .../string_find/pointer_size_size.pass.cpp    |   2 +
 .../string_find/string_size.pass.cpp          |   2 +
 .../string_find/string_view_size.pass.cpp     |   2 +
 .../string_rfind/char_size.pass.cpp           |   2 +
 .../string_rfind/pointer_size.pass.cpp        |   2 +
 .../string_rfind/pointer_size_size.pass.cpp   |   2 +
 .../string_rfind/string_size.pass.cpp         |   2 +
 .../string_rfind/string_view_size.pass.cpp    |   2 +
 .../string.ops/string_substr/substr.pass.cpp  |   1 +
 .../string_substr/substr_rvalue.pass.cpp      |   1 +
 .../string.require/contiguous.pass.cpp        |   1 +
 .../starts_with.char.pass.cpp                 |   2 +
 .../starts_with.ptr.pass.cpp                  |   2 +
 .../starts_with.string_view.pass.cpp          |   2 +
 .../std/strings/basic.string/types.pass.cpp   |   2 +
 .../strings/strings.erasure/erase.pass.cpp    |   5 +-
 .../strings/strings.erasure/erase_if.pass.cpp |   5 +-
 libcxx/test/support/test_allocator.h          | 188 ++++++++++++++++++
 234 files changed, 934 insertions(+), 12 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index fdffca5aed18be..32b8fcdb49212f 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -607,6 +607,7 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
 #include <__type_traits/is_same.h>
 #include <__type_traits/is_standard_layout.h>
 #include <__type_traits/is_trivial.h>
+#include <__type_traits/is_trivially_constructible.h>
 #include <__type_traits/noexcept_move_assign_container.h>
 #include <__type_traits/remove_cvref.h>
 #include <__type_traits/void_t.h>
@@ -829,6 +830,7 @@ private:
     size_type __words[__n_words];
   };
 
+#ifdef _LIBCPP_CXX03_LANG
   struct __rep {
     union {
       __short __s;
@@ -836,6 +838,88 @@ private:
       __raw __r;
     };
   };
+#else
+  // Since C++03, unions can contain members with non-trivial special member functions (C++03 doesn't allow unions to
+  // contain members with non-trivial special member functions). In this case, the corresponding special member
+  // function in the union will be deleted and therefore must be explicitly defined. Therefore, to support fancy
+  // pointers with non-trivial special member functions in __long, we must explicitly define a constructor, copy
+  // constructor and copy assignment operator in __rep.
+  struct __rep {
+    _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep() _NOEXCEPT : __s{} {}
+    
+    _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__rep() _NOEXCEPT = default;
+
+    _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep(const __rep& __other) _NOEXCEPT {
+      // For certain fancy pointers such as offset pointers, the value of __l.__data_ will be different for 2 pointers
+      // pointing to the same object (because the offset is calculated with respect to the pointer itself). Therefore,
+      // the copy assignment operator of the underlying pointer needs to be explicitly called.
+      if (__is_rep_long(__other)) {
+        __begin_long_lifetime(*this);
+        __copy_long(*this, __other);
+      } else {
+        __copy_short(*this, __other);
+      }
+    }
+
+    _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep& operator=(const __rep& __other) _NOEXCEPT {
+      if (this != &__other) {
+        if (__is_rep_long(__other)) {
+          if (!__is_rep_long(*this)) {
+            __begin_long_lifetime(*this);
+          }
+          __copy_long(*this, __other);
+        } else {
+          __copy_short(*this, __other);
+        }
+      }
+      return *this;
+    }
+
+    union {
+        __short __s;
+        __long __l;
+        __raw __r;
+    };
+
+  private:
+    _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __begin_long_lifetime(__rep& __str) _NOEXCEPT {
+#if _LIBCPP_STD_VER >= 17
+      if constexpr(!__is_trivially_constructible(__long)) {
+#else
+      if (!__is_trivially_constructible(__long)) {
+#endif // _LIBCPP_STD_VER >= 17
+          std::construct_at(std::addressof(__str.__l));
+      }
+    }
+
+    _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __copy_long(__rep& __dest, const __rep& __src) _NOEXCEPT {
+      __dest.__l.__is_long_ = __src.__l.__is_long_;
+      __dest.__l.__cap_ = __src.__l.__cap_;
+      __dest.__l.__size_ = __src.__l.__size_;
+      __dest.__l.__data_ = __src.__l.__data_;
+    }
+
+    _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __copy_short(__rep& __dest, const __rep& __src) _NOEXCEPT {
+      __dest.__s.__is_long_ = __src.__s.__is_long_;
+      __dest.__s.__size_ = __src.__s.__size_;
+
+      for (size_type __i = 0; __i <sizeof(value_type) - 1; ++__i) {
+        __dest.__s.__padding_[__i] = __src.__s.__padding_[__i];
+      }
+
+      for (size_type __i = 0;  __i <__min_cap; ++__i) {
+        __dest.__s.__data_[__i] = __src.__s.__data_[__i];
+      }
+    }
+
+    _LIBCPP_CONSTEXPR_SINCE_CXX20 static bool __is_rep_long(const __rep& __str_rep) _NOEXCEPT {
+      if (__libcpp_is_constant_evaluated() && __builtin_constant_p(__str_rep.__l.__is_long_)) {
+        return __str_rep.__l.__is_long_;
+      }
+      return __str_rep.__s.__is_long_;
+    }
+  };
+#endif // _LIBCPP_CXX03_LANG
 
   __compressed_pair<__rep, allocator_type> __r_;
 
@@ -854,6 +938,7 @@ private:
       auto __capacity   = __recommend(__size) + 1;
       auto __allocation = __alloc_traits::allocate(__alloc(), __capacity);
       __begin_lifetime(__allocation, __capacity);
+      __begin_long_lifetime();
       __set_long_cap(__capacity);
       __set_long_pointer(__allocation);
       __set_long_size(__size);
@@ -1675,6 +1760,20 @@ public:
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
   find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT;
 
+    // If __long is not trivially constructible (this occurs if the pointer type inside __long is not trivially constructible)
+    // then the lifetime of __l must be explicitly started with std::construct_at before it can be assigned to. If __long is 
+    // trivially constructible, then the lifetime of __l can be implicitly started with a simple assignment and therefore does
+    // not need to be explicitly initialised here.
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_long_lifetime() {
+#if _LIBCPP_STD_VER >= 17
+        if constexpr(!__is_trivially_constructible(__long)) {
+#else
+        if (!__is_trivially_constructible(__long)) {
+#endif // _LIBCPP_STD_VER >= 17
+            std::construct_at(std::addressof(__r_.first().__l));
+        }
+    }
+
   template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0>
   _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type
   find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT;
@@ -2033,6 +2132,7 @@ private:
         if (__is_long())
           __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
         __alloc() = std::move(__a);
+        __begin_long_lifetime(); 
         __set_long_pointer(__allocation.ptr);
         __set_long_cap(__allocation.count);
         __set_long_size(__str.size());
@@ -2207,6 +2307,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_ty
     auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
     __p               = __allocation.ptr;
     __begin_lifetime(__p, __allocation.count);
+    __begin_long_lifetime(); 
     __set_long_pointer(__p);
     __set_long_cap(__allocation.count);
     __set_long_size(__sz);
@@ -2232,6 +2333,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(const value
     auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
     __p               = __allocation.ptr;
     __begin_lifetime(__p, __allocation.count);
+    __begin_long_lifetime(); 
     __set_long_pointer(__p);
     __set_long_cap(__allocation.count);
     __set_long_size(__sz);
@@ -2255,6 +2357,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
     auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__n) + 1);
     __p               = __allocation.ptr;
     __begin_lifetime(__p, __allocation.count);
+    __begin_long_lifetime(); 
     __set_long_pointer(__p);
     __set_long_cap(__allocation.count);
     __set_long_size(__n);
@@ -2320,6 +2423,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_size(_InputIterator __fir
     auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
     __p               = __allocation.ptr;
     __begin_lifetime(__p, __allocation.count);
+    __begin_long_lifetime(); 
     __set_long_pointer(__p);
     __set_long_cap(__allocation.count);
     __set_long_size(__sz);
@@ -2370,6 +2474,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
         std::__to_address(__p) + __n_copy + __n_add, std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz);
   if (__old_cap + 1 != __min_cap)
     __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1);
+  __begin_long_lifetime(); 
   __set_long_pointer(__p);
   __set_long_cap(__allocation.count);
   __old_sz = __n_copy + __n_add + __sec_cp_sz;
@@ -2411,6 +2516,7 @@ void _LIBCPP_CONSTEXPR_SINCE_CXX20
         std::__to_address(__p) + __n_copy + __n_add, std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz);
   if (__old_cap + 1 != __min_cap)
     __alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1);
+  __begin_long_lifetime(); 
   __set_long_pointer(__p);
   __set_long_cap(__allocation.count);
 }
@@ -3261,6 +3367,7 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
   if (__was_long)
     __alloc_traits::deallocate(__alloc(), __p, __cap + 1);
   if (__now_long) {
+    __begin_long_lifetime(); 
     __set_long_cap(__target_capacity + 1);
     __set_long_size(__sz);
     __set_long_pointer(__new_data);
diff --git a/libcxx/test/libcxx/strings/basic.string/alignof.compile.pass.cpp b/libcxx/test/libcxx/strings/basic.string/alignof.compile.pass.cpp
index 7b4d54ed410b02..fb6b6e917cb99c 100644
--- a/libcxx/test/libcxx/strings/basic.string/alignof.compile.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/alignof.compile.pass.cpp
@@ -44,6 +44,9 @@ class small_iter_allocator {
 template <class CharT>
 using min_string = std::basic_string<CharT, std::char_traits<CharT>, min_allocator<CharT>>;
 
+template <class CharT>
+using fancy_string = std::basic_string<CharT, std::char_traits<CharT>, fancy_pointer_allocator<CharT>>;
+
 template <class CharT>
 using test_string = std::basic_string<CharT, std::char_traits<CharT>, test_allocator<CharT>>;
 
@@ -54,6 +57,7 @@ using small_string = std::basic_string<CharT, std::char_traits<CharT>, small_ite
 
 static_assert(alignof(std::string) == 8, "");
 static_assert(alignof(min_string<char>) == 8, "");
+static_assert(alignof(fancy_string<char>) == 8, "");
 static_assert(alignof(test_string<char>) == 8, "");
 static_assert(alignof(small_string<char>) == 2, "");
 
@@ -61,11 +65,13 @@ static_assert(alignof(small_string<char>) == 2, "");
 #    if __WCHAR_WIDTH__ == 32
 static_assert(alignof(std::wstring) == 8, "");
 static_assert(alignof(min_string<wchar_t>) == 8, "");
+static_assert(alignof(fancy_string<wchar_t>) == 8, "");
 static_assert(alignof(test_string<wchar_t>) == 8, "");
 static_assert(alignof(small_string<wchar_t>) == 4, "");
 #    elif __WCHAR_WIDTH__ == 16
 static_assert(alignof(std::wstring) == 8, "");
 static_assert(alignof(min_string<wchar_t>) == 8, "");
+static_assert(alignof(fancy_string<wchar_t>) == 8, "");
 static_assert(alignof(test_string<wchar_t>) == 8, "");
 static_assert(alignof(small_string<wchar_t>) == 2, "");
 #    else
@@ -76,6 +82,7 @@ static_assert(alignof(small_string<wchar_t>) == 2, "");
 #  ifndef TEST_HAS_NO_CHAR8_T
 static_assert(alignof(std::u8string) == 8, "");
 static_assert(alignof(min_string<char8_t>) == 8, "");
+static_assert(alignof(fancy_string<char8_t>) == 8, "");
 static_assert(alignof(test_string<char8_t>) == 8, "");
 static_assert(alignof(small_string<char8_t>) == 2, "");
 #  endif
@@ -85,6 +92,8 @@ static_assert(alignof(std::u16string) == 8, "");
 static_assert(alignof(std::u32string) == 8, "");
 static_assert(alignof(min_string<char16_t>) == 8, "");
 static_assert(alignof(min_string<char32_t>) == 8, "");
+static_assert(alignof(fancy_string<char16_t>) == 8, "");
+static_assert(alignof(fancy_string<char32_t>) == 8, "");
 static_assert(alignof(test_string<char16_t>) == 8, "");
 static_assert(alignof(test_string<char32_t>) == 8, "");
 static_assert(alignof(small_string<char16_t>) == 2, "");
@@ -95,6 +104,7 @@ static_assert(alignof(small_string<char32_t>) == 4, "");
 
 static_assert(alignof(std::string) == 4, "");
 static_assert(alignof(min_string<char>) == 4, "");
+static_assert(alignof(fancy_string<char>) == 4, "");
 static_assert(alignof(test_string<char>) == 4, "");
 static_assert(alignof(small_string<char>) == 2, "");
 
@@ -102,11 +112,13 @@ static_assert(alignof(small_string<char>) == 2, "");
 #    if __WCHAR_WIDTH__ == 32
 static_assert(alignof(std::wstring) == 4, "");
 static_assert(alignof(min_string<wchar_t>) == 4, "");
+static_assert(alignof(fancy_string<wchar_t>) == 4, "");
 static_assert(alignof(test_string<wchar_t>) == 4, "");
 static_assert(alignof(small_string<wchar_t>) == 4, "");
 #    elif __WCHAR_WIDTH__ == 16
 static_assert(alignof(std::wstring) == 4, "");
 static_assert(alignof(min_string<wchar_t>) == 4, "");
+static_assert(alignof(fancy_string<wchar_t>) == 4, "");
 static_assert(alignof(test_string<wchar_t>) == 4, "");
 static_assert(alignof(small_string<wchar_t>) == 2, "");
 #    else
@@ -117,6 +129,7 @@ static_assert(alignof(small_string<wchar_t>) == 2, "");
 #  ifndef TEST_HAS_NO_CHAR8_T
 static_assert(alignof(std::u8string) == 4, "");
 static_assert(alignof(min_string<char8_t>) == 4, "");
+static_assert(alignof(fancy_string<char8_t>) == 4, "");
 static_assert(alignof(test_string<char8_t>) == 4, "");
 static_assert(alignof(small_string<char8_t>) == 2, "");
 #  endif
@@ -126,6 +139,8 @@ static_assert(alignof(std::u16string) == 4, "");
 static_assert(alignof(std::u32string) == 4, "");
 static_assert(alignof(min_string<char16_t>) == 4, "");
 static_assert(alignof(min_string<char32_t>) == 4, "");
+static_assert(alignof(fancy_string<char16_t>) == 4, "");
+static_assert(alignof(fancy_string<char32_t>) == 4, "");
 static_assert(alignof(test_string<char16_t>) == 4, "");
 static_assert(alignof(test_string<char32_t>) == 4, "");
 static_assert(alignof(small_string<char32_t>) == 4, "");
diff --git a/libcxx/test/libcxx/strings/basic.string/sizeof.compile.pass.cpp b/libcxx/test/libcxx/strings/basic.string/sizeof.compile.pass.cpp
index 6e00e43618b2e3..2788c1274b4b0d 100644
--- a/libcxx/test/libcxx/strings/basic.string/sizeof.compile.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/sizeof.compile.pass.cpp
@@ -42,6 +42,9 @@ class small_iter_allocator {
 template <class CharT>
 using min_string = std::basic_string<CharT, std::char_traits<CharT>, min_allocator<CharT> >;
 
+template <class CharT>
+using fancy_string = std::basic_string<CharT, std::char_traits<CharT>, fancy_pointer_allocator<CharT> >;
+
 template <class CharT>
 using test_string = std::basic_string<CharT, std::char_traits<CharT>, test_allocator<CharT> >;
 
@@ -52,6 +55,9 @@ using small_string = std::basic_string<CharT, std::char_traits<CharT>, small_ite
 
 static_assert(sizeof(std::string) == 24, "");
 static_assert(sizeof(min_string<char>) == 24, "");
+#  if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<char>) == 24, "");
+#  endif
 static_assert(sizeof(test_string<char>) == 32, "");
 static_assert(sizeof(small_string<char>) == 6, "");
 
@@ -59,11 +65,17 @@ static_assert(sizeof(small_string<char>) == 6, "");
 #    if __WCHAR_WIDTH__ == 32
 static_assert(sizeof(std::wstring) == 24, "");
 static_assert(sizeof(min_string<wchar_t>) == 24, "");
+#      if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<wchar_t>) == 24, "");
+#      endif
 static_assert(sizeof(test_string<wchar_t>) == 32, "");
 static_assert(sizeof(small_string<wchar_t>) == 12, "");
 #    elif __WCHAR_WIDTH__ == 16
 static_assert(sizeof(std::wstring) == 24, "");
 static_assert(sizeof(min_string<wchar_t>) == 24, "");
+#      if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<wchar_t>) == 24, "");
+#      endif
 static_assert(sizeof(test_string<wchar_t>) == 32, "");
 static_assert(sizeof(small_string<wchar_t>) == 6, "");
 #    else
@@ -74,6 +86,9 @@ static_assert(sizeof(small_string<wchar_t>) == 6, "");
 #  ifndef TEST_HAS_NO_CHAR8_T
 static_assert(sizeof(std::u8string) == 24, "");
 static_assert(sizeof(min_string<char8_t>) == 24, "");
+#    if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<char8_t>) == 24, "");
+#    endif
 static_assert(sizeof(test_string<char8_t>) == 32, "");
 static_assert(sizeof(small_string<char8_t>) == 6, "");
 #  endif
@@ -83,6 +98,10 @@ static_assert(sizeof(std::u16string) == 24, "");
 static_assert(sizeof(std::u32string) == 24, "");
 static_assert(sizeof(min_string<char16_t>) == 24, "");
 static_assert(sizeof(min_string<char32_t>) == 24, "");
+#    if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<char16_t>) == 24, "");
+static_assert(sizeof(fancy_string<char32_t>) == 24, "");
+#    endif
 static_assert(sizeof(test_string<char16_t>) == 32, "");
 static_assert(sizeof(test_string<char32_t>) == 32, "");
 static_assert(sizeof(small_string<char16_t>) == 6, "");
@@ -93,6 +112,9 @@ static_assert(sizeof(small_string<char32_t>) == 12, "");
 
 static_assert(sizeof(std::string) == 12, "");
 static_assert(sizeof(min_string<char>) == 12, "");
+#  if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<char>) == 12, "");
+#  endif
 static_assert(sizeof(test_string<char>) == 24, "");
 static_assert(sizeof(small_string<char>) == 6, "");
 
@@ -100,11 +122,17 @@ static_assert(sizeof(small_string<char>) == 6, "");
 #    if __WCHAR_WIDTH__ == 32
 static_assert(sizeof(std::wstring) == 12, "");
 static_assert(sizeof(min_string<wchar_t>) == 12, "");
+#      if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<wchar_t>) == 12, "");
+#      endif
 static_assert(sizeof(test_string<wchar_t>) == 24, "");
 static_assert(sizeof(small_string<wchar_t>) == 12, "");
 #    elif __WCHAR_WIDTH__ == 16
 static_assert(sizeof(std::wstring) == 12, "");
 static_assert(sizeof(min_string<wchar_t>) == 12, "");
+#      if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<wchar_t>) == 12, "");
+#      endif
 static_assert(sizeof(test_string<wchar_t>) == 24, "");
 static_assert(sizeof(small_string<wchar_t>) == 6, "");
 #    else
@@ -115,6 +143,9 @@ static_assert(sizeof(small_string<wchar_t>) == 6, "");
 #  ifndef TEST_HAS_NO_CHAR8_T
 static_assert(sizeof(std::u8string) == 12, "");
 static_assert(sizeof(min_string<char8_t>) == 12, "");
+#    if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<char8_t>) == 12, "");
+#    endif
 static_assert(sizeof(test_string<char8_t>) == 24, "");
 static_assert(sizeof(small_string<char>) == 6, "");
 #  endif
@@ -124,6 +155,10 @@ static_assert(sizeof(std::u16string) == 12, "");
 static_assert(sizeof(std::u32string) == 12, "");
 static_assert(sizeof(min_string<char16_t>) == 12, "");
 static_assert(sizeof(min_string<char32_t>) == 12, "");
+#    if TEST_STD_VER >= 11
+static_assert(sizeof(fancy_string<char16_t>) == 12, "");
+static_assert(sizeof(fancy_string<char32_t>) == 12, "");
+#    endif
 static_assert(sizeof(test_string<char16_t>) == 24, "");
 static_assert(sizeof(test_string<char32_t>) == 24, "");
 static_assert(sizeof(small_string<char16_t>) == 6, "");
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.back.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.back.pass.cpp
index 42beb28c47b136..440fd22b0d2870 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.back.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.back.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -29,6 +30,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cback.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cback.pass.cpp
index 7a3d3e1661636a..43db2bdcfeaa10 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cback.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cback.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -29,6 +30,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cfront.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cfront.pass.cpp
index 66432dc099b5ff..78b053a9e49070 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cfront.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cfront.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -29,6 +30,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cindex.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cindex.pass.cpp
index 41bb48b6f574c8..93f59ebabb1f77 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.cindex.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.cindex.pass.cpp
@@ -20,6 +20,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -31,6 +32,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.front.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.front.pass.cpp
index 1033e17961b242..1934e926c37243 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.front.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.front.pass.cpp
@@ -20,6 +20,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -30,6 +31,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.access/assert.index.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.access/assert.index.pass.cpp
index 776bba32da184d..af5207b93b1c3d 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.access/assert.index.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.access/assert.index.pass.cpp
@@ -20,6 +20,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -31,6 +32,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp
index 8415214efa8b8b..8fab5dd67edb62 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp
@@ -30,6 +30,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 bool test() {
@@ -74,6 +75,7 @@ int main(int, char**) {
 
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
 #if TEST_STD_VER > 17
diff --git a/libcxx/test/libcxx/strings/basic.string/string.cons/copy_shrunk_long.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.cons/copy_shrunk_long.pass.cpp
index d4a0b318f36d72..6eea24490f8965 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.cons/copy_shrunk_long.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.cons/copy_shrunk_long.pass.cpp
@@ -34,12 +34,13 @@ TEST_CONSTEXPR_CXX20 bool test() {
 int main(int, char**) {
   test<std::basic_string<char, std::char_traits<char>, test_allocator<char> > >();
 #if TEST_STD_VER >= 11
-  test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 #if TEST_STD_VER > 17
-  static_assert(test<std::basic_string<char, std::char_traits<char>, test_allocator<char>>>());
-  static_assert(test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>());
+  static_assert(test<std::basic_string<char, std::char_traits<char>, test_allocator<char> > >());
+  static_assert(test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >());
+  static_assert(test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >());
 #endif
-
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.add.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.add.pass.cpp
index 8459284637dc50..c78ac207f46744 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.add.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.add.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class C>
 void test() {
@@ -32,6 +33,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.compare.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.compare.pass.cpp
index c55410edf4ebac..aa99d18a0c2014 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.compare.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.compare.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -28,6 +29,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.decrement.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.decrement.pass.cpp
index f1fa08d006a1e0..dd0a7420bde8da 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.decrement.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.decrement.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class C>
 void test() {
@@ -31,6 +32,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.dereference.pass.cpp
index 0bf295c6c4f4fb..8fab28beb80e63 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.dereference.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class C>
 void test() {
@@ -28,6 +29,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.increment.pass.cpp
index 9cc9ab40bcdd65..0c68b416f2ad21 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.increment.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class C>
 void test() {
@@ -31,6 +32,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.index.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.index.pass.cpp
index 34060065d20466..4d9aa1a0cc233a 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.index.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.index.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class C>
 void test() {
@@ -31,6 +32,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.subtract.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.subtract.pass.cpp
index d3274cbd90cc50..2f60065dc324b2 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.subtract.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.iterators/debug.iterator.subtract.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -28,6 +29,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.erase_iter.null.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.erase_iter.null.pass.cpp
index 0b4cb9db51c94c..f5fa9d8537cbb5 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.erase_iter.null.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.erase_iter.null.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -30,6 +31,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.pop_back.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.pop_back.pass.cpp
index 2bab67bdc3edc5..2dd03f84e4fcd0 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.pop_back.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/assert.pop_back.pass.cpp
@@ -18,6 +18,7 @@
 #include <string>
 
 #include "check_assertion.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -27,6 +28,7 @@ void test() {
 
 int main(int, char**) {
   test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter.pass.cpp
index 93fd6caf0ba236..4fc4be6bfaf673 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -30,6 +31,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter_iter.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter_iter.pass.cpp
index ed97e21d9411e6..29954095f3b228 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter_iter.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.erase.iter_iter.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "check_assertion.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -56,6 +57,7 @@ void test() {
 int main(int, char**) {
   test<std::string>();
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_char.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_char.pass.cpp
index 561f79e0e18fb8..946839aea66123 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_char.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_char.pass.cpp
@@ -22,6 +22,7 @@
 #include <string>
 
 #include "check_assertion.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -34,6 +35,7 @@ void test() {
 
 int main(int, char**) {
   test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_iter_iter.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_iter_iter.pass.cpp
index eef525349972b9..baff22ee85a449 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_iter_iter.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_iter_iter.pass.cpp
@@ -17,6 +17,7 @@
 #include <string>
 
 #include "check_assertion.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -30,6 +31,7 @@ void test() {
 
 int main(int, char**) {
   test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_size_char.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_size_char.pass.cpp
index 4b7532678f2e57..4b1ed1b82ebade 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_size_char.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/debug.insert.iter_size_char.pass.cpp
@@ -16,6 +16,7 @@
 #include <string>
 
 #include "check_assertion.h"
+#include "test_allocator.h"
 
 template <class S>
 void test() {
@@ -27,6 +28,7 @@ void test() {
 
 int main(int, char**) {
   test<std::string>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp
index 8e6e07d659c1a0..5cc22c4ddfdaf5 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/resize_default_initialized.pass.cpp
@@ -14,6 +14,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 TEST_CONSTEXPR_CXX20 void write_c_str(char* buf, int size) {
   for (int i = 0; i < size; ++i) {
@@ -67,8 +68,13 @@ TEST_CONSTEXPR_CXX20 bool test() {
 
 int main(int, char**) {
   test<std::string>();
+#if TEST_STD_VER >= 11
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
+#endif
+
 #if TEST_STD_VER > 17
   static_assert(test<std::string>());
+  static_assert(test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >());
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string.hash/enabled_hashes.pass.cpp b/libcxx/test/std/strings/basic.string.hash/enabled_hashes.pass.cpp
index 611f95f0d3ef6e..3f382225859cbe 100644
--- a/libcxx/test/std/strings/basic.string.hash/enabled_hashes.pass.cpp
+++ b/libcxx/test/std/strings/basic.string.hash/enabled_hashes.pass.cpp
@@ -63,6 +63,7 @@ int main(int, char**) {
     test_hash_enabled_for_type<std::u16string>();
     test_hash_enabled_for_type<std::u32string>();
     test_hash_enabled_for_type<std::basic_string<char, std::char_traits<char>, test_allocator<char>>>();
+    test_hash_enabled_for_type<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
     test_hash_disabled_for_type<std::basic_string<MyChar, std::char_traits<MyChar>, std::allocator<MyChar>>>();
     test_hash_disabled_for_type<std::basic_string<char, constexpr_char_traits<char>, std::allocator<char>>>();
   }
diff --git a/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
index 52c0646c7d7c56..f1ffeffb11eaee 100644
--- a/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/at.pass.cpp
@@ -16,6 +16,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "make_string.h"
 #include "test_macros.h"
@@ -61,6 +62,7 @@ struct TestCaller {
     test_string<std::basic_string<T> >();
 #if TEST_STD_VER >= 11
     test_string<std::basic_string<T, std::char_traits<T>, min_allocator<T> > >();
+    test_string<std::basic_string<T, std::char_traits<T>, fancy_pointer_allocator<T> > >();
 #endif
   }
 };
diff --git a/libcxx/test/std/strings/basic.string/string.access/back.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/back.pass.cpp
index 2f0c282c8e4365..bcf76d6aa6998e 100644
--- a/libcxx/test/std/strings/basic.string/string.access/back.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/back.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -40,6 +41,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.access/front.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/front.pass.cpp
index 809b0399dc70fd..aad6f2db6b7b33 100644
--- a/libcxx/test/std/strings/basic.string/string.access/front.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/front.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -40,6 +41,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp
index 8ba8bf0c8b096b..9604da6d161e72 100644
--- a/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test_string() {
@@ -59,6 +60,8 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string_long<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
+  test_string_long<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/clear.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/clear.pass.cpp
index 643ea4a3bdad48..a768c495d37167 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/clear.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/clear.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -48,6 +49,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/empty.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/empty.pass.cpp
index b4700d68a59af2..c8a4914ec3dbbc 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/empty.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/empty.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s) {
@@ -33,6 +34,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/length.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/length.pass.cpp
index e873f82c4830b6..0f0ff13a67d1c5 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/length.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/length.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s) {
@@ -32,6 +33,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/max_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/max_size.pass.cpp
index 52dbde45dbb265..1e0d88e67df467 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/max_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/max_size.pass.cpp
@@ -24,6 +24,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test_resize_max_size_minus_1(const S& s) {
@@ -84,6 +85,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/over_max_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/over_max_size.pass.cpp
index 0b459f9625689e..f3ebef401f2fdc 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/over_max_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/over_max_size.pass.cpp
@@ -24,6 +24,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test(const S& s) {
@@ -49,6 +50,7 @@ bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/reserve.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/reserve.pass.cpp
index 43414da3794a5f..928b87007af4db 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/reserve.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/reserve.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 void test(typename S::size_type min_cap, typename S::size_type erased_index) {
@@ -50,6 +51,7 @@ bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/reserve_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/reserve_size.pass.cpp
index 30c171680a23c4..08fc78aecc90f0 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/reserve_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/reserve_size.pass.cpp
@@ -21,6 +21,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -81,6 +82,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp
index edc8b67808b856..aa1df49554ba43 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp
@@ -20,6 +20,7 @@
 #include "make_string.h"
 #include "test_macros.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 constexpr void test_appending(std::size_t k, size_t N, size_t new_capacity) {
@@ -91,18 +92,35 @@ void test_value_categories() {
 
 int main(int, char**) {
   test<std::basic_string<char, std::char_traits<char>, std::allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
+
   test<std::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t>>>();
+  test<std::basic_string<char8_t, std::char_traits<char8_t>, fancy_pointer_allocator<char8_t>>>();
+
   test<std::basic_string<char16_t, std::char_traits<char16_t>, std::allocator<char16_t>>>();
+  test<std::basic_string<char16_t, std::char_traits<char16_t>, fancy_pointer_allocator<char16_t>>>();
+
   test<std::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t>>>();
+  test<std::basic_string<char32_t, std::char_traits<char32_t>, fancy_pointer_allocator<char32_t>>>();
 
   static_assert(test<std::basic_string<char, std::char_traits<char>, std::allocator<char>>>());
+  static_assert(test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>());
+
   static_assert(test<std::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t>>>());
+  static_assert(test<std::basic_string<char8_t, std::char_traits<char8_t>, fancy_pointer_allocator<char8_t>>>());
+
   static_assert(test<std::basic_string<char16_t, std::char_traits<char16_t>, std::allocator<char16_t>>>());
+  static_assert(test<std::basic_string<char16_t, std::char_traits<char16_t>, fancy_pointer_allocator<char16_t>>>());
+
   static_assert(test<std::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t>>>());
+  static_assert(test<std::basic_string<char32_t, std::char_traits<char32_t>, fancy_pointer_allocator<char32_t>>>());
 
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
   test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>();
+  test<std::basic_string<wchar_t, std::char_traits<wchar_t>, fancy_pointer_allocator<wchar_t>>>();
+
   static_assert(test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>());
+  static_assert(test<std::basic_string<wchar_t, std::char_traits<wchar_t>, fancy_pointer_allocator<wchar_t>>>());
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_size.pass.cpp
index 7cf4b7ca3b6efd..cb2223f889b8f0 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/resize_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_size.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, S expected) {
@@ -64,6 +65,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_size_char.pass.cpp
index e3b925ca8bcdbd..1792c109aa445e 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/resize_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_size_char.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, typename S::value_type c, S expected) {
@@ -76,6 +77,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
index 057050cdcf7fa3..80e25bba8fe335 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -58,6 +59,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/size.pass.cpp
index 9d53971779b648..e1be04a13427c5 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s, typename S::size_type c) {
@@ -32,6 +33,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/T_size_size.pass.cpp
index dcf697bed752fa..0b1b6b5e17589e 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/T_size_size.pass.cpp
@@ -116,6 +116,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>());
   test_string(safe_allocator<char>());
+  test_string(fancy_pointer_allocator<char>());
 #endif
 
   {
diff --git a/libcxx/test/std/strings/basic.string/string.cons/alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/alloc.pass.cpp
index 91beac37764db4..960a2ba9abafe9 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/alloc.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test() {
@@ -95,6 +96,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test2<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test2<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test2<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   test2<std::basic_string<char, std::char_traits<char>, explicit_allocator<char> > >();
 #endif
 
diff --git a/libcxx/test/std/strings/basic.string/string.cons/char_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/char_assignment.pass.cpp
index 1019dc8bca5df5..7c36a3aca38542 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/char_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/char_assignment.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s1, typename S::value_type s2) {
@@ -41,6 +42,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/copy.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/copy.pass.cpp
index f65f8e97c98249..ac40221986685b 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/copy.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/copy.pass.cpp
@@ -44,6 +44,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>());
   test_string(safe_allocator<char>());
+  test_string(fancy_pointer_allocator<char>());
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/copy_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/copy_alloc.pass.cpp
index b0045cb4afbba5..ba4d4bac299542 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/copy_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/copy_alloc.pass.cpp
@@ -102,7 +102,6 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string(test_allocator<char>(3));
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>());
-  test_string(safe_allocator<char>());
 #endif
 
 #if TEST_STD_VER >= 11
diff --git a/libcxx/test/std/strings/basic.string/string.cons/copy_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/copy_assignment.pass.cpp
index 2e98fccb5394bb..e0689a36a96848 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/copy_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/copy_assignment.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s1, const S& s2) {
@@ -51,6 +52,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
 #if TEST_STD_VER >= 11
diff --git a/libcxx/test/std/strings/basic.string/string.cons/default.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/default.pass.cpp
index fc263f9820cb5b..5d72d5bf316f53 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/default.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/default.pass.cpp
@@ -23,6 +23,9 @@ LIBCPP_STATIC_ASSERT(std::is_nothrow_default_constructible<std::string>::value,
 LIBCPP_STATIC_ASSERT(std::is_nothrow_default_constructible<
                          std::basic_string<char, std::char_traits<char>, test_allocator<char>>>::value,
                      "");
+LIBCPP_STATIC_ASSERT(std::is_nothrow_default_constructible<
+                         std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>::value,
+                     "");
 LIBCPP_STATIC_ASSERT(!std::is_nothrow_default_constructible<
                          std::basic_string<char, std::char_traits<char>, limited_allocator<char, 10>>>::value,
                      "");
diff --git a/libcxx/test/std/strings/basic.string/string.cons/dtor.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/dtor.pass.cpp
index e9f174068473d5..ab799e80904840 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/dtor.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/dtor.pass.cpp
@@ -36,6 +36,9 @@ std::wstring unused_wide_string;
 static_assert(std::is_nothrow_destructible<std::string>::value, "");
 static_assert(
     std::is_nothrow_destructible< std::basic_string<char, std::char_traits<char>, test_allocator<char>>>::value, "");
+static_assert(std::is_nothrow_destructible<
+                  std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>::value,
+              "");
 LIBCPP_STATIC_ASSERT(
     !std::is_nothrow_destructible< std::basic_string<char, std::char_traits<char>, throwing_alloc<char>>>::value, "");
 
diff --git a/libcxx/test/std/strings/basic.string/string.cons/initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/initializer_list.pass.cpp
index ebdcc523f055d4..df7776059bab94 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/initializer_list.pass.cpp
@@ -52,6 +52,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::allocator>();
   test_string<min_allocator>();
   test_string<safe_allocator>();
+  test_string<fancy_pointer_allocator>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.cons/initializer_list_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/initializer_list_assignment.pass.cpp
index a3491696a4fc8a..4c29f9e667adc4 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/initializer_list_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/initializer_list_assignment.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 // clang-format off
 template <template <class> class Alloc>
@@ -66,6 +67,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::allocator>();
   test_string<min_allocator>();
   test_string<safe_allocator>();
+  test_string<fancy_pointer_allocator>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp
index e14227d1a77171..4cac882d5d5e01 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc.pass.cpp
@@ -93,6 +93,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string(test_allocator<char>(2));
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>());
+  test_string(fancy_pointer_allocator<char>());
 #endif
   {
     static_assert((!std::is_constructible<std::string, std::string, std::string>::value), "");
diff --git a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.pass.cpp
index d9176da63d0dc7..c630889ded88f3 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/iter_alloc_deduction.pass.cpp
@@ -104,6 +104,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
     LIBCPP_ASSERT(is_string_asan_correct(s1));
   }
+  {
+    const char16_t* s = u"12345678901234";
+    std::basic_string s1{s, s + 10, fancy_pointer_allocator<char16_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char16_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char16_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char16_t>>, "");
+    assert(s1.size() == 10);
+    assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
+  }
   {
     const char32_t* s = U"12345678901234";
     std::basic_string s1{s, s + 10, explicit_allocator<char32_t>{}};
@@ -115,6 +125,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
     LIBCPP_ASSERT(is_string_asan_correct(s1));
   }
+  {
+    const char32_t* s = U"12345678901234";
+    std::basic_string s1{s, s + 10, fancy_pointer_allocator<char32_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char32_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char32_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char32_t>>, "");
+    assert(s1.size() == 10);
+    assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
+  }
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move.pass.cpp
index 5d2d774b360638..6238322471be89 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/move.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move.pass.cpp
@@ -47,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string(test_allocator<char>());
   test_string(test_allocator<char>(3));
   test_string(min_allocator<char>());
+  test_string(fancy_pointer_allocator<char>());
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp
index 7210d67b5cb226..48b33f32ba120e 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_alloc.pass.cpp
@@ -74,6 +74,18 @@ TEST_CONSTEXPR_CXX20 bool test() {
     test(S("1"), A());
     test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
   }
+  {
+    typedef fancy_pointer_allocator<char> A;
+    typedef std::basic_string<char, std::char_traits<char>, A> S;
+#if TEST_STD_VER > 14
+    static_assert((noexcept(S{})), "");
+#elif TEST_STD_VER >= 11
+    static_assert((noexcept(S()) == std::is_nothrow_move_constructible<A>::value), "");
+#endif
+    test(S(), A());
+    test(S("1"), A());
+    test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
+  }
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
index bba86b3acffee8..551de2b3f4a669 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp
@@ -68,6 +68,10 @@ TEST_CONSTEXPR_CXX20 bool test() {
     typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> C;
     static_assert(!std::is_nothrow_move_assignable<C>::value, "");
   }
+  {
+    typedef std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>> C;
+    static_assert(std::is_nothrow_move_assignable<C>::value, "");
+  }
   {
     typedef std::basic_string<char, std::char_traits<char>, some_alloc<char>> C;
 #if TEST_STD_VER > 14
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_assignment.pass.cpp
index 9af9abdfc449cf..1fc87f8a450cbf 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/move_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_assignment.pass.cpp
@@ -57,6 +57,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
index d807cac2c72c84..c408508e8f21a2 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
@@ -30,6 +30,10 @@ int main(int, char**) {
     typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> C;
     static_assert(std::is_nothrow_move_constructible<C>::value, "");
   }
+  {
+    typedef std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>> C;
+    static_assert(std::is_nothrow_move_constructible<C>::value, "");
+  }
   {
     typedef std::basic_string<char, std::char_traits<char>, limited_allocator<char, 10>> C;
 #if TEST_STD_VER <= 14
diff --git a/libcxx/test/std/strings/basic.string/string.cons/pointer_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/pointer_alloc.pass.cpp
index d5d5152e11e54e..f4581b092a8a2d 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/pointer_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/pointer_alloc.pass.cpp
@@ -71,6 +71,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test(min_allocator<char>());
   test(safe_allocator<char>());
+  test(fancy_pointer_allocator<char>());
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/pointer_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/pointer_assignment.pass.cpp
index 98430cdd6ab998..3b5786493588cd 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/pointer_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/pointer_assignment.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s1, const typename S::value_type* s2) {
@@ -52,6 +53,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp
index b6ba2be46d18bd..8a7b4e7317c177 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp
@@ -68,6 +68,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test(min_allocator<char>());
   test(safe_allocator<char>());
+  test(fancy_pointer_allocator<char>());
 #endif
 
 #if TEST_STD_VER >= 11
diff --git a/libcxx/test/std/strings/basic.string/string.cons/size_char_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/size_char_alloc.pass.cpp
index a87e01f0fc0881..12d3a8615c088b 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/size_char_alloc.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/size_char_alloc.pass.cpp
@@ -98,6 +98,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>());
   test_string(safe_allocator<char>());
+  test_string(fancy_pointer_allocator<char>());
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/string_view.pass.cpp
index ad37b50b83ba7e..d2b2494ed7d757 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/string_view.pass.cpp
@@ -99,6 +99,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>());
   test_string(safe_allocator<char>());
+  test_string(fancy_pointer_allocator<char>());
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/string_view_assignment.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/string_view_assignment.pass.cpp
index 2e6c54a584b6e1..2d6a3522a3d943 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/string_view_assignment.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/string_view_assignment.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(S s1, SV sv) {
@@ -52,6 +53,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp
index 3a6f84f2699aca..a5287a23321363 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp
@@ -66,6 +66,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.size() == sv.size());
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::string_view sv = "12345678901234";
+    std::basic_string s1{sv, fancy_pointer_allocator<char>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char>>, "");
+    assert(s1.size() == sv.size());
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
   {
     std::wstring_view sv = L"12345678901234";
@@ -77,6 +87,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.size() == sv.size());
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::wstring_view sv = L"12345678901234";
+    std::basic_string s1{sv, fancy_pointer_allocator<wchar_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, wchar_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<wchar_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<wchar_t>>, "");
+    assert(s1.size() == sv.size());
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
 #endif
 #ifndef TEST_HAS_NO_CHAR8_T
   {
@@ -89,6 +109,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.size() == sv.size());
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::u8string_view sv = u8"12345678901234";
+    std::basic_string s1{sv, fancy_pointer_allocator<char8_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char8_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char8_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char8_t>>, "");
+    assert(s1.size() == sv.size());
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
 #endif
   {
     std::u16string_view sv = u"12345678901234";
@@ -100,6 +130,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.size() == sv.size());
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::u16string_view sv = u"12345678901234";
+    std::basic_string s1{sv, fancy_pointer_allocator<char16_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char16_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char16_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char16_t>>, "");
+    assert(s1.size() == sv.size());
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
   {
     std::u32string_view sv = U"12345678901234";
     std::basic_string s1{sv, explicit_allocator<char32_t>{}};
diff --git a/libcxx/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp
index 08e696b7a091bd..c32bdb748be4de 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp
@@ -73,6 +73,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.size() == 4);
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::string_view sv = "12345678901234";
+    std::basic_string s1{sv, 0, 4, fancy_pointer_allocator<char>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char>>, "");
+    assert(s1.size() == 4);
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
   {
     std::wstring_view sv = L"12345678901234";
@@ -84,6 +94,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.size() == 4);
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::wstring_view sv = L"12345678901234";
+    std::basic_string s1{sv, 0, 4, fancy_pointer_allocator<wchar_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, wchar_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<wchar_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<wchar_t>>, "");
+    assert(s1.size() == 4);
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
 #endif
 #ifndef TEST_HAS_NO_CHAR8_T
   {
@@ -96,6 +116,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.size() == 4);
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::u8string_view sv = u8"12345678901234";
+    std::basic_string s1{sv, 0, 4, fancy_pointer_allocator<char8_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char8_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char8_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char8_t>>, "");
+    assert(s1.size() == 4);
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
 #endif
   {
     std::u16string_view sv = u"12345678901234";
@@ -107,6 +137,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.size() == 4);
     assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
   }
+  {
+    std::u16string_view sv = u"12345678901234";
+    std::basic_string s1{sv, 0, 4, fancy_pointer_allocator<char16_t>{}};
+    using S = decltype(s1); // what type did we get?
+    static_assert(std::is_same_v<S::value_type, char16_t>, "");
+    static_assert(std::is_same_v<S::traits_type, std::char_traits<char16_t>>, "");
+    static_assert(std::is_same_v<S::allocator_type, fancy_pointer_allocator<char16_t>>, "");
+    assert(s1.size() == 4);
+    assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0);
+  }
   {
     std::u32string_view sv = U"12345678901234";
     std::basic_string s1{sv, 0, 4, explicit_allocator<char32_t>{}};
diff --git a/libcxx/test/std/strings/basic.string/string.cons/substr.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/substr.pass.cpp
index cafd9674f4898d..189a43cd206229 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/substr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/substr.pass.cpp
@@ -169,6 +169,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>(), min_allocator<char>());
   test_string(safe_allocator<char>(), safe_allocator<char>());
+  test_string(fancy_pointer_allocator<char>(), fancy_pointer_allocator<char>());
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.cons/substr_rvalue.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/substr_rvalue.pass.cpp
index a9b07a6eb1aa46..e13ab40f086a17 100644
--- a/libcxx/test/std/strings/basic.string/string.cons/substr_rvalue.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.cons/substr_rvalue.pass.cpp
@@ -212,6 +212,7 @@ constexpr void test_allocators() {
   test_string<std::basic_string<CharT, CharTraits, std::allocator<CharT>>>(std::allocator<CharT>{});
   test_string<std::basic_string<CharT, CharTraits, min_allocator<CharT>>>(min_allocator<CharT>{});
   test_string<std::basic_string<CharT, CharTraits, test_allocator<CharT>>>(test_allocator<CharT>{42});
+  test_string<std::basic_string<CharT, CharTraits, fancy_pointer_allocator<CharT>>>(fancy_pointer_allocator<CharT>{});
 }
 
 template <class CharT>
diff --git a/libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp b/libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp
index 658af8e2cd6496..d9ea3c98633fe6 100644
--- a/libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.contains/contains.char.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class S>
 constexpr void test_string() {
@@ -33,6 +34,7 @@ constexpr void test_string() {
 
 constexpr bool test() {
   test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp b/libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp
index 99f400fa0c37b3..ada28b9611d403 100644
--- a/libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.contains/contains.ptr.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class S>
 constexpr void test_string() {
@@ -63,6 +64,7 @@ constexpr void test_string() {
 
 constexpr bool test() {
   test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp
index 619a718794b14e..192702913070a2 100644
--- a/libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.contains/contains.string_view.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class CharT, template <class> class Alloc>
 constexpr void test_string() {
@@ -86,6 +87,7 @@ constexpr void test_string() {
 
 constexpr bool test() {
   test_string<char, std::allocator>();
+  test_string<char, fancy_pointer_allocator>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.char.pass.cpp b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.char.pass.cpp
index a9547ec4f3af3f..734954131a2d9c 100644
--- a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.char.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class S>
 constexpr void test_string() {
@@ -31,6 +32,7 @@ constexpr void test_string() {
 
 constexpr bool test() {
   test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.ptr.pass.cpp b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.ptr.pass.cpp
index 23331967d1c730..006bc7664e6b6d 100644
--- a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.ptr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.ptr.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class S>
 constexpr void test_string() {
@@ -60,6 +61,7 @@ constexpr void test_string() {
 
 constexpr bool test() {
   test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.string_view.pass.cpp
index 683a16a2fc536a..5ee06c31671850 100644
--- a/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ends_with/ends_with.string_view.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class CharT, template <class> class Alloc>
 constexpr void test_string() {
@@ -70,6 +71,7 @@ constexpr void test_string() {
 
 constexpr bool test() {
   test_string<char, std::allocator>();
+  test_string<char, fancy_pointer_allocator>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/begin.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/begin.pass.cpp
index 202a87dd777b3b..0da516f14b65ed 100644
--- a/libcxx/test/std/strings/basic.string/string.iterators/begin.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/begin.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -38,6 +39,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/cbegin.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/cbegin.pass.cpp
index df2c38476197ed..cd3afb59789bd3 100644
--- a/libcxx/test/std/strings/basic.string/string.iterators/cbegin.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/cbegin.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s) {
@@ -35,6 +36,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/cend.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/cend.pass.cpp
index 31d06725e5107d..b794408e5ebee8 100644
--- a/libcxx/test/std/strings/basic.string/string.iterators/cend.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/cend.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s) {
@@ -32,6 +33,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/crbegin.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/crbegin.pass.cpp
index 85b33afeb403eb..84aae817b597e6 100644
--- a/libcxx/test/std/strings/basic.string/string.iterators/crbegin.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/crbegin.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s) {
@@ -35,6 +36,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/crend.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/crend.pass.cpp
index 5d1f90c409bc40..3e40a30f750384 100644
--- a/libcxx/test/std/strings/basic.string/string.iterators/crend.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/crend.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s) {
@@ -32,6 +33,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/end.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/end.pass.cpp
index 2c3e3b12872157..2a72ed0326efd8 100644
--- a/libcxx/test/std/strings/basic.string/string.iterators/end.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/end.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -41,6 +42,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/rbegin.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/rbegin.pass.cpp
index feaea2f65790c7..c07ccb1faf6c20 100644
--- a/libcxx/test/std/strings/basic.string/string.iterators/rbegin.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/rbegin.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -38,6 +39,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.iterators/rend.pass.cpp b/libcxx/test/std/strings/basic.string/string.iterators/rend.pass.cpp
index d34ee26fd9d04b..1e20f95cd9d987 100644
--- a/libcxx/test/std/strings/basic.string/string.iterators/rend.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.iterators/rend.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -41,6 +42,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp
index a02b455ce1fe62..9802838609327a 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/robust_against_adl.pass.cpp
@@ -12,6 +12,7 @@
 #include <string>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 struct Incomplete;
 template <class T>
@@ -39,6 +40,9 @@ TEST_CONSTEXPR_CXX20 void test_string() {
 
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
+#if TEST_STD_VER >= 11
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
+#endif
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/T_size_size.pass.cpp
index e43c36c31e483b..6a70e0c17ae1a2 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/T_size_size.pass.cpp
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(S s, SV sv, typename S::size_type pos, typename S::size_type n, S expected) {
@@ -91,6 +92,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   {
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/initializer_list.pass.cpp
index f1f5828bfe21d7..0ebfe2974e1c79 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/initializer_list.pass.cpp
@@ -19,6 +19,7 @@
 #include "min_allocator.h"
 #include "nasty_string.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test() {
@@ -43,6 +44,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #ifndef TEST_HAS_NO_NASTY_STRING
   test<nasty_string>();
 #endif
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp
index 684661aeab8fc3..db3cf93423f377 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/iterator.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "test_allocator.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
 
@@ -228,6 +229,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp
index af334eb080c37e..5db5ae70b2caab 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, S expected) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test appending to self
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp
index 93e7500a11967c..bff361363d9cee 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer_size.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, typename S::size_type n, S expected) {
@@ -51,6 +52,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test appending to self
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/push_back.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/push_back.pass.cpp
index a352b4cf9b92e6..7f3de71a512246 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/push_back.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/push_back.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 struct VeryLarge {
   long long a;
@@ -81,6 +82,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
   {
     // https://llvm.org/PR31454
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/size_char.pass.cpp
index a898efcf21855f..b305c939a237a6 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/size_char.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, typename S::value_type c, S expected) {
@@ -52,6 +53,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp
index 66a2dc26341f84..04eb83f692de54 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, S str, S expected) {
@@ -62,6 +63,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #if TEST_STD_VER >= 11
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_size_size.pass.cpp
index d30f13d96b5b87..16bdadba023b8e 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_size_size.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, S str, typename S::size_type pos, typename S::size_type n, S expected) {
@@ -97,6 +98,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   {
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_view.pass.cpp
index 9de48ca2463e2f..d4d6e62a939646 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_view.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(S s, SV sv, S expected) {
@@ -61,6 +62,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/T_size_size.pass.cpp
index b35f6b9497d03b..76483022754181 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/T_size_size.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(S s, SV sv, typename S::size_type pos, typename S::size_type n, S expected) {
@@ -88,6 +89,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   {
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/initializer_list.pass.cpp
index 47a59e8997e62e..a4da91fc1f7cc1 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/initializer_list.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test_string() {
@@ -39,10 +40,9 @@ TEST_CONSTEXPR_CXX20 void test_string() {
 
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
-#if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
-#endif
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp
index c183def9ee75fe..653904a766da5a 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/iterator.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_iterators.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S, class It>
 TEST_CONSTEXPR_CXX20 void test(S s, It first, It last, S expected) {
@@ -174,6 +175,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp
index 0d5c269d30df47..8549f137a946e9 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, S expected) {
@@ -51,6 +52,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test assignment to self
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp
index 1f40898b71bfeb..810032708b19b2 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer_size.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, typename S::size_type n, S expected) {
@@ -57,6 +58,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test assign to self
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/rv_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/rv_string.pass.cpp
index a33e8e97157c40..cf87524b0d9fd1 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/rv_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/rv_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, S str, S expected) {
@@ -52,6 +53,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/size_char.pass.cpp
index 3c7651135f1aa1..8b0dd89648baa8 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/size_char.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type n, typename S::value_type c, S expected) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp
index 8b310630bf07ab..7784154c721e19 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp
@@ -107,6 +107,14 @@ TEST_CONSTEXPR_CXX20 bool test() {
     testAlloc(S(), S("1234567890"), min_allocator<char>());
     testAlloc(S(), S("12345678901234567890"), min_allocator<char>());
   }
+  {
+    typedef std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>> S;
+    test_assign<S>();
+    testAlloc(S(), S(), fancy_pointer_allocator<char>());
+    testAlloc(S(), S("12345"), fancy_pointer_allocator<char>());
+    testAlloc(S(), S("1234567890"), fancy_pointer_allocator<char>());
+    testAlloc(S(), S("12345678901234567890"), fancy_pointer_allocator<char>());
+  }
 #endif
 #if TEST_STD_VER > 14
   {
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_size_size.pass.cpp
index 1cd2368b2a6b3f..efd7909643e43a 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_size_size.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, S str, typename S::size_type pos, typename S::size_type n, S expected) {
@@ -88,6 +89,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   {
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_view.pass.cpp
index aeda9db36a840e..3ff71a929ba6de 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_view.pass.cpp
@@ -69,6 +69,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_copy/copy.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_copy/copy.pass.cpp
index 0d7221ced8034f..67729e30c492c6 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_copy/copy.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_copy/copy.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S str, typename S::value_type* s, typename S::size_type n, typename S::size_type pos) {
@@ -115,6 +116,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
index b724973150296b..68f90e5dfa569f 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, S expected) {
@@ -49,6 +50,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
index 5270335aa9ff3d..8d46e61b774768 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, typename S::difference_type n, S expected) {
@@ -92,6 +93,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
index f52512231e094d..619aea72aa316b 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, S expected) {
@@ -40,6 +41,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
index 97acffd484e646..c51c9497aaf32e 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, typename S::size_type n, S expected) {
@@ -183,6 +184,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp
index 1d8c7e06ed8c36..37911f54e4ecc9 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S& s, typename S::const_iterator p, typename S::value_type c, S expected) {
@@ -74,6 +75,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp
index 769bd7c4274ff4..1ec1c493a7e362 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test_string() {
@@ -37,6 +38,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
index 060216e7a82b30..efe3a84075df7b 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_iterators.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S, class It>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, It first, It last, S expected) {
@@ -150,6 +151,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #ifndef TEST_HAS_NO_EXCEPTIONS
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp
index 6937ccc0d540a4..3f24c630c886b2 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -101,6 +102,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_T_size_size.pass.cpp
index f7e6ca71180e33..b0a19f977d4d59 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_T_size_size.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -1858,6 +1859,8 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>,
        std::basic_string_view<char, std::char_traits<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>,
+       std::basic_string_view<char, std::char_traits<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp
index 9e2d00279b96d6..c42e26fb051399 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, const typename S::value_type* str, S expected) {
@@ -131,6 +132,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test inserting into self
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp
index 3e581b56a63901..f04d365e28bda4 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -391,11 +392,13 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #if TEST_STD_VER > 17
   static_assert(test<std::string>());
   static_assert(test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>());
+  static_assert(test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>());
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_size_char.pass.cpp
index f18ef484b5a047..e13083a389fc4b 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_size_char.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -132,6 +133,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp
index 49870ba05e3572..62724e038a81ec 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, S str, S expected) {
@@ -131,6 +132,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
 #if TEST_STD_VER >= 11
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string_size_size.pass.cpp
index 2c0579485d0fb5..14cf20085a515b 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_string_size_size.pass.cpp
@@ -20,6 +20,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -1819,6 +1820,7 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/string_view.pass.cpp
index 7c0f157bc32300..699b88bec5813f 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/string_view.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos, SV sv, S expected) {
@@ -129,6 +130,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   { // test inserting into self
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/char.pass.cpp
index 753c38fa232b3a..c049eb1eb6c29f 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/char.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::value_type str, S expected) {
@@ -39,6 +40,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/initializer_list.pass.cpp
index 165fb2f96313b3..14e9610ac2412f 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/initializer_list.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test_string() {
@@ -45,6 +46,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   return true;
 }
 
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/pointer.pass.cpp
index 4231b0c6cd8d62..c260e3da8274b1 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/pointer.pass.cpp
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, S expected) {
@@ -63,6 +64,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp
index 0aee67f27fb056..dbbcda9dd32404 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, S str, S expected) {
@@ -64,6 +65,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   { // LWG 2946
     std::string s;
     s += {"abc", 1};
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_initializer_list.pass.cpp
index efc21725ee24cd..41210a319bd3b0 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_initializer_list.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_initializer_list.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test_string() {
@@ -28,6 +29,7 @@ TEST_CONSTEXPR_CXX20 void test_string() {
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp
index c1ca532a5f910f..3a2f12d31b162d 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "test_iterators.h"
+#include "test_allocator.h"
 
 template <class S, class It>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size_type n1, It f, It l, S expected) {
@@ -1064,6 +1065,7 @@ int main(int, char**) {
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp
index fa13ca8062b2a3..a7793fae3763bb 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -299,6 +300,7 @@ int main(int, char**) {
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp
index 45d57c793a3352..2ddf6ffe55be9b 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -1004,6 +1005,7 @@ int main(int, char**) {
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp
index dd87da1e253546..4cd17627be91cb 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -285,7 +286,8 @@ int main(int, char**) {
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return 0;
-}
+}
\ No newline at end of file
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp
index eb0c62a66504ce..5c28589e7ca321 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size_type n1, S str, S expected) {
@@ -295,6 +296,7 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string_view.pass.cpp
index 767ed41ae22477..d741aa0c0062cf 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string_view.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size_type n1, SV sv, S expected) {
@@ -283,6 +284,7 @@ int main(int, char**) {
   test<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test<char, min_allocator>();
+  test<char, fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_T_size_size.pass.cpp
index df08ae675a11e5..8c25ce94922a2d 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_T_size_size.pass.cpp
@@ -24,6 +24,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -6282,6 +6283,7 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<char, min_allocator>();
   test<char, safe_allocator>();
+  test<char, fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer.pass.cpp
index aefe3ced9765ef..f60cab2e588110 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -380,6 +381,7 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer_size.pass.cpp
index cb01c34e43d4aa..9cf1696799356f 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer_size.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -1344,6 +1345,7 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_size_char.pass.cpp
index 67e93167942250..f024da04cb95da 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_size_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_size_char.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -384,6 +385,7 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp
index 47fe7030c83b35..9aba8dabcbde36 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size_type n1, S str, S expected) {
@@ -388,6 +389,7 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_size_size.pass.cpp
index 48645f62809909..dc1c026c0de516 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_size_size.pass.cpp
@@ -23,6 +23,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -6102,6 +6103,7 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_view.pass.cpp
index 7f17160419065c..97987eae72afc3 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_view.pass.cpp
@@ -19,6 +19,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::size_type pos1, typename S::size_type n1, SV sv, S expected) {
@@ -379,6 +380,7 @@ int main(int, char**) {
 #if TEST_STD_VER >= 11
   test<char, min_allocator>();
   test<char, safe_allocator>();
+  test<char, fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
index 16bdac1c4dcc63..ea166e3ca7ef51 100644
--- a/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
@@ -14,6 +14,7 @@
 #include <stdexcept>
 #include <algorithm>
 #include <cassert>
+#include "test_allocator.h"
 
 #include "test_macros.h"
 #include "min_allocator.h"
@@ -62,6 +63,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line.pass.cpp
index 7bcb34135440bf..45a5e3d9248549 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "min_allocator.h"
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <template <class> class Alloc>
 void test_string() {
@@ -144,6 +145,7 @@ int main(int, char**) {
   test_string<std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<min_allocator>();
+  test_string<fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim.pass.cpp
index 97a55fa09d14df..87962e85cdf1ce 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "min_allocator.h"
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <template <class> class Alloc>
 void test_string() {
@@ -150,6 +151,7 @@ int main(int, char**) {
   test_string<std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<min_allocator>();
+  test_string<fancy_pointer_allocator>();
 #endif
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim_rv.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim_rv.pass.cpp
index 1cd50a4c8940c7..275274606e60e2 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim_rv.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_delim_rv.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <template <class> class Alloc>
 void test() {
@@ -42,6 +43,7 @@ int main(int, char**) {
   test<std::allocator>();
 #if TEST_STD_VER >= 11
   test<min_allocator>();
+  test<fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_rv.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_rv.pass.cpp
index ff100f9234bef0..dac37ff415388a 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_rv.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line_rv.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <template <class> class Alloc>
 void test() {
@@ -41,6 +42,9 @@ void test() {
 int main(int, char**) {
   test<std::allocator>();
   test<min_allocator>();
+#if TEST_STD_VER >= 11
+  test<fancy_pointer_allocator>();
+#endif // TEST_STD_VER >= 11
 
   return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_extract.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_extract.pass.cpp
index fde4990c9cafb2..e04f11b1150152 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_extract.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_extract.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "min_allocator.h"
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <template <class> class Alloc>
 void test_string() {
@@ -115,6 +116,7 @@ int main(int, char**) {
   test_string<std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<min_allocator>();
+  test_string<fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_insert.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_insert.pass.cpp
index c66f15213ff2f0..89b46d41a5e7af 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_insert.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/stream_insert.pass.cpp
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <template <class> class Alloc>
 void test() {
@@ -65,6 +66,7 @@ int main(int, char**) {
 
 #if TEST_STD_VER >= 11
   test<min_allocator>();
+  test<fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap.pass.cpp
index c807007fea3528..8995477d9955df 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string.special/swap.pass.cpp
@@ -20,6 +20,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
@@ -63,6 +64,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/pointer_string.pass.cpp
index 11cfcfcf429957..bd77ce2e59ea73 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const typename S::value_type* lhs, const S& rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_pointer.pass.cpp
index c04c06243cd258..c7429e8cc1c702 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const typename S::value_type* rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string.pass.cpp
index 881770e421bb04..5081cc6958257d 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string_view.pass.cpp
index 1595ec501f4e90..da6a3c86fbb4e7 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, SV rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_view_string.pass.cpp
index 246b98bc5e107c..35bd322002cdc5 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(SV lhs, const S& rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/char_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/char_string.pass.cpp
index 2ca5788e6d8a30..585e6b47aee23f 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/char_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/char_string.pass.cpp
@@ -23,6 +23,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(typename S::value_type lhs, const S& rhs, const S& x) {
@@ -56,6 +57,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/pointer_string.pass.cpp
index fa14f657d8269c..772fefcef42124 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/pointer_string.pass.cpp
@@ -22,6 +22,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(const typename S::value_type* lhs, const S& rhs, const S& x) {
@@ -78,6 +79,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_char.pass.cpp
index 9c0fb56e1f1c99..dc13b61a025032 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_char.pass.cpp
@@ -23,6 +23,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(const S& lhs, typename S::value_type rhs, const S& x) {
@@ -58,6 +59,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_pointer.pass.cpp
index 3e1aaebf112eb5..723a9d187594a9 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_pointer.pass.cpp
@@ -23,6 +23,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(const S& lhs, const typename S::value_type* rhs, const S& x) {
@@ -80,6 +81,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_string.pass.cpp
index fcc8ceab870715..14d2b115b06d5a 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string_string.pass.cpp
@@ -35,6 +35,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "asan_testing.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(const S& lhs, const S& rhs, const S& x) {
@@ -136,6 +137,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/pointer_string.pass.cpp
index a8114af2600cad..e32beb04f45dee 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const typename S::value_type* lhs, const S& rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_pointer.pass.cpp
index 8e67e6e81a6e91..b5c4417fc7a82c 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const typename S::value_type* rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string.pass.cpp
index 31bace312f1df8..6f08981e51f5fa 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string_view.pass.cpp
index c758c4adfe6042..9cd603eaa60071 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, SV rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_view_string.pass.cpp
index 39dd627033c485..86615394ce32ab 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(SV lhs, const S& rhs, bool x) {
@@ -48,6 +49,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/pointer_string.pass.cpp
index ce0fbf55b5c511..8fb70310cb3f15 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const typename S::value_type* lhs, const S& rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_pointer.pass.cpp
index 2a77947bc7febe..79468cf9ac5a40 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const typename S::value_type* rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string.pass.cpp
index 794f9e76b4e857..b799d1773a8ac8 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string_view.pass.cpp
index de06981bb47870..43926e53404f87 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, SV rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_view_string.pass.cpp
index 8026777a88db19..c5525240e63eb3 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(SV lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/pointer_string.pass.cpp
index 35d3c69785325a..0774e120e4f94e 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const typename S::value_type* lhs, const S& rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_pointer.pass.cpp
index 3f8883e358da56..50279392b934d5 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const typename S::value_type* rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string.pass.cpp
index 1dc65bf0b6db09..af17ea82748d98 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string_view.pass.cpp
index 19c96ffb77e79d..54fb2f9b174d22 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, SV rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_view_string.pass.cpp
index d55b2f8fd34be4..c70a90ac4de474 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_opgt=/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(SV lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/pointer_string.pass.cpp
index 0c4dbe2f9193b9..abeebad52977b1 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const typename S::value_type* lhs, const S& rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_pointer.pass.cpp
index bcdb1091140dfc..b0a7c29cd8bdae 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const typename S::value_type* rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string.pass.cpp
index 6ca1dd27f31ab6..4f835fdeef2a7b 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string_view.pass.cpp
index 56549d17677364..4d39b0baf1b2b7 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, SV rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_view_string.pass.cpp
index 72e9d4bf96682a..9c8503bd2b9342 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(SV lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/pointer_string.pass.cpp
index 85c6f04ecc2c14..03679cc700f9f5 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/pointer_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/pointer_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const typename S::value_type* lhs, const S& rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_pointer.pass.cpp
index 16db9337823297..1689f13dc46d59 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_pointer.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const typename S::value_type* rhs, bool x) {
@@ -46,6 +47,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string.pass.cpp
index a9700141779156..33c6a1e2f3276b 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string.pass.cpp
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string_view.pass.cpp
index 2ee253820c11e9..24db2ba6c75d14 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& lhs, SV rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_view_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_view_string.pass.cpp
index 88951e4da9101b..a9b74e72c222fe 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_view_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_oplt=/string_view_string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(SV lhs, const S& rhs, bool x) {
@@ -47,6 +48,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/c_str.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/c_str.pass.cpp
index 837599ae9ef551..a7053de9512df5 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/c_str.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/c_str.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s) {
@@ -39,6 +40,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/data.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/data.pass.cpp
index 27762fbd9390d5..d03f03e05fbd5c 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/data.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/data.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test_const(const S& s) {
@@ -63,6 +64,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/get_allocator.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/get_allocator.pass.cpp
index a6158aeb38dc2e..1d552345f06aba 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string.accessors/get_allocator.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string.accessors/get_allocator.pass.cpp
@@ -39,6 +39,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string(test_allocator<char>(3));
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>());
+  test_string(fancy_pointer_allocator<char>());
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp
index e1d23924517ffb..edf335538910ac 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/pointer.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 TEST_CONSTEXPR_CXX20 int sign(int x) {
   if (x == 0)
@@ -54,6 +55,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_T_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_T_size_size.pass.cpp
index c6281d9e377f47..b073873baf2772 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_T_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_T_size_size.pass.cpp
@@ -19,6 +19,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -6044,6 +6045,7 @@ int main(int, char**) {
   test<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test<char, min_allocator>();
+  test<char, fancy_pointer_allocator>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer.pass.cpp
index d4a5133ed3907f..2f44efa443aed5 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -362,6 +363,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer_size.pass.cpp
index aba230d92e1824..c9979cf1dbb7f4 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -1339,6 +1340,7 @@ int main(int, char**) {
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp
index 018daaa2f262e4..597528472b33e5 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 TEST_CONSTEXPR_CXX20 int sign(int x) {
   if (x == 0)
@@ -369,6 +370,7 @@ int main(int, char**) {
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   { // LWG 2946
     std::string s = " !";
     assert(s.compare(0, 1, {"abc", 1}) < 0);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_size_size.pass.cpp
index f5d70b93c979f9..35e4be5e3d5ee5 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_size_size.pass.cpp
@@ -19,6 +19,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -6010,6 +6011,7 @@ int main(int, char**) {
   test<std::string>();
 #if TEST_STD_VER >= 11
   test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_view.pass.cpp
index 006f8495886b83..2ed2c7b11fb576 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/size_size_string_view.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 #include "test_macros.h"
 
@@ -364,6 +365,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp
index 7378b604c91c87..2f2fa2679b6531 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 TEST_CONSTEXPR_CXX20 int sign(int x) {
   if (x == 0)
@@ -54,6 +55,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   { // LWG 2946
     std::string s = " !";
     assert(s.compare({"abc", 1}) < 0);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp
index a03e34328f51a5..6cfa314397e5f1 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_compare/string_view.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 TEST_CONSTEXPR_CXX20 int sign(int x) {
   if (x == 0)
@@ -57,6 +58,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp
index fd97e5bd6e79c0..967f337703bbf7 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -68,6 +69,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp
index 927ec97ae0218f..b7b3a627ddf120 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -146,6 +147,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp
index 2da628b8437d5c..d66a031744d604 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -377,6 +378,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp
index 23e1906943401b..de712424a77c67 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) {
@@ -146,6 +147,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   { // LWG 2946
     std::string s = " !";
     assert(s.find_first_not_of({"abc", 1}) == 0);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp
index d63eb8c2f1673f..d906496b73da4b 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) {
@@ -149,6 +150,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp
index 100d3f4bf25107..aed0ff6feaea35 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -66,6 +67,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp
index 6d805393245e78..0977b40cb32fe1 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -147,6 +148,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp
index 14d23b8ece135e..50f280ac10b026 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -377,6 +378,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp
index ed872091dcffe9..025b013843f6eb 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) {
@@ -146,6 +147,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   { // LWG 2946
     std::string s = " !";
     assert(s.find_first_of({"abc", 1}) == std::string::npos);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp
index 541d0f171a91e5..fa75567950d197 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.first.of/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) {
@@ -149,6 +150,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp
index a23206d51430c0..e40ebd048711c9 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -66,6 +67,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp
index 1cb761ee31a641..f9332fe48c779e 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -147,6 +148,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp
index 4fe72a5a9e5c1a..aef6f1ed647e62 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -377,6 +378,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp
index ae088ba98b5ff5..a200504d26eef1 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) {
@@ -146,6 +147,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   { // LWG 2946
     std::string s = " !";
     assert(s.find_last_not_of({"abc", 1}) == s.size() - 1);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp
index 478015095a7acc..1bd55b1c51e03f 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) {
@@ -149,6 +150,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp
index fd278d9b917eba..f91f642a125ab3 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -66,6 +67,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp
index f177671e8ebfe2..8e6c3339b2a96e 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -147,6 +148,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp
index 0dc4f92ba33b7b..3d84112961ecb1 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -377,6 +378,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp
index c4c7c251445feb..d5b86903532d6a 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) {
@@ -146,6 +147,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   { // LWG 2946
     std::string s = " !";
     assert(s.find_last_of({"abc", 1}) == std::string::npos);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp
index 3eae90abd78fbd..b6362909a1e627 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find.last.of/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) {
@@ -148,6 +149,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp
index c0c89c90b30191..8c4917aa18ee66 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -66,6 +67,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp
index e07302f2624f4b..b66472e2e9bf9d 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -151,6 +152,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp
index 5fda0e2af64c77..b420d4d4ab1f6d 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -377,6 +378,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
index 60ed469ce991b1..a469943372d3e9 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) {
@@ -146,6 +147,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 #if TEST_STD_VER >= 11
   { // LWG 2946
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp
index 68c08e2d504bd9..45080544c1a1e8 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) {
@@ -148,6 +149,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp
index b8f2ad0112d4ab..94685a493279b2 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/char_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -66,6 +67,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp
index 1d396fb6b8efeb..3c86a6288b859d 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -146,6 +147,7 @@ TEST_CONSTEXPR_CXX20 bool tests() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp
index 8e981a5e1087dd..30c5e735e35491 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/pointer_size_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -377,6 +378,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp
index f9d09dcabcfd23..42333303177cd3 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(const S& s, const S& str, typename S::size_type pos, typename S::size_type x) {
@@ -140,6 +141,7 @@ TEST_CONSTEXPR_CXX20 bool tests() {
   test_string<std::string>();
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
   { // LWG 2946
     std::string s = " !";
     assert(s.rfind({"abc", 1}) == std::string::npos);
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp
index e42fd3a0ee2de5..0e23762c978c2c 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_rfind/string_view_size.pass.cpp
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void test(const S& s, SV sv, typename S::size_type pos, typename S::size_type x) {
@@ -144,6 +145,7 @@ TEST_CONSTEXPR_CXX20 bool tests() {
   test_string<char, std::allocator>();
 #if TEST_STD_VER >= 11
   test_string<char, min_allocator>();
+  test_string<char, fancy_pointer_allocator>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr.pass.cpp
index 6a66a0067b390b..38088b26d6ddff 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr.pass.cpp
@@ -121,6 +121,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
 #if TEST_STD_VER >= 11
   test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
   test_string<std::basic_string<char, std::char_traits<char>, safe_allocator<char>>>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr_rvalue.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr_rvalue.pass.cpp
index 596eb923db3100..615c5825c12418 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr_rvalue.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr_rvalue.pass.cpp
@@ -77,6 +77,7 @@ constexpr void test_allocators() {
   test_string<std::basic_string<CharT, CharTraits, std::allocator<CharT>>>();
   test_string<std::basic_string<CharT, CharTraits, min_allocator<CharT>>>();
   test_string<std::basic_string<CharT, CharTraits, test_allocator<CharT>>>();
+  test_string<std::basic_string<CharT, CharTraits, fancy_pointer_allocator<CharT>>>();
 }
 
 template <class CharT>
diff --git a/libcxx/test/std/strings/basic.string/string.require/contiguous.pass.cpp b/libcxx/test/std/strings/basic.string/string.require/contiguous.pass.cpp
index 78908901686cf3..51587e731d9372 100644
--- a/libcxx/test/std/strings/basic.string/string.require/contiguous.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.require/contiguous.pass.cpp
@@ -50,6 +50,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string(test_allocator<char>(3));
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>());
+  test_string(fancy_pointer_allocator<char>());
 #endif
 
   return true;
diff --git a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.char.pass.cpp b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.char.pass.cpp
index eb9399d62eaa3b..1a3b1f9d85acd0 100644
--- a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.char.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.char.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class S>
 constexpr void test_string() {
@@ -31,6 +32,7 @@ constexpr void test_string() {
 
 constexpr bool test() {
   test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.ptr.pass.cpp b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.ptr.pass.cpp
index 3647489a0f15f3..25f0229f19b669 100644
--- a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.ptr.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.ptr.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class S>
 constexpr void test_string() {
@@ -59,6 +60,7 @@ constexpr void test_string() {
 
 constexpr bool test() {
   test_string<std::string>();
+  test_string<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char>>>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.string_view.pass.cpp
index c09afbae378498..5e0806167d3c38 100644
--- a/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.starts_with/starts_with.string_view.pass.cpp
@@ -15,6 +15,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class CharT, template <class> class Alloc>
 constexpr void test_string() {
@@ -70,6 +71,7 @@ constexpr void test_string() {
 
 constexpr bool test() {
   test_string<char, std::allocator>();
+  test_string<char, fancy_pointer_allocator>();
 
   return true;
 }
diff --git a/libcxx/test/std/strings/basic.string/types.pass.cpp b/libcxx/test/std/strings/basic.string/types.pass.cpp
index 45408fa6202986..5d6ca300f45b23 100644
--- a/libcxx/test/std/strings/basic.string/types.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/types.pass.cpp
@@ -39,6 +39,7 @@
 #include "test_traits.h"
 #include "test_allocator.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class Traits, class Allocator>
 void test() {
@@ -79,6 +80,7 @@ int main(int, char**) {
   static_assert((std::is_same<std::basic_string<char>::allocator_type, std::allocator<char> >::value), "");
 #if TEST_STD_VER >= 11
   test<std::char_traits<char>, min_allocator<char> >();
+  test<std::char_traits<char>, fancy_pointer_allocator<char> >();
 #endif
 
   return 0;
diff --git a/libcxx/test/std/strings/strings.erasure/erase.pass.cpp b/libcxx/test/std/strings/strings.erasure/erase.pass.cpp
index 35139dd6ad4076..1d6f3bc5edeb20 100644
--- a/libcxx/test/std/strings/strings.erasure/erase.pass.cpp
+++ b/libcxx/test/std/strings/strings.erasure/erase.pass.cpp
@@ -66,8 +66,9 @@ void test() {
 
 int main(int, char**) {
   test<std::string>();
-  test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
-  test<std::basic_string<char, std::char_traits<char>, test_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, test_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp b/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp
index 5bedd394ee5781..f8a42310409e99 100644
--- a/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp
+++ b/libcxx/test/std/strings/strings.erasure/erase_if.pass.cpp
@@ -68,8 +68,9 @@ void test() {
 
 int main(int, char**) {
   test<std::string>();
-  test<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
-  test<std::basic_string<char, std::char_traits<char>, test_allocator<char>>>();
+  test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, test_allocator<char> > >();
+  test<std::basic_string<char, std::char_traits<char>, fancy_pointer_allocator<char> > >();
 
   return 0;
 }
diff --git a/libcxx/test/support/test_allocator.h b/libcxx/test/support/test_allocator.h
index 8ae04413f8a93c..2ad0556669de59 100644
--- a/libcxx/test/support/test_allocator.h
+++ b/libcxx/test/support/test_allocator.h
@@ -17,6 +17,7 @@
 #include <cstdlib>
 #include <climits>
 #include <cassert>
+#include <iterator>
 
 #include "test_macros.h"
 
@@ -435,6 +436,193 @@ TEST_CONSTEXPR_CXX20 thread_unsafe_shared_ptr<T> make_thread_unsafe_shared(Args.
 }
 } // namespace detail
 
+template <class T>
+class fancy_pointer {
+public:
+  // For the std::pointer_traits interface.
+  using pointer         = T*;
+  using element_type    = T;
+  using difference_type = std::ptrdiff_t;
+
+  template <class U>
+  using rebind = fancy_pointer<U>;
+
+  // For the std::iterator_traits interface.
+  using value_type        = typename std::remove_cv<T>::type;
+  using reference         = typename std::add_lvalue_reference<T>::type;
+  using iterator_category = std::random_access_iterator_tag;
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer() TEST_NOEXCEPT : ptr_(nullptr) {}
+  TEST_CONSTEXPR_CXX14 fancy_pointer(T* p) TEST_NOEXCEPT : ptr_(p) {}
+
+  template <typename T2>
+  TEST_CONSTEXPR_CXX14 fancy_pointer(const fancy_pointer<T2>& other) TEST_NOEXCEPT : ptr_(other.get()) {}
+
+  TEST_CONSTEXPR_CXX14 operator T*() const TEST_NOEXCEPT { return ptr_; }
+  TEST_CONSTEXPR_CXX14 fancy_pointer(fancy_pointer&&) TEST_NOEXCEPT                 = default;
+  TEST_CONSTEXPR_CXX14 fancy_pointer(const fancy_pointer&) TEST_NOEXCEPT            = default;
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator=(fancy_pointer&&) TEST_NOEXCEPT      = default;
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator=(const fancy_pointer&) TEST_NOEXCEPT = default;
+  TEST_CONSTEXPR_CXX20 ~fancy_pointer() TEST_NOEXCEPT                               = default;
+  TEST_CONSTEXPR_CXX14 operator fancy_pointer<const T>() const TEST_NOEXCEPT { return fancy_pointer<const T>(get()); }
+  TEST_CONSTEXPR_CXX14 T& operator*() const TEST_NOEXCEPT { return *ptr_; }
+  TEST_CONSTEXPR_CXX14 T* operator->() const TEST_NOEXCEPT { return ptr_; }
+  TEST_CONSTEXPR_CXX14 explicit operator bool() const TEST_NOEXCEPT { return ptr_; }
+  TEST_CONSTEXPR_CXX14 T* get() const TEST_NOEXCEPT { return ptr_; }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator++() TEST_NOEXCEPT {
+    ++ptr_;
+    return *this;
+  }
+  TEST_CONSTEXPR_CXX14 fancy_pointer operator++(int) TEST_NOEXCEPT {
+    fancy_pointer tmp(*this);
+    ++ptr_;
+    return tmp;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator--() TEST_NOEXCEPT {
+    --ptr_;
+    return *this;
+  }
+  TEST_CONSTEXPR_CXX14 fancy_pointer operator--(int) TEST_NOEXCEPT {
+    fancy_pointer tmp(*this);
+    --ptr_;
+    return tmp;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator+=(difference_type n) TEST_NOEXCEPT {
+    ptr_ += n;
+    return *this;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer& operator-=(difference_type n) TEST_NOEXCEPT {
+    ptr_ -= n;
+    return *this;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer operator+(difference_type n) const TEST_NOEXCEPT {
+    fancy_pointer tmp(*this);
+    tmp += n;
+    return tmp;
+  }
+
+  TEST_CONSTEXPR_CXX14 fancy_pointer operator-(difference_type n) const TEST_NOEXCEPT {
+    fancy_pointer tmp(*this);
+    tmp -= n;
+    return tmp;
+  }
+
+  TEST_CONSTEXPR_CXX14 reference operator[](difference_type n) const TEST_NOEXCEPT { return ptr_[n]; }
+
+  friend TEST_CONSTEXPR_CXX14 fancy_pointer operator+(difference_type x, fancy_pointer y) TEST_NOEXCEPT {
+    return y + x;
+  }
+
+  friend TEST_CONSTEXPR_CXX14 bool operator<(fancy_pointer x, fancy_pointer y) TEST_NOEXCEPT { return x.ptr_ < y.ptr_; }
+  friend TEST_CONSTEXPR_CXX14 bool operator>(fancy_pointer x, fancy_pointer y) TEST_NOEXCEPT { return y < x; }
+  friend TEST_CONSTEXPR_CXX14 bool operator<=(fancy_pointer x, fancy_pointer y) TEST_NOEXCEPT { return !(y < x); }
+  friend TEST_CONSTEXPR_CXX14 bool operator>=(fancy_pointer x, fancy_pointer y) TEST_NOEXCEPT { return !(x < y); }
+
+  static TEST_CONSTEXPR_CXX14 fancy_pointer pointer_to(reference ref) TEST_NOEXCEPT { return fancy_pointer(&ref); }
+
+  T* ptr_;
+};
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 typename fancy_pointer<T>::difference_type
+operator-(fancy_pointer<T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return x.ptr_ - y.ptr_;
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 typename fancy_pointer<T>::difference_type
+operator-(fancy_pointer<const T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return x.ptr_ - y.ptr_;
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 typename fancy_pointer<T>::difference_type
+operator-(fancy_pointer<T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return x.ptr_ - y.ptr_;
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 typename fancy_pointer<T>::difference_type
+operator-(fancy_pointer<const T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return x.ptr_ - y.ptr_;
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator==(fancy_pointer<T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return x.get() == y.get();
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator==(fancy_pointer<const T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return x.get() == y.get();
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator==(fancy_pointer<T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return x.get() == y.get();
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator==(fancy_pointer<const T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return x.get() == y.get();
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator!=(fancy_pointer<T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return !(x == y);
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator!=(fancy_pointer<const T> x, fancy_pointer<T> y) TEST_NOEXCEPT {
+  return !(x == y);
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator!=(fancy_pointer<T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return !(x == y);
+}
+
+template <typename T>
+TEST_CONSTEXPR_CXX14 bool operator!=(fancy_pointer<const T> x, fancy_pointer<const T> y) TEST_NOEXCEPT {
+  return !(x == y);
+}
+
+template <class T>
+class fancy_pointer_allocator : public std::allocator<T> {
+  typedef std::allocator<T> base;
+
+public:
+  typedef T value_type;
+  typedef fancy_pointer<T> pointer;
+  typedef fancy_pointer<const T> const_pointer;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef std::size_t size_type;
+  typedef std::ptrdiff_t difference_type;
+
+  template <class U>
+  struct rebind {
+    typedef fancy_pointer_allocator<U> other;
+  };
+
+  TEST_CONSTEXPR_CXX20 fancy_pointer_allocator() TEST_NOEXCEPT {}
+
+  template <class U>
+  TEST_CONSTEXPR explicit fancy_pointer_allocator(fancy_pointer_allocator<U>) TEST_NOEXCEPT {}
+
+  TEST_CONSTEXPR_CXX20 pointer allocate(size_t n) { return base::allocate(n); }
+  TEST_CONSTEXPR_CXX20 void deallocate(pointer p, size_t n) { return base::deallocate(p, n); }
+
+#if TEST_STD_VER > 20
+  TEST_CONSTEXPR_CXX20 std::allocation_result<pointer> allocate_at_least(std::size_t n) { return {allocate(n), n}; }
+#endif
+};
+
 template <class T, std::size_t N>
 class limited_allocator {
   template <class U, std::size_t UN>



More information about the libcxx-commits mailing list