diff --git a/libcxx/include/memory b/libcxx/include/memory --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -1569,21 +1569,21 @@ {typedef allocator_traits::other> other;}; #endif // _LIBCPP_CXX03_LANG - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static pointer allocate(allocator_type& __a, size_type __n) {return __a.allocate(__n);} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static pointer allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) {return __allocate(__a, __n, __hint, __has_allocate_hint());} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void deallocate(allocator_type& __a, pointer __p, size_type __n) _NOEXCEPT {__a.deallocate(__p, __n);} #ifndef _LIBCPP_HAS_NO_VARIADICS template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void construct(allocator_type& __a, _Tp* __p, _Args&&... __args) {__construct(__has_construct(), __a, __p, _VSTD::forward<_Args>(__args)...);} @@ -1618,15 +1618,15 @@ #endif // _LIBCPP_HAS_NO_VARIADICS template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void destroy(allocator_type& __a, _Tp* __p) {__destroy(__has_destroy(), __a, __p);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static size_type max_size(const allocator_type& __a) _NOEXCEPT {return __max_size(__has_max_size(), __a);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static allocator_type select_on_container_copy_construction(const allocator_type& __a) {return __select_on_container_copy_construction( @@ -1634,7 +1634,7 @@ __a);} template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void __construct_forward_with_exception_guarantees(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2) @@ -1652,7 +1652,7 @@ } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static typename enable_if < @@ -1672,7 +1672,7 @@ } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void __construct_range_forward(allocator_type& __a, _Iter __begin1, _Iter __end1, _Ptr& __begin2) @@ -1684,7 +1684,7 @@ template ::type, class _RawDestTp = typename remove_const<_DestTp>::type> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static typename enable_if < @@ -1705,7 +1705,7 @@ } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void __construct_backward_with_exception_guarantees(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2) @@ -1726,7 +1726,7 @@ } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static typename enable_if < @@ -1745,27 +1745,28 @@ private: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static pointer __allocate(allocator_type& __a, size_type __n, const_void_pointer __hint, true_type) _LIBCPP_SUPPRESS_DEPRECATED_PUSH {return __a.allocate(__n, __hint);} _LIBCPP_SUPPRESS_DEPRECATED_POP - _LIBCPP_INLINE_VISIBILITY + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static pointer __allocate(allocator_type& __a, size_type __n, const_void_pointer, false_type) {return __a.allocate(__n);} #ifndef _LIBCPP_HAS_NO_VARIADICS template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void __construct(true_type, allocator_type& __a, _Tp* __p, _Args&&... __args) _LIBCPP_SUPPRESS_DEPRECATED_PUSH {__a.construct(__p, _VSTD::forward<_Args>(__args)...);} _LIBCPP_SUPPRESS_DEPRECATED_POP template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void __construct(false_type, allocator_type&, _Tp* __p, _Args&&... __args) { ::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...); @@ -1786,33 +1787,33 @@ #endif // _LIBCPP_HAS_NO_VARIADICS template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void __destroy(true_type, allocator_type& __a, _Tp* __p) _LIBCPP_SUPPRESS_DEPRECATED_PUSH {__a.destroy(__p);} _LIBCPP_SUPPRESS_DEPRECATED_POP template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static void __destroy(false_type, allocator_type&, _Tp* __p) { __p->~_Tp(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static size_type __max_size(true_type, const allocator_type& __a) _NOEXCEPT _LIBCPP_SUPPRESS_DEPRECATED_PUSH {return __a.max_size();} _LIBCPP_SUPPRESS_DEPRECATED_POP - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static size_type __max_size(false_type, const allocator_type&) _NOEXCEPT {return numeric_limits::max() / sizeof(value_type);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static allocator_type __select_on_container_copy_construction(true_type, const allocator_type& __a) {return __a.select_on_container_copy_construction();} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 static allocator_type __select_on_container_copy_construction(false_type, const allocator_type& __a) {return __a;} @@ -1870,8 +1871,7 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC _Tp* allocate(size_t __n) { - // TODO(mpark): Replace with `allocator_traits::max_size(*this)`. - if (__n > (size_t(~0) / sizeof(_Tp))) + if (__n > allocator_traits::max_size(*this)) __throw_length_error("allocator::allocate(size_t n)" " 'n' exceeds maximum supported size"); return static_cast<_Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); @@ -1996,8 +1996,7 @@ _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC const _Tp* allocate(size_t __n) { - // TODO(mpark): Replace with `allocator_traits::max_size(*this)`. - if (__n > (size_t(~0) / sizeof(_Tp))) + if (__n > allocator_traits::max_size(*this)) __throw_length_error("allocator::allocate(size_t n)" " 'n' exceeds maximum supported size"); return static_cast(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); diff --git a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp --- a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp +++ b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp @@ -11,7 +11,7 @@ // template // struct allocator_traits // { -// static pointer allocate(allocator_type& a, size_type n); +// static constexpr pointer allocate(allocator_type& a, size_type n); // ... // }; @@ -27,25 +27,41 @@ { typedef T value_type; - value_type* allocate(std::size_t n) + TEST_CONSTEXPR_CXX20 A() {} + + TEST_CONSTEXPR_CXX20 value_type* allocate(std::size_t n) { assert(n == 10); - return reinterpret_cast(static_cast(0xDEADBEEF)); + return &storage; } + + value_type storage; }; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool +test() { { A a; - assert(std::allocator_traits >::allocate(a, 10) == reinterpret_cast(static_cast(0xDEADBEEF))); + assert(std::allocator_traits >::allocate(a, 10) == &a.storage); } { typedef IncompleteHolder* VT; typedef A Alloc; Alloc a; - assert(std::allocator_traits::allocate(a, 10) == reinterpret_cast(static_cast(0xDEADBEEF))); + assert(std::allocator_traits::allocate(a, 10) == &a.storage); } + return true; +} + +int main(int, char**) +{ + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp --- a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp +++ b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp @@ -12,7 +12,7 @@ // struct allocator_traits // { // template -// static void construct(allocator_type& a, Ptr p, Args&&... args); +// static constexpr void construct(allocator_type& a, Ptr p, Args&&... args); // ... // }; @@ -31,124 +31,148 @@ }; -int b_construct = 0; - template struct B { typedef T value_type; + TEST_CONSTEXPR_CXX20 B(int& count) : count(count) {} + #if TEST_STD_VER >= 11 template - void construct(U* p, Args&& ...args) + TEST_CONSTEXPR_DYNAMIC_ALLOC void construct(U* p, Args&& ...args) { - ++b_construct; + ++count; +#if TEST_STD_VER > 17 + std::construct_at(p, std::forward(args)...); +#else ::new ((void*)p) U(std::forward(args)...); +#endif } #endif + + int& count; }; struct A0 { - static int count; - A0() {++count;} + TEST_CONSTEXPR_CXX20 A0(int* count) {++*count;} }; -int A0::count = 0; - struct A1 { - static int count; - A1(char c) + TEST_CONSTEXPR_CXX20 A1(int* count, char c) { assert(c == 'c'); - ++count; + ++*count; } }; -int A1::count = 0; - struct A2 { - static int count; - A2(char c, int i) + TEST_CONSTEXPR_CXX20 A2(int* count, char c, int i) { assert(c == 'd'); assert(i == 5); - ++count; + ++*count; } }; -int A2::count = 0; - -int main(int, char**) +TEST_CONSTEXPR_DYNAMIC_ALLOC bool +test() { { - A0::count = 0; - A a; - std::aligned_storage::type a0; - assert(A0::count == 0); - std::allocator_traits >::construct(a, (A0*)&a0); - assert(A0::count == 1); + int A0_count = 0; + A a; + std::allocator alloc; + A0* a0 = alloc.allocate(1); + assert(A0_count == 0); + std::allocator_traits >::construct(a, a0, &A0_count); + assert(A0_count == 1); + alloc.deallocate(a0, 1); } { - A1::count = 0; - A a; - std::aligned_storage::type a1; - assert(A1::count == 0); - std::allocator_traits >::construct(a, (A1*)&a1, 'c'); - assert(A1::count == 1); + int A1_count = 0; + A a; + std::allocator alloc; + A1* a1 = alloc.allocate(1); + assert(A1_count == 0); + std::allocator_traits >::construct(a, a1, &A1_count, 'c'); + assert(A1_count == 1); + alloc.deallocate(a1, 1); } { - A2::count = 0; - A a; - std::aligned_storage::type a2; - assert(A2::count == 0); - std::allocator_traits >::construct(a, (A2*)&a2, 'd', 5); - assert(A2::count == 1); + int A2_count = 0; + A a; + std::allocator alloc; + A2* a2 = alloc.allocate(1); + assert(A2_count == 0); + std::allocator_traits >::construct(a, a2, &A2_count, 'd', 5); + assert(A2_count == 1); + alloc.deallocate(a2, 1); } { typedef IncompleteHolder* VT; typedef A Alloc; Alloc a; - std::aligned_storage::type store; - std::allocator_traits::construct(a, (VT*)&store, nullptr); + std::allocator alloc; + VT* vt = alloc.allocate(1); + std::allocator_traits::construct(a, vt, nullptr); + alloc.deallocate(vt, 1); } + #if TEST_STD_VER >= 11 { - A0::count = 0; - b_construct = 0; - B b; - std::aligned_storage::type a0; - assert(A0::count == 0); + int A0_count = 0; + int b_construct = 0; + B b(b_construct); + std::allocator alloc; + A0* a0 = alloc.allocate(1); + assert(A0_count == 0); assert(b_construct == 0); - std::allocator_traits >::construct(b, (A0*)&a0); - assert(A0::count == 1); + std::allocator_traits >::construct(b, a0, &A0_count); + assert(A0_count == 1); assert(b_construct == 1); + alloc.deallocate(a0, 1); } { - A1::count = 0; - b_construct = 0; - B b; - std::aligned_storage::type a1; - assert(A1::count == 0); + int A1_count = 0; + int b_construct = 0; + B b(b_construct); + std::allocator alloc; + A1* a1 = alloc.allocate(1); + assert(A1_count == 0); assert(b_construct == 0); - std::allocator_traits >::construct(b, (A1*)&a1, 'c'); - assert(A1::count == 1); + std::allocator_traits >::construct(b, a1, &A1_count, 'c'); + assert(A1_count == 1); assert(b_construct == 1); + alloc.deallocate(a1, 1); } { - A2::count = 0; - b_construct = 0; - B b; - std::aligned_storage::type a2; - assert(A2::count == 0); + int A2_count = 0; + int b_construct = 0; + B b(b_construct); + std::allocator alloc; + A2* a2 = alloc.allocate(1); + assert(A2_count == 0); assert(b_construct == 0); - std::allocator_traits >::construct(b, (A2*)&a2, 'd', 5); - assert(A2::count == 1); + std::allocator_traits >::construct(b, a2, &A2_count, 'd', 5); + assert(A2_count == 1); assert(b_construct == 1); + alloc.deallocate(a2, 1); } #endif + return true; +} + +int main(int, char**) +{ + test(); + +#if TEST_STD_VER > 17 && defined(__cpp_constexpr_dynamic_alloc) + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp --- a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp +++ b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp @@ -11,7 +11,7 @@ // template // struct allocator_traits // { -// static void deallocate(allocator_type& a, pointer p, size_type n); +// static constexpr void deallocate(allocator_type& a, pointer p, size_type n); // ... // }; @@ -22,36 +22,53 @@ #include "test_macros.h" #include "incomplete_type_helper.h" -int called = 0; - template struct A { typedef T value_type; - void deallocate(value_type* p, std::size_t n) + TEST_CONSTEXPR_CXX20 A(int& called) : called(called) {} + + TEST_CONSTEXPR_CXX20 void deallocate(value_type* p, std::size_t n) { - assert(p == reinterpret_cast(static_cast(0xDEADBEEF))); + assert(p == &storage); assert(n == 10); ++called; } + + int& called; + + value_type storage; }; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool +test() { { - A a; - std::allocator_traits >::deallocate(a, reinterpret_cast(static_cast(0xDEADBEEF)), 10); + int called = 0; + A a(called); + std::allocator_traits >::deallocate(a, &a.storage, 10); assert(called == 1); } - called = 0; { + int called = 0; typedef IncompleteHolder* VT; typedef A Alloc; - Alloc a; - std::allocator_traits::deallocate(a, reinterpret_cast(static_cast(0xDEADBEEF)), 10); + Alloc a(called); + std::allocator_traits::deallocate(a, &a.storage, 10); assert(called == 1); } + return true; +} + +int main(int, char**) +{ + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp --- a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp +++ b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp @@ -11,7 +11,7 @@ // template // struct allocator_traits // { -// static size_type max_size(const allocator_type& a) noexcept; +// static constexpr size_type max_size(const allocator_type& a) noexcept; // ... // }; @@ -36,13 +36,14 @@ { typedef T value_type; - size_t max_size() const + TEST_CONSTEXPR_CXX20 size_t max_size() const { return 100; } }; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool +test() { { B b; @@ -75,5 +76,16 @@ } #endif + return true; +} + +int main(int, char**) +{ + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp --- a/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp +++ b/libcxx/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp @@ -11,7 +11,7 @@ // template // struct allocator_traits // { -// static allocator_type +// static constexpr allocator_type // select_on_container_copy_construction(const allocator_type& a); // ... // }; @@ -29,7 +29,7 @@ { typedef T value_type; int id; - explicit A(int i = 0) : id(i) {} + TEST_CONSTEXPR_CXX20 explicit A(int i = 0) : id(i) {} }; @@ -39,15 +39,16 @@ typedef T value_type; int id; - explicit B(int i = 0) : id(i) {} + TEST_CONSTEXPR_CXX20 explicit B(int i = 0) : id(i) {} - B select_on_container_copy_construction() const + TEST_CONSTEXPR_CXX20 B select_on_container_copy_construction() const { return B(100); } }; -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool +test() { { A a; @@ -74,5 +75,16 @@ } #endif + return true; +} + +int main(int, char**) +{ + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; } diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -144,6 +144,7 @@ #define TEST_ALIGNAS(...) __attribute__((__aligned__(__VA_ARGS__))) #define TEST_CONSTEXPR #define TEST_CONSTEXPR_CXX14 +#define TEST_CONSTEXPR_DYNAMIC_ALLOC #define TEST_CONSTEXPR_CXX20 #define TEST_NOEXCEPT throw() #define TEST_NOEXCEPT_FALSE