diff --git a/libcxx/include/string b/libcxx/include/string
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -688,6 +688,8 @@
                   "traits_type::char_type must be the same type as CharT");
     static_assert(( is_same<typename allocator_type::value_type, value_type>::value),
                   "Allocator::value_type must be same type as value_type");
+    static_assert((is_trivially_destructible<pointer>::value),
+                  "pointer type must have a trivial destructor.");
 
     typedef __wrap_iter<pointer>                         iterator;
     typedef __wrap_iter<const_pointer>                   const_iterator;
@@ -787,6 +789,28 @@
 
     struct __rep
     {
+        _LIBCPP_CONSTEXPR_AFTER_CXX17 __rep() : __l{} {}
+
+        _LIBCPP_CONSTEXPR_AFTER_CXX17 __rep(const __rep& other) noexcept
+        {
+            __l.__is_long_ = other.__l.__is_long_;
+            __l.__cap_  = other.__l.__cap_;
+            __l.__size_ = other.__l.__size_;
+            __l.__data_ = other.__l.__data_;
+        }
+
+        _LIBCPP_CONSTEXPR_AFTER_CXX17 __rep& operator=(__rep other)
+        {
+            if (this != &other)
+            {
+                __l.__is_long_ = other.__l.__is_long_;
+                __l.__cap_  = other.__l.__cap_;
+                __l.__size_ = other.__l.__size_;
+                __l.__data_ = other.__l.__data_;
+            }
+            return *this;
+        }
+
         union
         {
             __long  __l;
diff --git a/libcxx/test/libcxx/strings/basic.string/allocator_with_fancy_pointer.pass.cpp b/libcxx/test/libcxx/strings/basic.string/allocator_with_fancy_pointer.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/strings/basic.string/allocator_with_fancy_pointer.pass.cpp
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <string>
+
+// Create string with custom allocator using fancy pointer and ensure compilation is successful
+
+#include <string>
+
+template <class T>
+class NonTriviallyConstructiblePointer {
+  T* ptr;
+
+public:
+  NonTriviallyConstructiblePointer() {}
+  NonTriviallyConstructiblePointer(T* p) : ptr(p) {}
+  operator T*() const { return ptr; }
+  NonTriviallyConstructiblePointer(NonTriviallyConstructiblePointer&&)                 = default;
+  NonTriviallyConstructiblePointer(const NonTriviallyConstructiblePointer&)            = default;
+  NonTriviallyConstructiblePointer& operator=(NonTriviallyConstructiblePointer&&)      = default;
+  NonTriviallyConstructiblePointer& operator=(const NonTriviallyConstructiblePointer&) = default;
+  ~NonTriviallyConstructiblePointer()                                                  = default;
+  T& operator*() const { return *ptr; }
+  T* operator->() const { return ptr; }
+  operator bool() const { return ptr; }
+};
+
+template <class T>
+class allocator : public std::allocator<T> {
+  using base = std::allocator<T>;
+
+public:
+  using pointer = NonTriviallyConstructiblePointer<T>;
+  pointer allocate(size_t n) { return base::allocate(n); }
+  void deallocate(pointer p, size_t n) { return base::deallocate(p, n); }
+};
+
+int main() { std::basic_string<char, std::char_traits<char>, allocator<char>> s; }
diff --git a/libcxx/test/libcxx/strings/basic.string/allocator_with_fancy_pointer_non_trivial_destructor.fail.cpp b/libcxx/test/libcxx/strings/basic.string/allocator_with_fancy_pointer_non_trivial_destructor.fail.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/libcxx/strings/basic.string/allocator_with_fancy_pointer_non_trivial_destructor.fail.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <string>
+
+// Test that basic_string requires its allocator to use a pointer with a trivial destructor.
+
+#include <string>
+
+template <class T>
+class NonTriviallyDestructiblePointer {
+  T* ptr;
+
+public:
+  NonTriviallyDestructiblePointer() {} // non-trivial constructor
+  NonTriviallyDestructiblePointer(T* p) : ptr(p) {}
+  operator T*() const { return ptr; }
+  NonTriviallyDestructiblePointer(NonTriviallyDestructiblePointer&&)                 = default;
+  NonTriviallyDestructiblePointer(const NonTriviallyDestructiblePointer&)            = default;
+  NonTriviallyDestructiblePointer& operator=(NonTriviallyDestructiblePointer&&)      = default;
+  NonTriviallyDestructiblePointer& operator=(const NonTriviallyDestructiblePointer&) = default;
+  ~NonTriviallyDestructiblePointer() {} // non-trivial destructor
+  T& operator*() const { return *ptr; }
+  T* operator->() const { return ptr; }
+  operator bool() const { return ptr; }
+};
+
+template <class T>
+class allocator : public std::allocator<T> {
+  using base = std::allocator<T>;
+
+public:
+  using pointer = NonTriviallyDestructiblePointer<T>;
+  pointer allocate(size_t n) { return base::allocate(n); }
+  void deallocate(pointer p, size_t n) { return base::deallocate(p, n); }
+};
+
+int main() {
+  std::basic_string<char, std::char_traits<char>, allocator<char>>
+      s; // expected-error-re@* {{static assertion failed due to requirement 'is_trivially_destructible<NonTriviallyDestructiblePointer<char>>{{.+}}value'{{.+}} pointer type must have a trivial destructor.}}
+}