[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
Fri Nov 24 04:05:23 PST 2023


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

>From 10d49a6b00360620dc17c5288c01e281a45686e3 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. It also adds a static assert
which will fail if the fancy pointer is not trivially destructible.

Addresses bug report: https://bugs.llvm.org/show_bug.cgi?id=20508
---
 libcxx/include/string                         | 157 +++++++++++++-
 .../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           |   4 +-
 .../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           |   4 +-
 .../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          | 194 +++++++++++++++++-
 234 files changed, 989 insertions(+), 17 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index 68f13414c7b69484..0fd3355615a3598b 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -816,7 +816,10 @@ private:
 
     static_assert(sizeof(__short) == (sizeof(value_type) * (__min_cap + 1)), "__short has an unexpected size.");
 
-    union __ulx{__long __lx; __short __lxx;};
+    union __ulx {
+      __long __lx;
+      __short __lxx;
+    };
 
     enum {__n_words = sizeof(__ulx) / sizeof(size_type)};
 
@@ -825,6 +828,7 @@ private:
         size_type __words[__n_words];
     };
 
+#ifdef _LIBCPP_CXX03_LANG
     struct __rep
     {
         union
@@ -834,6 +838,124 @@ 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{} {
+            // We don't necessarily need to explicitly initialise __s here. __s can be implicitly created with simple 
+            // assignment. __l just needs to be first have its lifetime created with std::construct_at().
+
+            // Begin the lifetime of __l
+            // https://stackoverflow.com/questions/70549096/does-stdconstruct-at-make-an-array-member-of-a-union-active
+            // It seems that once the lifetime has begun, we can perform simple assignments during constant evaluation
+            // More cryptic info here: https://timsong-cpp.github.io/cppwp/n4868/class.union.general#6 (linked from previous
+            // SO post).
+            // std::construct_at(&__l);
+            // std::construct_at(&__s);
+        }
+        
+        _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__rep() _NOEXCEPT {
+            // Add explicit destruction of __long every time we change from long to short.
+            if (__is_rep_long(*this)) {
+                __l.~__long();
+            }
+        }
+
+        _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_rep_long(const __rep& __str_rep) const _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_;
+        }
+
+        _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep(const __rep& __other) _NOEXCEPT : __s{} {
+            // 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. For a short string, the
+            // memory should be directly copied.
+            if (__is_rep_long(__other)) {
+                // If the current string is currently short, we need to first activate the long member
+                    // before assigning to it.
+                    #if _LIBCPP_STD_VER >= 20
+                        if (__libcpp_is_constant_evaluated() && !__is_rep_long(*this)) {
+                            std::construct_at(std::addressof(__l));
+                        }
+                    #endif // _LIBCPP_STD_VER >= 20
+
+                __l.__is_long_ = __other.__l.__is_long_;
+                __l.__cap_ = __other.__l.__cap_;
+                __l.__size_ = __other.__l.__size_;
+                __l.__data_ = __other.__l.__data_;
+            } else {
+                // If the current string is currently long, we need to first activate the short member
+                // before assigning to it.
+                #if _LIBCPP_STD_VER >= 20
+                        if (__libcpp_is_constant_evaluated() && __is_rep_long(*this)) {
+                            __s = __short();
+                        }
+                    #endif // _LIBCPP_STD_VER >= 20
+                __s.__is_long_ = __other.__s.__is_long_;
+                __s.__size_ = __other.__s.__size_;
+
+                for (size_type __i = 0; __i < sizeof(value_type) - 1; ++__i) {
+                    __s.__padding_[__i] = __other.__s.__padding_[__i];
+                }
+
+                for (size_type __i = 0;  __i <__min_cap; ++__i) {
+                    __s.__data_[__i] = __other.__s.__data_[__i];
+                }
+            }
+        }
+
+        _LIBCPP_CONSTEXPR_SINCE_CXX20 __rep& operator=(const __rep& __other) _NOEXCEPT {
+            if (this != &__other) {
+                if (__is_rep_long(__other)) {
+                    // If the current string is currently short, we need to first active the long member
+                    // before assigning to it.
+                    #if _LIBCPP_STD_VER >= 20
+                        if (__libcpp_is_constant_evaluated() && !__is_rep_long(*this)) {
+                            std::construct_at(std::addressof(__l));
+                        }
+                    #endif // _LIBCPP_STD_VER >= 20
+                    
+                    __l.__is_long_ = __other.__l.__is_long_;
+                    __l.__cap_ = __other.__l.__cap_;
+                    __l.__size_ = __other.__l.__size_;
+                    __l.__data_ = __other.__l.__data_;
+                    // __other.__l.~__long();
+                } else {
+                    #if _LIBCPP_STD_VER >= 20
+                        if (__libcpp_is_constant_evaluated() && __is_rep_long(*this)) {
+                            __s = __short();
+                        }
+                    #endif // _LIBCPP_STD_VER >= 20
+                    __s.__is_long_ = __other.__s.__is_long_;
+                    __s.__size_ = __other.__s.__size_;
+
+                    for (size_type __i = 0; __i <sizeof(value_type) - 1; ++__i) {
+                        __s.__padding_[__i] = __other.__s.__padding_[__i];
+                    }
+
+                    for (size_type __i = 0;  __i <__min_cap; ++__i) {
+                        __s.__data_[__i] = __other.__s.__data_[__i];
+                    }
+                }
+            }
+            return *this;
+        }
+
+        union {
+            __short __s;
+            __long __l;
+            __raw __r;
+        };
+    };
+#endif // _LIBCPP_CXX03_LANG
 
     __compressed_pair<__rep, allocator_type> __r_;
 
