[🍒][libc++] Un-deprecate std::allocator<void>

This is a cherry-pick of 87784cc6fb3453a17e0e78 on 'main' for
backporting to LLVM 12.

Differential Revision: https://reviews.llvm.org/D104324
diff --git a/libcxx/include/memory b/libcxx/include/memory
index 39d0f5b..efb10c8 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -99,14 +99,14 @@
 };
 
 template <>
-class allocator<void> // deprecated in C++17, removed in C++20
+class allocator<void> // removed in C++20
 {
 public:
-    typedef void*                                 pointer;
-    typedef const void*                           const_pointer;
-    typedef void                                  value_type;
+    typedef void*                                 pointer;          // deprecated in C++17
+    typedef const void*                           const_pointer;    // deprecated in C++17
+    typedef void                                  value_type;       // deprecated in C++17
 
-    template <class _Up> struct rebind {typedef allocator<_Up> other;};
+    template <class _Up> struct rebind {typedef allocator<_Up> other;}; // deprecated in C++17
 };
 
 template <class T>
@@ -786,27 +786,27 @@
 
 template <class _Tp> class allocator;
 
-#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS)
+#if _LIBCPP_STD_VER <= 17
 template <>
-class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 allocator<void>
+class _LIBCPP_TEMPLATE_VIS allocator<void>
 {
 public:
-    typedef void*             pointer;
-    typedef const void*       const_pointer;
-    typedef void              value_type;
+    _LIBCPP_DEPRECATED_IN_CXX17 typedef void*             pointer;
+    _LIBCPP_DEPRECATED_IN_CXX17 typedef const void*       const_pointer;
+    _LIBCPP_DEPRECATED_IN_CXX17 typedef void              value_type;
 
-    template <class _Up> struct rebind {typedef allocator<_Up> other;};
+    template <class _Up> struct _LIBCPP_DEPRECATED_IN_CXX17 rebind {typedef allocator<_Up> other;};
 };
 
 template <>
-class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 allocator<const void>
+class _LIBCPP_TEMPLATE_VIS allocator<const void>
 {
 public:
-    typedef const void*       pointer;
-    typedef const void*       const_pointer;
-    typedef const void        value_type;
+    _LIBCPP_DEPRECATED_IN_CXX17 typedef const void*       pointer;
+    _LIBCPP_DEPRECATED_IN_CXX17 typedef const void*       const_pointer;
+    _LIBCPP_DEPRECATED_IN_CXX17 typedef const void        value_type;
 
-    template <class _Up> struct rebind {typedef allocator<_Up> other;};
+    template <class _Up> struct _LIBCPP_DEPRECATED_IN_CXX17 rebind {typedef allocator<_Up> other;};
 };
 #endif
 
diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp
index bfff214..a6134b0 100644
--- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp
+++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp
@@ -33,18 +33,19 @@
 #include <type_traits>
 #include <cstddef>
 
