diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -136,6 +136,11 @@ against the static version of libc++, which will result in no dependency being taken against the shared library. +- The ``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION`` macro has been added to allow + re-enabling the ``allocator`` specialization. When used in conjuction with + ``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS``, this ensures that the members of + ``allocator`` removed in C++20 can be accessed. + ABI Changes ----------- diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -314,6 +314,12 @@ including `pointer`, `reference`, `rebind`, `address`, `max_size`, `construct`, `destroy`, and the two-argument overload of `allocate`. +**_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION**: + This macro is used to re-enable the library-provided specializations of + `allocator` and `allocator`. + Use it in conjunction with `_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS` + to ensure that removed members of `allocator` can be accessed. + **_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS**: This macro is used to re-enable the `argument_type`, `result_type`, `first_argument_type`, and `second_argument_type` members of class diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1152,6 +1152,7 @@ # if defined(_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES) # define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS +# define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION # define _LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS # define _LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS # define _LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h --- a/libcxx/include/__memory/allocator.h +++ b/libcxx/include/__memory/allocator.h @@ -27,27 +27,31 @@ template class allocator; -#if _LIBCPP_STD_VER <= 17 +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION) template <> class _LIBCPP_TEMPLATE_VIS allocator { +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) public: _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 struct _LIBCPP_DEPRECATED_IN_CXX17 rebind {typedef allocator<_Up> other;}; +#endif }; template <> class _LIBCPP_TEMPLATE_VIS allocator { +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) public: _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 struct _LIBCPP_DEPRECATED_IN_CXX17 rebind {typedef allocator<_Up> other;}; +#endif }; #endif diff --git a/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_allocator_void_no_members.verify.cpp b/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_allocator_void_no_members.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_allocator_void_no_members.verify.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 members of std::allocator are not provided in C++20 +// with _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION but without +// _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS. + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION +// +// Ignore any extra errors arising from typo correction. +// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error + +#include + +std::allocator::pointer x; // expected-error-re {{no {{(type|template)}} named 'pointer'}} +std::allocator::const_pointer y; // expected-error-re {{no {{(type|template)}} named 'const_pointer'}} +std::allocator::value_type z; // expected-error-re {{no {{(type|template)}} named 'value_type'}} +std::allocator::rebind::other t; // expected-error-re {{no {{(type|template)}} named 'rebind'}} diff --git a/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_with_removed_members.compile.pass.cpp b/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_with_removed_members.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_with_removed_members.compile.pass.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 are provided in C++20 +// with a flag that keeps the removed members. + +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION + +#include +#include + +static_assert((std::is_same::pointer, void*>::value), ""); +static_assert((std::is_same::const_pointer, const void*>::value), ""); +static_assert((std::is_same::value_type, void>::value), ""); +static_assert((std::is_same::rebind::other, std::allocator >::value), "");