@@ -852,6 +974,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);
@@ -1757,6 +1880,29 @@ private:
 #endif // _LIBCPP_STD_VER >= 20
     }
 
+    // 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.
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_long_lifetime() {
+#if _LIBCPP_STD_VER >= 20
+        // if constexpr (is_trivially_constructible<__long>::value) {
+            std::construct_at(std::addressof(__r_.first().__l));
+        // }
+#endif // _LIBCPP_STD_VER >= 20
+    }
+
+//     // If __long is not trivially destructible (this occurs if the pointer type inside __long is not trivially destructible)
+//     // then the lifetime of __l must be explicitly ended before changing the active data member from __l. Otherwise, the 
+//     // destructor will never be called. Therefore, __end_long_lifetime() must be called everytime we change from __l to 
+//     // __s or __r.
+//     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __end_long_lifetime() {
+// #if _LIBCPP_STD_VER >= 20
+//         // if constexpr (is_trivially_constructible<__long>::value) {
+//             __r_.first().~__l();
+//         // }
+// #endif // _LIBCPP_STD_VER >= 20
+//     }
+
     _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI static bool __fits_in_sso(size_type __sz) {
         return __sz < __min_cap;
     }
@@ -1969,6 +2115,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());
@@ -2131,6 +2278,7 @@ void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s,
         auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__reserve) + 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);
@@ -2159,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);
@@ -2184,6 +2333,7 @@ void basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(
     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);
@@ -2212,6 +2362,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c)
         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);
@@ -2283,6 +2434,7 @@ void basic_string<_CharT, _Traits, _Allocator>::__init_with_size(
         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);
@@ -2334,6 +2486,7 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace
                           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;
@@ -2374,6 +2527,7 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_t
                           __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);
 }