-#include "test_macros.h"
-
-int main(int, char**)
-{
-    static_assert((std::is_same<std::allocator<char>::size_type, std::size_t>::value), "");
-    static_assert((std::is_same<std::allocator<char>::difference_type, std::ptrdiff_t>::value), "");
-    static_assert((std::is_same<std::allocator<char>::pointer, char*>::value), "");
-    static_assert((std::is_same<std::allocator<char>::const_pointer, const char*>::value), "");
-    static_assert((std::is_same<std::allocator<char>::reference, char&>::value), "");
-    static_assert((std::is_same<std::allocator<char>::const_reference, const char&>::value), "");
-    static_assert((std::is_same<std::allocator<char>::rebind<int>::other,
+template <class T>
+void test() {
+    static_assert((std::is_same<typename std::allocator<T>::size_type, std::size_t>::value), "");
+    static_assert((std::is_same<typename std::allocator<T>::difference_type, std::ptrdiff_t>::value), "");
+    static_assert((std::is_same<typename std::allocator<T>::pointer, T*>::value), "");
+    static_assert((std::is_same<typename std::allocator<T>::const_pointer, const T*>::value), "");
+    static_assert((std::is_same<typename std::allocator<T>::reference, T&>::value), "");
+    static_assert((std::is_same<typename std::allocator<T>::const_reference, const T&>::value), "");
+    static_assert((std::is_same<typename std::allocator<T>::template rebind<int>::other,
                                 std::allocator<int> >::value), "");
+}
 
+int main(int, char**) {
+    test<char>();
     return 0;
 }
diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_void.cxx2a.pass.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator_void.cxx2a.pass.cpp
deleted file mode 100644
index d03f90b..0000000
--- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_void.cxx2a.pass.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// Check that the following member types of allocator<void> are provided
-// regardless of the Standard when we request them from libc++.
-
-// template <>
-// class allocator<void>
-// {
-// public:
-//     typedef void*                                 pointer;
-//     typedef const void*                           const_pointer;
-//     typedef void                                  value_type;
-//
-//     template <class _Up> struct rebind {typedef allocator<_Up> other;};
-// };
-
-// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS
-// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
-
-#include <memory>
-#include <type_traits>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
-    static_assert((std::is_same<std::allocator<void>::pointer, void*>::value), "");
-    static_assert((std::is_same<std::allocator<void>::const_pointer, const void*>::value), "");
-    static_assert((std::is_same<std::allocator<void>::value_type, void>::value), "");
-    static_assert((std::is_same<std::allocator<void>::rebind<int>::other,
-                                std::allocator<int> >::value), "");
-    std::allocator<void> a;
-    std::allocator<void> a2 = a;
-    a2 = a;
-
-  return 0;
-}
diff --git a/libcxx/test/std/utilities/memory/default.allocator/PR50299.compile.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/PR50299.compile.pass.cpp
new file mode 100644
index 0000000..245d3d9
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/default.allocator/PR50299.compile.pass.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// Make sure we can use std::allocator<void> in all Standard modes. While the
+// explicit specialization for std::allocator<void> was deprecated, using that
+// specialization was neither deprecated nor removed (in C++20 it should simply
+// start using the primary template).
+//
+// See https://llvm.org/PR50299.
+
+#include <memory>
+
+std::allocator<void> a;
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.ctor.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.ctor.pass.cpp
index 28bfe41..6e6ff1f 100644
--- a/libcxx/test/std/utilities/memory/default.allocator/allocator.ctor.pass.cpp
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.ctor.pass.cpp
@@ -7,15 +7,14 @@
 //===----------------------------------------------------------------------===//
 
 // <memory>
-// UNSUPPORTED: c++03, c++11, c++14, c++17
 //
 // template <class T>
 // class allocator
 // {
 // public: // All of these are constexpr after C++17
-//  constexpr allocator() noexcept;
-//  constexpr allocator(const allocator&) noexcept;
-//  template<class U> constexpr allocator(const allocator<U>&) noexcept;
+//  allocator() noexcept;
+//  allocator(const allocator&) noexcept;
+//  template<class U> allocator(const allocator<U>&) noexcept;
 // ...
 // };
 
@@ -24,28 +23,27 @@
 
 #include "test_macros.h"
 
+template<class T>
+TEST_CONSTEXPR_CXX20 bool test() {
+  typedef std::allocator<T> A1;
+  typedef std::allocator<long> A2;
 
-int main(int, char**)
-{
-    {
-    typedef std::allocator<char> AC;
-    typedef std::allocator<long> AL;
+  A1 a1;
+  A1 a1_copy = a1; (void)a1_copy;
+  A2 a2 = a1; (void)a2;
 
-    constexpr AC a1;
-    constexpr AC a2{a1};
-    constexpr AL a3{a2};
-    (void) a3;
-    }
-    {
-    typedef std::allocator<const char> AC;
-    typedef std::allocator<const long> AL;
+  return true;
+}
 
-    constexpr AC a1;
-    constexpr AC a2{a1};
-    constexpr AL a3{a2};
-    (void) a3;
-    }
+int main(int, char**) {
+  test<char>();
+  test<char const>();
+  test<void>();
 
-
+#if TEST_STD_VER > 17
+  static_assert(test<char>());
+  static_assert(test<char const>());
+  static_assert(test<void>());
+#endif
   return 0;
 }
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.dtor.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.dtor.pass.cpp
index 7ae87dd..a095ca1 100644
--- a/libcxx/test/std/utilities/memory/default.allocator/allocator.dtor.pass.cpp
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.dtor.pass.cpp
@@ -13,7 +13,6 @@
 
 #include <memory>
 
-
 template <typename T>
 constexpr bool test() {
     std::allocator<T> alloc;
@@ -26,11 +25,13 @@
 int main(int, char**)
 {
     test<int>();
+    test<void>();
 #ifdef _LIBCPP_VERSION // extension
     test<int const>();
 #endif // _LIBCPP_VERSION
 
     static_assert(test<int>());
+    static_assert(test<void>());
 #ifdef _LIBCPP_VERSION // extension
     static_assert(test<int const>());
 #endif // _LIBCPP_VERSION
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_pointers.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_pointers.pass.cpp
index 27e91a6..777e5df 100644
--- a/libcxx/test/std/utilities/memory/default.allocator/allocator_pointers.pass.cpp
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_pointers.pass.cpp
@@ -11,9 +11,9 @@
 #include <memory>
 #include <cassert>
 
-// #include <memory>
-
 #include "test_macros.h"
+
+// <memory>
 //
 // template <class Alloc>
 // struct allocator_traits
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx17.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx17.verify.cpp
index f09651a..88af53a 100644
--- a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx17.verify.cpp
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx17.verify.cpp
@@ -30,20 +30,27 @@
 // UNSUPPORTED: clang-6
 
 #include <memory>
-#include "test_macros.h"
 
-int main(int, char**)
-{
-    typedef std::allocator<char>::pointer AP;             // expected-warning {{'pointer' is deprecated}}
-    typedef std::allocator<char>::const_pointer ACP;      // expected-warning {{'const_pointer' is deprecated}}
-    typedef std::allocator<char>::reference AR;           // expected-warning {{'reference' is deprecated}}
-    typedef std::allocator<char>::const_reference ACR;    // expected-warning {{'const_reference' is deprecated}}
-    typedef std::allocator<char>::rebind<int>::other ARO; // expected-warning {{'rebind<int>' is deprecated}}
-
-    typedef std::allocator<char const>::pointer AP2;             // expected-warning {{'pointer' is deprecated}}
-    typedef std::allocator<char const>::const_pointer ACP2;      // expected-warning {{'const_pointer' is deprecated}}
-    typedef std::allocator<char const>::reference AR2;           // expected-warning {{'reference' is deprecated}}
-    typedef std::allocator<char const>::const_reference ACR2;    // expected-warning {{'const_reference' is deprecated}}
-    typedef std::allocator<char const>::rebind<int>::other ARO2; // expected-warning {{'rebind<int>' is deprecated}}
+int main(int, char**) {
+    {
+        typedef std::allocator<char>::pointer Pointer;                  // expected-warning {{'pointer' is deprecated}}
+        typedef std::allocator<char>::const_pointer ConstPointer;       // expected-warning {{'const_pointer' is deprecated}}
+        typedef std::allocator<char>::reference Reference;              // expected-warning {{'reference' is deprecated}}
+        typedef std::allocator<char>::const_reference ConstReference;   // expected-warning {{'const_reference' is deprecated}}
+        typedef std::allocator<char>::rebind<int>::other Rebind;        // expected-warning {{'rebind<int>' is deprecated}}
+    }
+    {
+        typedef std::allocator<char const>::pointer Pointer;                  // expected-warning {{'pointer' is deprecated}}
+        typedef std::allocator<char const>::const_pointer ConstPointer;       // expected-warning {{'const_pointer' is deprecated}}
+        typedef std::allocator<char const>::reference Reference;              // expected-warning {{'reference' is deprecated}}
+        typedef std::allocator<char const>::const_reference ConstReference;   // expected-warning {{'const_reference' is deprecated}}
+        typedef std::allocator<char const>::rebind<int>::other Rebind;        // expected-warning {{'rebind<int>' is deprecated}}
+    }
+    {
+        typedef std::allocator<void>::pointer Pointer;                  // expected-warning {{'pointer' is deprecated}}
+        typedef std::allocator<void>::const_pointer ConstPointer;       // expected-warning {{'const_pointer' is deprecated}}
+        // reference and const_reference are not provided by std::allocator<void>
+        typedef std::allocator<void>::rebind<int>::other Rebind;        // expected-warning {{'rebind<int>' is deprecated}}
+    }
     return 0;
 }
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp
index 6a03493..74adc69 100644
--- a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp
@@ -18,47 +18,49 @@
 //     typedef ptrdiff_t difference_type;
 //     typedef T         value_type;
 //
+//     typedef T*        pointer;           // deprecated in C++17, removed in C++20
+//     typedef T const*  const_pointer;     // deprecated in C++17, removed in C++20
+//     typedef T&        reference;         // deprecated in C++17, removed in C++20
+//     typedef T const&  const_reference;   // deprecated in C++17, removed in C++20
+//     template< class U > struct rebind { typedef allocator<U> other; }; // deprecated in C++17, removed in C++20
+//
 //     typedef true_type propagate_on_container_move_assignment;
 //     typedef true_type is_always_equal;
 // ...
 // };
 
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
+
 #include <memory>
 #include <type_traits>
 #include <cstddef>
 
 #include "test_macros.h"
 
-template <typename T, typename U>
-TEST_CONSTEXPR_CXX20 bool test()
-{
-    static_assert((std::is_same<typename std::allocator<T>::size_type, std::size_t>::value), "");
-    static_assert((std::is_same<typename std::allocator<T>::difference_type, std::ptrdiff_t>::value), "");
-    static_assert((std::is_same<typename std::allocator<T>::value_type, T>::value), "");
-    static_assert((std::is_same<typename std::allocator<T>::propagate_on_container_move_assignment, std::true_type>::value), "");
-    static_assert((std::is_same<typename std::allocator<T>::is_always_equal, std::true_type>::value), "");
+struct U;
 
-    std::allocator<T> a;
-    std::allocator<T> a2 = a;
-    a2 = a;
-    std::allocator<U> a3 = a2;
-    (void)a3;
+template <typename T>
+void test() {
+    typedef std::allocator<T> Alloc;
+    static_assert((std::is_same<typename Alloc::size_type, std::size_t>::value), "");
+    static_assert((std::is_same<typename Alloc::difference_type, std::ptrdiff_t>::value), "");
+    static_assert((std::is_same<typename Alloc::value_type, T>::value), "");
+    static_assert((std::is_same<typename Alloc::propagate_on_container_move_assignment, std::true_type>::value), "");
+    static_assert((std::is_same<typename Alloc::is_always_equal, std::true_type>::value), "");
 
-    return true;
+#if TEST_STD_VER <= 17
+    static_assert((std::is_same<typename Alloc::pointer, T*>::value), "");
+    static_assert((std::is_same<typename Alloc::const_pointer, T const*>::value), "");
+    static_assert((std::is_same<typename Alloc::reference, T&>::value), "");
+    static_assert((std::is_same<typename Alloc::const_reference, T const&>::value), "");
+    static_assert((std::is_same<typename Alloc::template rebind<U>::other, std::allocator<U> >::value), "");
+#endif
 }
 
-int main(int, char**)
-{
-    test<char, int>();
-#ifdef _LIBCPP_VERSION // extension
-    test<char const, int const>();
-#endif // _LIBCPP_VERSION
-
-#if TEST_STD_VER > 17
-    static_assert(test<char, int>());
-#ifdef _LIBCPP_VERSION // extension
-    static_assert(test<char const, int const>());
-#endif // _LIBCPP_VERSION
+int main(int, char**) {
+    test<char>();
+#ifdef _LIBCPP_VERSION
+    test<char const>(); // extension
 #endif
     return 0;
 }
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx20.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx20.verify.cpp
index 9805acc..1d91a02 100644
--- a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx20.verify.cpp
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx20.verify.cpp
@@ -31,16 +31,17 @@
 template <typename T>
 void check()
 {
-    typedef typename std::allocator<T>::pointer AP;                      // expected-error 2 {{no type named 'pointer'}}
-    typedef typename std::allocator<T>::const_pointer ACP;               // expected-error 2 {{no type named 'const_pointer'}}
-    typedef typename std::allocator<T>::reference AR;                    // expected-error 2 {{no type named 'reference'}}
-    typedef typename std::allocator<T>::const_reference ACR;             // expected-error 2 {{no type named 'const_reference'}}
-    typedef typename std::allocator<T>::template rebind<int>::other ARO; // expected-error 2 {{no member named 'rebind'}}
+    typedef typename std::allocator<T>::pointer AP;                      // expected-error 3 {{no type named 'pointer'}}
+    typedef typename std::allocator<T>::const_pointer ACP;               // expected-error 3 {{no type named 'const_pointer'}}
+    typedef typename std::allocator<T>::reference AR;                    // expected-error 3 {{no type named 'reference'}}
+    typedef typename std::allocator<T>::const_reference ACR;             // expected-error 3 {{no type named 'const_reference'}}
+    typedef typename std::allocator<T>::template rebind<int>::other ARO; // expected-error 3 {{no member named 'rebind'}}
 }
 
 int main(int, char**)
 {
     check<char>();
     check<char const>();
+    check<void>();
     return 0;
 }
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.void.compile.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.void.compile.pass.cpp
new file mode 100644
index 0000000..d7b4a1b
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.void.compile.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Check that the nested types of std::allocator<void> are provided.
+// After C++17, those are not provided in the primary template and the
+// explicit specialization doesn't exist anymore, so this test is moot.
+
+// REQUIRES: c++03 || c++11 || c++14 || c++17
+
+// template <>
+// class allocator<void>
+// {
+// public:
+//     typedef void*                                 pointer;
+//     typedef const void*                           const_pointer;
+//     typedef void                                  value_type;
+//
+//     template <class _Up> struct rebind {typedef allocator<_Up> other;};
+// };
+
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
+
+#include <memory>
+#include <type_traits>
+
+static_assert((std::is_same<std::allocator<void>::pointer, void*>::value), "");
+static_assert((std::is_same<std::allocator<void>::const_pointer, const void*>::value), "");
+static_assert((std::is_same<std::allocator<void>::value_type, void>::value), "");
+static_assert((std::is_same<std::allocator<void>::rebind<int>::other,
+                            std::allocator<int> >::value), "");
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_void.deprecated_in_cxx17.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_void.deprecated_in_cxx17.verify.cpp
deleted file mode 100644
index cd98e63..0000000
--- a/libcxx/test/std/utilities/memory/default.allocator/allocator_void.deprecated_in_cxx17.verify.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// Check that allocator<void> is deprecated in C++17.
-
-// REQUIRES: c++17
-
-#include <memory>
-#include "test_macros.h"
-
-int main(int, char**)
-{
-    typedef std::allocator<void>::pointer AP;             // expected-warning {{'allocator<void>' is deprecated}}
-    typedef std::allocator<void>::const_pointer ACP;      // expected-warning {{'allocator<void>' is deprecated}}
-    typedef std::allocator<void>::rebind<int>::other ARO; // expected-warning {{'allocator<void>' is deprecated}}
-    return 0;
-}