[libc++] Use allocator_traits to consistently allocate/deallocate/construct/destroy objects in std::any

https://llvm.org/PR45099 notes (correctly) that we're inconsistent in memory
allocation in `std::any`. We allocate memory with `std::allocator<T>::allocate`,
construct with placement new, destroy by calling the destructor directly, and
deallocate by calling `delete`. Most of those are customizable by the user,
but in different ways.

The standard is silent on how these things are to be accomplished.
This patch makes it so we use `allocator_traits<allocator<T>>` for all
of these operations (allocate, construct, destruct, deallocate).
This is, at least, consistent.

Fixes https://llvm.org/PR45099.

Differential Revision: https://reviews.llvm.org/D81133
diff --git a/libcxx/include/any b/libcxx/include/any
index 36b07c9..7546f31 100644
--- a/libcxx/include/any
+++ b/libcxx/include/any
@@ -82,7 +82,6 @@
 
 #include <experimental/__config>
 #include <memory>
-#include <new>
 #include <typeinfo>
 #include <type_traits>
 #include <cstdlib>
@@ -368,7 +367,11 @@
     template <class ..._Args>
     _LIBCPP_INLINE_VISIBILITY
     static _Tp& __create(any & __dest, _Args&&... __args) {
-        _Tp* __ret = ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...);
+        typedef allocator<_Tp> _Alloc;
+        typedef allocator_traits<_Alloc> _ATraits;
+        _Alloc __a;
+        _Tp * __ret = static_cast<_Tp*>(static_cast<void*>(&__dest.__s.__buf));
+        _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...);
         __dest.__h = &_SmallHandler::__handle;
         return *__ret;
     }
@@ -376,8 +379,11 @@
   private:
     _LIBCPP_INLINE_VISIBILITY
     static void __destroy(any & __this) {
-        _Tp & __value = *static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
-        __value.~_Tp();
+        typedef allocator<_Tp> _Alloc;
+        typedef allocator_traits<_Alloc> _ATraits;
+        _Alloc __a;
+        _Tp * __p = static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
+        _ATraits::destroy(__a, __p);
         __this.__h = nullptr;
     }
 
@@ -445,10 +451,12 @@
     _LIBCPP_INLINE_VISIBILITY
     static _Tp& __create(any & __dest, _Args&&... __args) {
         typedef allocator<_Tp> _Alloc;
+        typedef allocator_traits<_Alloc> _ATraits;
         typedef __allocator_destructor<_Alloc> _Dp;
         _Alloc __a;
-        unique_ptr<_Tp, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
-        _Tp* __ret = ::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...);
+        unique_ptr<_Tp, _Dp> __hold(_ATraits::allocate(__a, 1), _Dp(__a, 1));
+        _Tp * __ret = __hold.get();
+        _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...);
         __dest.__s.__ptr = __hold.release();
         __dest.__h = &_LargeHandler::__handle;
         return *__ret;
@@ -458,7 +466,12 @@
 
     _LIBCPP_INLINE_VISIBILITY
     static void __destroy(any & __this){
-        delete static_cast<_Tp*>(__this.__s.__ptr);
+        typedef allocator<_Tp> _Alloc;
+        typedef allocator_traits<_Alloc> _ATraits;
+        _Alloc __a;
+        _Tp * __p = static_cast<_Tp *>(__this.__s.__ptr);
+        _ATraits::destroy(__a, __p);
+        _ATraits::deallocate(__a, __p, 1);
         __this.__h = nullptr;
     }
 
diff --git a/libcxx/test/libcxx/utilities/any/allocator.pass.cpp b/libcxx/test/libcxx/utilities/any/allocator.pass.cpp
new file mode 100644
index 0000000..c6800eb
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/any/allocator.pass.cpp
@@ -0,0 +1,136 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <any>
+
+// Check that we're consistently using std::allocator_traits to
+// allocate/deallocate/construct/destroy objects in std::any.
+// See https://llvm.org/PR45099 for details.
+
+#include <any>
+#include <cassert>
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+
+// Make sure we don't fit in std::any's SBO
+struct Large { char big[sizeof(std::any) + 1]; };
+
+// Make sure we fit in std::any's SBO
+struct Small { };
+
+bool Large_was_allocated = false;
+bool Large_was_constructed = false;
+bool Large_was_destroyed = false;
+bool Large_was_deallocated = false;
+
+bool Small_was_allocated = false;
+bool Small_was_constructed = false;
+bool Small_was_destroyed = false;
+bool Small_was_deallocated = false;
+
+namespace std {
+  template <>
+  struct allocator<Large> {
+    using value_type = Large;
+    using size_type = std::size_t;
+    using difference_type = std::ptrdiff_t;
+    using propagate_on_container_move_assignment = std::true_type;
+    using is_always_equal = std::true_type;
+
+    Large* allocate(std::size_t n) {
+      Large_was_allocated = true;
+      return static_cast<Large*>(::operator new(n));
+    }
+
+    template <typename ...Args>
+    void construct(Large* p, Args&& ...args) {
+      new (p) Large(std::forward<Args>(args)...);
+      Large_was_constructed = true;
+    }
+
+    void destroy(Large* p) {
+      p->~Large();
+      Large_was_destroyed = true;
+    }
+
+    void deallocate(Large* p, std::size_t) {
+      Large_was_deallocated = true;
+      return ::operator delete(p);
+    }
+  };
+
+  template <>
+  struct allocator<Small> {
+    using value_type = Small;
+    using size_type = std::size_t;
+    using difference_type = std::ptrdiff_t;
+    using propagate_on_container_move_assignment = std::true_type;
+    using is_always_equal = std::true_type;
+
+    Small* allocate(std::size_t n) {
+      Small_was_allocated = true;
+      return static_cast<Small*>(::operator new(n));
+    }
+
+    template <typename ...Args>
+    void construct(Small* p, Args&& ...args) {
+      new (p) Small(std::forward<Args>(args)...);
+      Small_was_constructed = true;
+    }
+
+    void destroy(Small* p) {
+      p->~Small();
+      Small_was_destroyed = true;
+    }
+
+    void deallocate(Small* p, std::size_t) {
+      Small_was_deallocated = true;
+      return ::operator delete(p);
+    }
+  };
+} // end namespace std
+
+
+int main(int, char**) {
+  // Test large types
+  {
+    {
+      std::any a = Large();
+      (void)a;
+
+      assert(Large_was_allocated);
+      assert(Large_was_constructed);
+    }
+
+    assert(Large_was_destroyed);
+    assert(Large_was_deallocated);
+  }
+
+  // Test small types
+  {
+    {
+      std::any a = Small();
+      (void)a;
+
+      assert(!Small_was_allocated);
+      assert(Small_was_constructed);
+    }
+
+    assert(Small_was_destroyed);
+    assert(!Small_was_deallocated);
+  }
+
+  return 0;
+}