@@ -3304,6 +3458,7 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
         __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 7b4d54ed410b0274..fb6b6e917cb99c13 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 6e00e43618b2e36a..2788c1274b4b0dca 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 9c6d49af7883e723..f288c0078b421a9e 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 7a89d06d2474135f..1812f69987e859df 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 30dc29a951c7bf6b..3821854dcbbb76b0 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 2b4072826fd604d2..dc0e2727688b03bc 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 e75908ee07c13660..4492b0245fb223fe 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 95701314faf8e2d1..f0cc44c2ec4cd11c 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 7bf8043df76d5b1b..0475f4b2cfa953fc 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 d4a0b318f36d728b..6eea24490f896578 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 8459284637dc5063..c78ac207f46744a7 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 c55410edf4ebac64..aa99d18a0c2014d1 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 f1fa08d006a1e0dd..dd0a7420bde8da59 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 0bf295c6c4f4fb8f..8fab28beb80e6350 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 9cc9ab40bcdd6592..0c68b416f2ad211c 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 34060065d204669d..4d9aa1a0cc233a86 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 d3274cbd90cc5008..2f60065dc324b210 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 8c6d704a684b5300..07e50e88ea0a8f12 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 1bdf3af367430285..f203c4ad8b53ec82 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 93fd6caf0ba2365c..4fc4be6bfaf67388 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 ed97e21d9411e623..29954095f3b228cf 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 561f79e0e18fb813..946839aea66123d2 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 eef525349972b929..baff22ee85a44931 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 4b7532678f2e5796..4b1ed1b82ebadeae 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 8e6e07d659c1a0a4..5cc22c4ddfdaf53c 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 611f95f0d3ef6e98..3f382225859cbe59 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 52c0646c7d7c568f..f1ffeffb11eaeee1 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 2f0c282c8e436509..bcf76d6aa6998ebc 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 809b0399dc70fd52..aad6f2db6b7b33ba 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 8ba8bf0c8b096bbc..9604da6d161e72c7 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 3a308de9b7569a3f..1e1b75a3379b154f 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
