diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 71de10abb6eaa..d30021b7eb234 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -121,6 +121,15 @@ Deprecations and Removals - The ``_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS`` macro has been removed and is not honored anymore. Additional warnings provided by libc++ as a matter of QoI will now be provided unconditionally. +- libc++ no longer supports ``std::allocator`` and containers of ``const``-qualified element type, such + as ``std::vector`` and ``std::list``. This used to be supported as an undocumented extension. + If you were using ``std::vector``, replace it with ``std::vector`` instead. The + ``_LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST`` macro can be defined to temporarily re-enable this extension as + folks transition their code. This macro will be honored for one released and ignored starting in LLVM 20. + To assist with the clean-up process, consider running your code through Clang Tidy, with + `std-allocator-const ` + enabled. + Upcoming Deprecations and Removals ---------------------------------- diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h index 215d3832f9ef3..2d8624e771bce 100644 --- a/libcxx/include/__memory/allocator.h +++ b/libcxx/include/__memory/allocator.h @@ -14,6 +14,7 @@ #include <__memory/addressof.h> #include <__memory/allocate_at_least.h> #include <__memory/allocator_traits.h> +#include <__type_traits/is_const.h> #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_same.h> #include <__type_traits/is_void.h> @@ -36,8 +37,6 @@ class allocator; // Specializing allocator is deprecated, but not using it. template <> class _LIBCPP_TEMPLATE_VIS allocator { -# if _LIBCPP_STD_VER <= 17 - public: _LIBCPP_DEPRECATED_IN_CXX17 typedef void* pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* const_pointer; @@ -47,13 +46,12 @@ class _LIBCPP_TEMPLATE_VIS allocator { struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { typedef allocator<_Up> other; }; -# endif }; +// TODO(LLVM 20): Remove the escape hatch +# ifdef _LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST template <> class _LIBCPP_TEMPLATE_VIS allocator { -# if _LIBCPP_STD_VER <= 17 - public: _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* const_pointer; @@ -63,9 +61,9 @@ class _LIBCPP_TEMPLATE_VIS allocator { struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { typedef allocator<_Up> other; }; -# endif }; -#endif +# endif // _LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST +#endif // _LIBCPP_STD_VER <= 17 // This class provides a non-trivial default constructor to the class that derives from it // if the condition is satisfied. @@ -94,6 +92,7 @@ struct __non_trivial_if { template class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if::value, allocator<_Tp> > { + static_assert(!is_const<_Tp>::value, "std::allocator does not support const types"); static_assert(!is_volatile<_Tp>::value, "std::allocator does not support volatile types"); public: @@ -170,6 +169,8 @@ class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if::v #endif }; +// TODO(LLVM 20): Remove the escape hatch +#ifdef _LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST template class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if::value, allocator > { @@ -180,9 +181,9 @@ class _LIBCPP_TEMPLATE_VIS allocator typedef ptrdiff_t difference_type; typedef const _Tp value_type; typedef true_type propagate_on_container_move_assignment; -#if _LIBCPP_STD_VER <= 23 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_ALLOCATOR_MEMBERS) +# if _LIBCPP_STD_VER <= 23 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_ALLOCATOR_MEMBERS) _LIBCPP_DEPRECATED_IN_CXX23 typedef true_type is_always_equal; -#endif +# endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator() _NOEXCEPT = default; @@ -199,11 +200,11 @@ class _LIBCPP_TEMPLATE_VIS allocator } } -#if _LIBCPP_STD_VER >= 23 +# if _LIBCPP_STD_VER >= 23 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result allocate_at_least(size_t __n) { return {allocate(__n), __n}; } -#endif +# endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void deallocate(const _Tp* __p, size_t __n) { if (__libcpp_is_constant_evaluated()) { @@ -214,7 +215,7 @@ class _LIBCPP_TEMPLATE_VIS allocator } // C++20 Removed members -#if _LIBCPP_STD_VER <= 17 +# if _LIBCPP_STD_VER <= 17 _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& reference; @@ -243,8 +244,9 @@ class _LIBCPP_TEMPLATE_VIS allocator } _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI void destroy(pointer __p) { __p->~_Tp(); } -#endif +# endif }; +#endif // _LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index 358a851958db1..2d00e3308c497 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -259,7 +259,7 @@ struct __shared_ptr_emplace : __shared_weak_count { class _Allocator = _Alloc, __enable_if_t::value, int> = 0> _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __storage_(std::move(__a)) { - using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; + using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __remove_cv_t<_Tp> >::type; _TpAlloc __tmp(*__get_alloc()); allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), std::forward<_Args>(__args)...); } @@ -278,7 +278,7 @@ struct __shared_ptr_emplace : __shared_weak_count { template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT { - using _TpAlloc = typename __allocator_traits_rebind<_Allocator, _Tp>::type; + using _TpAlloc = typename __allocator_traits_rebind<_Allocator, __remove_cv_t<_Tp> >::type; _TpAlloc __tmp(*__get_alloc()); allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); } @@ -598,8 +598,8 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr(auto_ptr<_Yp>&& __r) : __ptr_(__r.get()) { - typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__r.get(), default_delete<_Yp>(), allocator<_Yp>()); + typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<__remove_cv_t<_Yp> > > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__r.get(), default_delete<_Yp>(), allocator<__remove_cv_t<_Yp> >()); __enable_weak_this(__r.get(), __r.get()); __r.release(); } @@ -776,7 +776,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { private: template ::value> struct __shared_ptr_default_allocator { - typedef allocator<_Yp> type; + typedef allocator<__remove_cv_t<_Yp> > type; }; template @@ -834,7 +834,7 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&& template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(_Args&&... __args) { - return std::allocate_shared<_Tp>(allocator<_Tp>(), std::forward<_Args>(__args)...); + return std::allocate_shared<_Tp>(allocator<__remove_cv_t<_Tp> >(), std::forward<_Args>(__args)...); } #if _LIBCPP_STD_VER >= 20 @@ -848,7 +848,7 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() { - return std::allocate_shared_for_overwrite<_Tp>(allocator<_Tp>()); + return std::allocate_shared_for_overwrite<_Tp>(allocator<__remove_cv_t<_Tp>>()); } #endif // _LIBCPP_STD_VER >= 20 diff --git a/libcxx/test/libcxx/containers/sequences/vector/const_T.compile.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector/const_T.compile.pass.cpp deleted file mode 100644 index 62fff96ac5abe..0000000000000 --- a/libcxx/test/libcxx/containers/sequences/vector/const_T.compile.pass.cpp +++ /dev/null @@ -1,18 +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 -// -//===----------------------------------------------------------------------===// - -// Make sure that `vector` works - -#include - -void test() { - std::vector v; - v.emplace_back(1); - v.push_back(1); - v.resize(3); -} diff --git a/libcxx/test/libcxx/containers/sequences/vector/const_value_type.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector/const_value_type.pass.cpp deleted file mode 100644 index 1ad505a76d3fb..0000000000000 --- a/libcxx/test/libcxx/containers/sequences/vector/const_value_type.pass.cpp +++ /dev/null @@ -1,25 +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 -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03 - -// - -// vector v; // an extension - -#include -#include - -#include "test_macros.h" - -int main(int, char**) -{ - std::vector v = {1, 2, 3}; - - return 0; -} diff --git a/libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp index 210d269c9fa23..646569e3d573a 100644 --- a/libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp +++ b/libcxx/test/libcxx/diagnostics/memory.nodiscard.verify.cpp @@ -39,15 +39,3 @@ void test_allocator() { allocator.allocate_at_least(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} #endif } - -void test_const_allocator() { - std::allocator allocator; - allocator.allocate(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - -#if TEST_STD_VER <= 17 - allocator.allocate(1, nullptr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} -#endif -#if TEST_STD_VER >= 23 - allocator.allocate_at_least(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} -#endif -} diff --git a/libcxx/test/libcxx/memory/allocator_void.trivial.compile.pass.cpp b/libcxx/test/libcxx/memory/allocator_void.trivial.compile.pass.cpp index f9d67c065de85..69a4b8943caa6 100644 --- a/libcxx/test/libcxx/memory/allocator_void.trivial.compile.pass.cpp +++ b/libcxx/test/libcxx/memory/allocator_void.trivial.compile.pass.cpp @@ -17,18 +17,10 @@ #include typedef std::allocator A1; -typedef std::allocator A2; -struct A3 : std::allocator { }; -struct A4 : std::allocator { }; +struct A2 : std::allocator { }; static_assert(std::is_trivially_default_constructible::value, ""); static_assert(std::is_trivial::value, ""); static_assert(std::is_trivially_default_constructible::value, ""); static_assert(std::is_trivial::value, ""); - -static_assert(std::is_trivially_default_constructible::value, ""); -static_assert(std::is_trivial::value, ""); - -static_assert(std::is_trivially_default_constructible::value, ""); -static_assert(std::is_trivial::value, ""); diff --git a/libcxx/test/libcxx/memory/allocator_volatile.verify.cpp b/libcxx/test/libcxx/memory/allocator_volatile.verify.cpp index 6fa7fe1b1aeda..53fdc08e7a024 100644 --- a/libcxx/test/libcxx/memory/allocator_volatile.verify.cpp +++ b/libcxx/test/libcxx/memory/allocator_volatile.verify.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// -// http://wg21.link/LWG2447 gives implementors freedom to reject volatile types in `std::allocator`. +// http://wg21.link/LWG2447 gives implementors freedom to reject const or volatile types in `std::allocator`. #include -std::allocator A1; // expected-error@*:* {{std::allocator does not support volatile types}} -std::allocator A2; // expected-error@*:* {{std::allocator does not support volatile types}} +std::allocator A1; // expected-error@*:* {{std::allocator does not support const types}} +std::allocator A2; // expected-error@*:* {{std::allocator does not support volatile types}} diff --git a/libcxx/test/std/concepts/concepts.lang/concept.default.init/default_initializable.compile.pass.cpp b/libcxx/test/std/concepts/concepts.lang/concept.default.init/default_initializable.compile.pass.cpp index ee1405f1f889d..6a31fb90e4da2 100644 --- a/libcxx/test/std/concepts/concepts.lang/concept.default.init/default_initializable.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.lang/concept.default.init/default_initializable.compile.pass.cpp @@ -205,9 +205,6 @@ void test() test_not_const>(); test_false >(); test_true >(); -#ifdef _LIBCPP_VERSION - test_true >(); -#endif // _LIBCPP_VERSION test_true >(); test_true >(); test_true >(); @@ -226,9 +223,6 @@ void test() // Container adaptors test_true >(); -#ifdef _LIBCPP_VERSION - test_true >(); -#endif // _LIBCPP_VERSION test_true >(); test_true >(); 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 6e6ff1f2d1344..a278bc41ef761 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 @@ -37,12 +37,12 @@ TEST_CONSTEXPR_CXX20 bool test() { int main(int, char**) { test(); - test(); + test(); test(); #if TEST_STD_VER > 17 static_assert(test()); - static_assert(test()); + static_assert(test()); static_assert(test()); #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 a095ca102491e..69c6595c98645 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 @@ -26,15 +26,9 @@ int main(int, char**) { test(); test(); -#ifdef _LIBCPP_VERSION // extension - test(); -#endif // _LIBCPP_VERSION static_assert(test()); static_assert(test()); -#ifdef _LIBCPP_VERSION // extension - static_assert(test()); -#endif // _LIBCPP_VERSION return 0; } diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.constexpr.size.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.constexpr.size.verify.cpp index fbbb334fea0fd..34a89e8be8591 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.constexpr.size.verify.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.constexpr.size.verify.cpp @@ -34,5 +34,4 @@ constexpr bool test() void f() { static_assert(test()); // expected-error {{static assertion expression is not an integral constant expression}} - LIBCPP_STATIC_ASSERT(test()); // expected-error {{static assertion expression is not an integral constant expression}} } diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp index 1913a0e0dcc8d..2b11bd7f48dd7 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.pass.cpp @@ -45,7 +45,6 @@ void test() int main(int, char**) { test(); - LIBCPP_ONLY(test()); return 0; } 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 917492929ecc2..96ae6427188c0 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 @@ -35,13 +35,6 @@ void f() { typedef std::allocator::const_reference ConstReference; // expected-warning {{'const_reference' is deprecated}} typedef std::allocator::rebind::other Rebind; // expected-warning {{'rebind' is deprecated}} } - { - typedef std::allocator::pointer Pointer; // expected-warning {{'pointer' is deprecated}} - typedef std::allocator::const_pointer ConstPointer; // expected-warning {{'const_pointer' is deprecated}} - typedef std::allocator::reference Reference; // expected-warning {{'reference' is deprecated}} - typedef std::allocator::const_reference ConstReference; // expected-warning {{'const_reference' is deprecated}} - typedef std::allocator::rebind::other Rebind; // expected-warning {{'rebind' is deprecated}} - } { typedef std::allocator::pointer Pointer; // expected-warning {{'pointer' is deprecated}} typedef std::allocator::const_pointer ConstPointer; // expected-warning {{'const_pointer' is deprecated}} diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx23.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx23.verify.cpp index ad431f94732ee..0a27cc712ed62 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx23.verify.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.deprecated_in_cxx23.verify.cpp @@ -25,7 +25,7 @@ void test() { typedef std::allocator::is_always_equal IAE; // expected-warning {{'is_always_equal' is deprecated}} } { - typedef std::allocator::is_always_equal IAE; // expected-warning {{'is_always_equal' is deprecated}} + typedef std::allocator::is_always_equal IAE; // expected-warning {{'is_always_equal' is deprecated}} } { typedef std::allocator::is_always_equal IAE; // expected-warning {{'is_always_equal' is deprecated}} 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 7085a1d3fc602..581bdced36a0d 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 @@ -61,8 +61,5 @@ void test() { int main(int, char**) { test(); -#ifdef _LIBCPP_VERSION - test(); // 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 2fb7a60c9a88f..e8c48439b9f46 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 @@ -39,6 +39,6 @@ void check() void f() { check(); - check(); + check(); check(); } diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx26.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx26.verify.cpp index 72cc21402327a..07332ec37bc37 100644 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx26.verify.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.removed_in_cxx26.verify.cpp @@ -29,6 +29,6 @@ void check() { void test() { check(); - check(); + check(); check(); } diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp index 47d4bba51be61..334517861e7b3 100644 --- a/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.construct/construct_at.pass.cpp @@ -81,7 +81,7 @@ constexpr bool test() } { - std::allocator a; + std::allocator a; Counted const* p = a.allocate(2); int count = 0; std::construct_at(p, count); @@ -92,7 +92,7 @@ constexpr bool test() assert(count == 1); p->~Counted(); assert(count == 0); - a.deallocate(p, 2); + a.deallocate(const_cast(p), 2); } return true;