@@ -15,6 +15,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.capacity/empty.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/empty.pass.cpp
index b4700d68a59af246..c8a4914ec3dbbc9b 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 e873f82c4830b6e9..0f0ff13a67d1c57a 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 52dbde45dbb265d6..1e0d88e67df467a9 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 0b459f9625689e76..f3ebef401f2fdc58 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 03e3cf2f9d7d38e7..99ac2570e8ca6d7c 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
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 void test(typename S::size_type min_cap, typename S::size_type erased_index) {
@@ -46,6 +47,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_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/reserve_size.pass.cpp
index bb804bf328b3b8d3..9910eb11838c6dbd 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
@@ -20,6 +20,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -77,6 +78,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 bbe6551a0ff1181d..a7ae6fb1270e92f2 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
@@ -19,6 +19,7 @@
 
 #include "make_string.h"
 #include "test_macros.h"
+#include "test_allocator.h"
 
 template <class S>
 constexpr void test_appending(std::size_t k, size_t N, size_t new_capacity) {
@@ -85,18 +86,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 487b12d9df87f338..12b85566be5175d8 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
@@ -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, typename S::size_type n, 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.capacity/resize_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_size_char.pass.cpp
index 3b6adc0b0afeb191..3b0f1e9fb4f4cd82 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
@@ -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, typename S::size_type n, typename S::value_type c, S expected) {
@@ -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.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
index 1efebfc9cea561b1..b7db5a062c4b3d22 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
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -45,6 +46,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/size.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/size.pass.cpp
index 9d53971779b6480c..e1be04a13427c5b7 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 a6b625b7b0e8113e..25fd7c268a67af46 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
@@ -113,6 +113,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string(test_allocator<char>(8));
 #if TEST_STD_VER >= 11
   test_string(min_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 97a0566ba031b00d..24036b926d1e8912 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
@@ -16,6 +16,7 @@
 #include "test_macros.h"
 #include "test_allocator.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test() {
@@ -89,6 +90,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test<std::basic_string<char, std::char_traits<char>, test_allocator<char> > >();
 #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>, 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 3cffc82e94835263..591122538ab7ede2 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
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s1, typename S::value_type s2) {
@@ -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.cons/copy.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/copy.pass.cpp
index 3afe76e88316f99c..99b270a3451d5751 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
@@ -40,6 +40,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.cons/copy_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/copy_alloc.pass.cpp
index 6b0040376a424ec1..a8c65c653e47a5e5 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
@@ -99,6 +99,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
 
 #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 8d0fcb3c6d2943f7..7f89bbf5e0e892c2 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
@@ -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 s1, const S& s2) {
@@ -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
 
 #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 3993a40dd5a165c2..7f41154a098d212b 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
@@ -22,6 +22,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 e9f174068473d550..ab799e8090484030 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 5b7e8bde2e6e877e..b6f258c7dfd5de36 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
@@ -38,6 +38,7 @@ TEST_CONSTEXPR_CXX20 void test_string() {
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::allocator>();
   test_string<min_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 88597daba121ac47..44e0966e029c715d 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
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 // clang-format off
 template <template <class> class Alloc>
@@ -43,6 +44,7 @@ TEST_CONSTEXPR_CXX20 void test_string() {
 TEST_CONSTEXPR_CXX20 bool test() {
   test_string<std::allocator>();
   test_string<min_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 2ef73e5ec8c1adea..db0973476812dae7 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
@@ -90,6 +90,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 65762ccf89d93049..9d0b76a4ff4677d9 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
@@ -99,6 +99,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     assert(s1.size() == 10);
     assert(s1.compare(0, s1.size(), s, s1.size()) == 0);
   }
+  {
+    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>{}};
@@ -109,6 +119,16 @@ TEST_CONSTEXPR_CXX20 bool test() {
     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, 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 f5ffebd35d50e92d..8fdee1642d14d70f 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
@@ -43,6 +43,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 0e5c72192adea64a..844e66038798243c 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
@@ -70,6 +70,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 bba86b3acffee8b8..551de2b3f4a669b5 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 89cb44d62ef2b6c5..aa9465d46a6ee7ae 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
@@ -51,6 +51,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/move_noexcept.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp
index d807cac2c72c8486..c408508e8f21a25d 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 84a29df5b57bf162..d8b8cbfc3f628fb9 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
@@ -67,6 +67,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test(test_allocator<char>(2));
 #if TEST_STD_VER >= 11
   test(min_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 4b3027a2aad1183f..8f650bb2ac19183e 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
@@ -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 s1, const typename S::value_type* s2) {
@@ -48,6 +49,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/pointer_size_alloc.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp
index e0dab72b5c6327ea..8a0febc8a08b14a6 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
@@ -64,6 +64,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test(test_allocator<char>(2));
 #if TEST_STD_VER >= 11
   test(min_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 3afbcdffa6bdfe37..60b613564f87f2b5 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
@@ -94,6 +94,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
 
   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 74fa76a013a6926c..dd08c5e5e3534edc 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
@@ -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
 
   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 3c88f9e40fc0b3be..66119b177e3db1ce 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
@@ -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(S s1, SV sv) {
@@ -48,6 +49,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/string_view_deduction.pass.cpp b/libcxx/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp
index 3a6f84f2699aca62..a5287a2332136364 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 08e696b7a091bd47..c32bdb748be4de3d 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 693edab76b17b0ce..224283d0b9ac6582 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
@@ -164,6 +164,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test_string(test_allocator<char>(3), test_allocator<char>(5));
 #if TEST_STD_VER >= 11
   test_string(min_allocator<char>(), min_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 272ce339f3adc610..fcc472c804862647 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
@@ -203,6 +203,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 658af8e2cd64967b..d9ea3c98633fe6a6 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 99f400fa0c37b38e..ada28b9611d403df 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 619a718794b14e1d..192702913070a22a 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 a9547ec4f3af3fdf..734954131a2d9c45 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 23331967d1c730a2..006bc7664e6b6d9e 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 683a16a2fc536afa..5ee06c31671850ac 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 202a87dd777b3b30..0da516f14b65ed22 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 df2c38476197ed1a..cd3afb59789bd39c 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 31d06725e5107dbb..b794408e5ebee841 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 85b33afeb403eb61..84aae817b597e69b 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 5d1f90c409bc4036..3e40a30f75038454 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 2c3e3b12872157e4..2a72ed0326efd8a7 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 feaea2f65790c77f..c07ccb1faf6c20c7 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 d34ee26fd9d04b77..1e20f95cd9d9873d 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 a02b455ce1fe62c0..9802838609327a12 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 cf45b368ebbcaf6b..8da8417f2e25dbbe 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) {
@@ -86,6 +87,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 6c5049f16bc61926..a6f08704e73bc8c6 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
@@ -18,6 +18,7 @@
 #include "test_macros.h"
 #include "min_allocator.h"
 #include "nasty_string.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test() {
@@ -40,6 +41,7 @@ TEST_CONSTEXPR_CXX20 bool test() {
   test<std::u32string>();
 
   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>>>();
 #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 2982cfe77042c0d6..e774e0d3c0e058f0 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"
 
 template <class S, class It>
@@ -224,7 +225,8 @@ 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>, 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_append/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/pointer.pass.cpp
index 68f5838ccf2f02a6..38fb32d4bc9d1fb6 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
@@ -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, const typename S::value_type* str, S expected) {
@@ -43,6 +44,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 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 b98c91cf097b1a0b..71295ebb98a6c635 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
@@ -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, const typename S::value_type* str, typename S::size_type n, S expected) {
@@ -48,6 +49,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 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 0b8e5f65c15e94d7..bd1be8dca3306c56 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
@@ -16,6 +16,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 struct VeryLarge {
   long long a;
@@ -74,6 +75,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
   {
     // 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 eb0728456df5be42..5b5fa52d1b29a8f4 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
@@ -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, typename S::size_type n, typename S::value_type c, S expected) {
@@ -44,6 +45,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_append/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp
index 21f2ff53004d158a..71b030d54bfb90cf 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
@@ -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, S str, S expected) {
@@ -51,6 +52,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
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 902d29c53ac69f54..956c465fe8aa5962 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
@@ -18,6 +18,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, typename S::size_type pos, typename S::size_type n, S expected) {
@@ -85,6 +86,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/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_append/string_view.pass.cpp
index c09cdde1bc105e3e..b6bdb1c9c1634341 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) {
@@ -53,6 +54,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 a2a954cb94aac6a9..606d55fd3eccf0f0 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
@@ -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, typename S::size_type pos, typename S::size_type n, S expected) {
@@ -85,6 +86,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_assign/initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/initializer_list.pass.cpp
index ba55f30785e94f46..1054e6bfc6382120 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
@@ -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() {
@@ -27,9 +28,8 @@ 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> > >();
-#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 b2ca4fb5ddd93709..bd5e126e69e7fa02 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
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class It>
 TEST_CONSTEXPR_CXX20 void test(S s, It first, It last, S expected) {
@@ -170,7 +171,8 @@ 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>, 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/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/pointer.pass.cpp
index 11e12c318a2e8002..c00bdbff26f622d8 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
@@ -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, const typename S::value_type* str, S expected) {
@@ -43,6 +44,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 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 2738a9a6ffad594e..c1e1951da2885d98 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
@@ -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, const typename S::value_type* str, typename S::size_type n, S expected) {
@@ -48,6 +49,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 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 a33e8e97157c40b7..cf87524b0d9fd135 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 b52c66103395f19a..a2239dcd12d4a37d 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
@@ -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, typename S::size_type n, typename S::value_type c, S expected) {
@@ -44,6 +45,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/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string.pass.cpp
index f39b7f66c4b187a4..e085182975851179 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
@@ -104,6 +104,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 9448452bafad9c36..89250ce583d5dbd6 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
@@ -18,6 +18,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, typename S::size_type pos, typename S::size_type n, S expected) {
@@ -85,6 +86,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_assign/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_assign/string_view.pass.cpp
index aeda9db36a840ed5..3ff71a929ba6def8 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 e1904baeb9033b07..a9683059e47a1832 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
@@ -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 str, typename S::value_type* s, typename S::size_type n, typename S::size_type pos) {
@@ -108,6 +109,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_erase/iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
index 03c5b965537c6fe3..fd64a337ffb41feb 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
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::difference_type pos, S expected) {
@@ -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.modifiers/string_erase/iter_iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
index f092ad718cdaa89f..a0938b7166e56f28 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
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.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) {
@@ -89,6 +90,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_erase/pop_back.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
index 9c63fa47a7e4a7f4..5c4878f2db6f4caf 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
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, S expected) {
@@ -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.modifiers/string_erase/size_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
index 610256061a5f2cd7..296339d26b5d082b 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
@@ -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, typename S::size_type pos, typename S::size_type n, S expected) {
@@ -180,6 +181,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_insert/iter_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp
index bc3ce511ab5c2211..664b30c786854929 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
@@ -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, typename S::const_iterator p, typename S::value_type c, S expected) {
@@ -53,6 +54,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_insert/iter_initializer_list.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp
index 876cc9ecd14c6a8f..65db9c673af8f792 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
@@ -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() {
@@ -29,6 +30,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_insert/iter_iter_iter.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp
index e3d0f1322e85de2b..0d1720c218b7c779 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
@@ -17,6 +17,7 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 #include "min_allocator.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) {
@@ -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
 
 #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 1e0d16e4cc2e172e..0d4ac24631e40747 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
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -98,6 +99,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_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 f7e6ca71180e3304..b0a19f977d4d5948 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 359fd999598f8890..4c55bd10f6339b0c 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
@@ -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, typename S::size_type pos, const typename S::value_type* str, S expected) {
@@ -128,6 +129,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_insert/size_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/size_pointer_size.pass.cpp
index 44f20ff63cc0ca5c..2c89f2e3a7875c0c 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
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -388,11 +389,13 @@ 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
 
 #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 2396b7e2f54df732..a974d251e81d6ed6 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
@@ -17,6 +17,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -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
 
   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 1b908ac464c31342..053c52c7fdcd6ab0 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
@@ -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, typename S::size_type pos, S str, S expected) {
@@ -128,6 +129,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
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 1a8f6b35b42c445b..e04972512cae659e 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
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -1816,6 +1817,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_insert/string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/string_view.pass.cpp
index 7c0f157bc3230093..699b88bec5813f93 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 1e03d8c1b6147413..7b27a5d7b33a9df3 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
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, typename S::value_type str, S expected) {
@@ -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.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 e7334b96276a5f82..db88d01cee3f4803 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
@@ -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_op_plus_equal/pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/pointer.pass.cpp
index 2d8c535b354c22f8..ccc5fc708e013b08 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
@@ -15,6 +15,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s, const typename S::value_type* str, S expected) {
@@ -50,6 +51,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_op_plus_equal/string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp
index e02ced737ae16a23..4c0ca35f5f69a5ee 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
@@ -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, S str, S expected) {
@@ -51,6 +52,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;
     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 efc21725ee24cdeb..41210a319bd3b0df 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 c1ca532a5f910f91..3a2f12d31b162d4b 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 fa13ca8062b2a320..a7793fae3763bbac 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 45d57c793a3352f5..2ddf6ffe55be9b52 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 dd87da1e25354636..4cd17627be91cb55 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 35db1d6368191693..b08a1eb9ba8604ed 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
@@ -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, typename S::size_type pos1, typename S::size_type n1, S str, S expected) {
@@ -292,6 +293,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_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string_view.pass.cpp
index 767ed41ae22477b5..d741aa0c0062cfb5 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 004a519262853945..3de486af2649b390 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
@@ -23,6 +23,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S, class SV>
 TEST_CONSTEXPR_CXX20 void
@@ -6279,6 +6280,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_pointer.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer.pass.cpp
index a7282615e4855417..95a041bba16e0514 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
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -377,6 +378,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/size_size_pointer_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_pointer_size.pass.cpp
index 7ef63bdf313ddafe..94e0bea469a00192 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
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -1341,6 +1342,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/size_size_size_char.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_size_char.pass.cpp
index 8841318c1d4df5b7..a615b12421ca5928 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
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -381,6 +382,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/size_size_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp
index fab2beeabd5721ad..5b83b2388f30d817 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
@@ -18,6 +18,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.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) {
@@ -385,6 +386,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/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 073de60289857ae7..7212eb0810c79b90 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
@@ -22,6 +22,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void
@@ -6099,6 +6100,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/size_size_string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string_view.pass.cpp
index cec8cc0c52dd9f34..86bea46b917775d3 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
@@ -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, typename S::size_type pos1, typename S::size_type n1, SV sv, S expected) {
@@ -376,6 +377,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_swap/swap.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_swap/swap.pass.cpp
index 3d9ec016bcfbd3a2..753707d7c6ebb7a6 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"
@@ -53,6 +54,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.io/get_line.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string.io/get_line.pass.cpp
index 7bcb34135440bfb6..45a5e3d92485495c 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 97a55fa09d14df00..87962e85cdf1ce42 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 1cd50a4c8940c75d..275274606e60e21e 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 ff100f9234bef0e9..dac37ff415388a90 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 fde4990c9cafb247..e04f11b115015280 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 c66f15213ff2f03f..89b46d41a5e7af4c 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 da6fc11c14329f47..54f078f36dcb226a 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
@@ -19,6 +19,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s1, S s2) {
@@ -55,6 +56,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!=/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op!=/pointer_string.pass.cpp
index 11cfcfcf4299570d..bd77ce2e59ea7345 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 c04c06243cd258ba..c7429e8cc1c7027b 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 881770e421bb04c6..5081cc6958257de7 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 1595ec501f4e90cf..da6a3c86fbb4e7fe 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 246b98bc5e107cf0..35bd322002cdc5f0 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 82a591e0533628d6..2a871048971fc209 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
@@ -22,6 +22,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(typename S::value_type lhs, const S& rhs, const S& x) {
@@ -53,6 +54,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+/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/pointer_string.pass.cpp
index fa14f657d8269c3f..772fefcef421247c 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 66cbac28f9f2c3ac..aa139a3635285d6c 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
@@ -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 S& lhs, typename S::value_type rhs, const S& x) {
@@ -55,6 +56,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 2802189f843c59c0..08de53089d14dae7 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
@@ -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 S& lhs, const typename S::value_type* rhs, const S& x) {
@@ -77,6 +78,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 f8ebb98767a8375a..51c12e5dec300f0d 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
@@ -34,6 +34,7 @@
 
 #include "test_macros.h"
 #include "min_allocator.h"
+#include "test_allocator.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test0(const S& lhs, const S& rhs, const S& x) {
@@ -133,6 +134,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==/pointer_string.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_operator==/pointer_string.pass.cpp
index a8114af2600cad2e..e32beb04f45dee20 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 8e67e6e81a6e91d2..b5c4417fc7a82cc6 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 31bace312f1df8d2..6f08981e51f5fac7 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 c758c4adfe604281..9cd603eaa60071d5 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 39dd627033c4856f..86615394ce32ab5a 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 ce0fbf55b5c51117..8fb70310cb3f1548 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 2a77947bc7febeac..79468cf9ac5a40fc 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 794f9e76b4e857ef..b799d1773a8ac87a 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 de06981bb47870a5..43926e53404f87c0 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 8026777a88db1956..c5525240e63eb303 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 35d3c69785325a3e..0774e120e4f94e69 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 3f8883e358da56e4..50279392b934d51b 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 1dc65bf0b6db093e..af17ea82748d98dd 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 19c96ffb77e79daa..54fb2f9b174d2276 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 d55b2f8fd34be454..c70a90ac4de47415 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 0c4dbe2f9193b964..abeebad52977b1cf 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 bcdb1091140dfc6a..b0a7c29cd8bdae21 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 6ca1dd27f31ab6f6..4f835fdeef2a7b12 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 56549d17677364ea..4d39b0baf1b2b7d5 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 72e9d4bf96682a93..9c8503bd2b934236 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 85c6f04ecc2c1468..03679cc700f9f517 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 16db9337823297b9..1689f13dc46d59d5 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 a970014177915643..33c6a1e2f3276bd1 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 2ee253820c11e95c..24db2ba6c75d14f6 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 88951e4da9101bfd..a9b74e72c222fe04 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 837599ae9ef551b6..a7053de9512df532 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 27762fbd9390d514..d03f03e05fbd5c75 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 a6158aeb38dc2e8d..1d552345f06aba36 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 e1d23924517ffbf6..edf335538910ac43 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 c6281d9e377f4749..b073873baf277288 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 d4a5133ed3907f8b..2f44efa443aed548 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 aba230d92e18248b..c9979cf1dbb7f4fe 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 018daaa2f262e4fe..597528472b33e5ee 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 f5d70b93c979f94e..35e4be5e3d5ee5d4 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 006f8495886b83a4..2ed2c7b11fb576bd 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 7378b604c91c87e6..2f2fa2679b6531f8 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 a03e34328f51a59d..6cfa314397e5f1b9 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 fd97e5bd6e79c02c..967f337703bbf799 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 927ec97ae0218f30..b7b3a627ddf1202a 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 2da628b8437d5c33..d66a031744d6040e 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 23e1906943401b64..de712424a77c6736 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 d63eb8c2f1673ff5..d906496b73da4b53 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 100d3f4bf25107da..aed0ff6feaea354b 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 6d805393245e7828..0977b40cb32fe161 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 14d23b8ece135e28..50f280ac10b02635 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 ed872091dcffe9d8..025b013843f6ebc9 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 541d0f171a91e57c..fa75567950d19764 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 a23206d51430c07f..e40ebd048711c92e 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 1cb761ee31a641a4..f9332fe48c779e6a 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 4fe72a5a9e5c1a8f..aef6f1ed647e62e8 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 ae088ba98b5ff5f4..a200504d26eef1eb 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 478015095a7accb7..1bd55b1c51e03f45 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 fd278d9b917ebabe..f91f642a125ab374 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 f177671e8ebfe2c8..8e6c3339b2a96e81 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 0dc4f92ba33b7b63..3d84112961ecb192 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 c4c7c251445feb9f..d5b86903532d6a5f 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 3eae90abd78fbdae..b6362909a1e627f2 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 c0c89c90b3019193..8c4917aa18ee66d6 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 e07302f2624f4b7b..b66472e2e9bf9dea 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 5fda0e2af64c7796..b420d4d4ab1f6d21 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 60ed469ce991b145..a469943372d3e978 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 68c08e2d504bd95a..45080544c1a1e8fb 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 b8f2ad0112d4ab68..94685a493279b2db 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 1d396fb6b8efeb3d..3c86a6288b859d47 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 8e981a5e1087dd88..30c5e735e35491e7 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 f9d09dcabcfd235d..42333303177cd301 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 e42fd3a0ee2de5d7..0e23762c978c2c43 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 83cfa8737408ca58..88ea53c038dc78fa 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
@@ -108,6 +108,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_substr/substr_rvalue.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_substr/substr_rvalue.pass.cpp
index c3c6c3f56b919614..1522feff5a2884dd 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
@@ -74,6 +74,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 78908901686cf302..51587e731d937257 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 eb9399d62eaa3b75..1a3b1f9d85acd067 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 3647489a0f15f3e6..25f0229f19b669bf 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 c09afbae378498f8..5e0806167d3c3877 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 45408fa620298635..5d6ca300f45b2314 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 35139dd6ad4076c8..1d6f3bc5edeb2053 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 5bedd394ee57811c..f8a42310409e991f 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 3bde73183ab6e39e..9c0103665057bef5 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"
 
@@ -29,8 +30,8 @@ TEST_CONSTEXPR_CXX20 inline typename std::allocator_traits<Alloc>::size_type all
 struct test_allocator_statistics {
   int time_to_throw = 0;
   int throw_after = INT_MAX;
-  int count = 0;
-  int alloc_count = 0;
+  int count           = 0;
+  int alloc_count     = 0;
   int construct_count = 0; // the number of times that ::construct was called
   int destroy_count = 0; // the number of times that ::destroy was called
   int copied = 0;
@@ -41,7 +42,7 @@ struct test_allocator_statistics {
     assert(count == 0 && "clearing leaking allocator data?");
     count = 0;
     time_to_throw = 0;
-    alloc_count = 0;
+    alloc_count     = 0;
     construct_count = 0;
     destroy_count = 0;
     throw_after = INT_MAX;
@@ -429,6 +430,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