diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1010,6 +1010,12 @@ # define _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_IS_CONSTANT_EVALUATED #endif +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) && defined(__cpp_constexpr_dynamic_alloc) +# define _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC constexpr +#else +# define _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC +#endif + // The _LIBCPP_NODISCARD_ATTRIBUTE should only be used to define other // NODISCARD macros to the correct attribute. #if __has_cpp_attribute(nodiscard) || defined(_LIBCPP_COMPILER_MSVC) diff --git a/libcxx/include/memory b/libcxx/include/memory --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -129,11 +129,13 @@ constexpr allocator(const allocator&) noexcept; // constexpr in C++20 template constexpr allocator(const allocator&) noexcept; // constexpr in C++20 - ~allocator(); + constexpr ~allocator(); // constexpr in C++20 pointer address(reference x) const noexcept; const_pointer address(const_reference x) const noexcept; - pointer allocate(size_type, allocator::const_pointer hint = 0); - void deallocate(pointer p, size_type n) noexcept; + constexpr pointer // constexpr in C++20 + allocate(size_type, allocator::const_pointer hint = 0); + constexpr void // constexpr in C++20 + deallocate(pointer p, size_type n) noexcept; size_type max_size() const noexcept; template void construct(U* p, Args&&... args); @@ -142,10 +144,10 @@ }; template -bool operator==(const allocator&, const allocator&) noexcept; +constexpr bool operator==(const allocator&, const allocator&) noexcept; // constexpr in C++20 template -bool operator!=(const allocator&, const allocator&) noexcept; +constexpr bool operator!=(const allocator&, const allocator&) noexcept; // constexpr in C++20 template class raw_storage_iterator @@ -1844,7 +1846,7 @@ {return _VSTD::addressof(__x);} _LIBCPP_INLINE_VISIBILITY const_pointer address(const_reference __x) const _NOEXCEPT {return _VSTD::addressof(__x);} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC pointer allocate(size_type __n, allocator::const_pointer = 0) { if (__n > max_size()) @@ -1852,9 +1854,10 @@ " 'n' exceeds maximum supported size"); return static_cast(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); } - _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC + void deallocate(pointer __p, size_type __n) _NOEXCEPT {_VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));} - _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type max_size() const _NOEXCEPT {return size_type(~0) / sizeof(_Tp);} #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template @@ -1946,16 +1949,18 @@ _LIBCPP_INLINE_VISIBILITY const_pointer address(const_reference __x) const _NOEXCEPT {return _VSTD::addressof(__x);} - _LIBCPP_INLINE_VISIBILITY pointer allocate(size_type __n, allocator::const_pointer = 0) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC + pointer allocate(size_type __n, allocator::const_pointer = 0) { if (__n > max_size()) __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))); } - _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC + void deallocate(pointer __p, size_type __n) _NOEXCEPT {_VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p), __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));} - _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 size_type max_size() const _NOEXCEPT {return size_type(~0) / sizeof(_Tp);} #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) template @@ -2022,11 +2027,11 @@ }; template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool operator==(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return true;} template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool operator!=(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return false;} template diff --git a/libcxx/include/new b/libcxx/include/new --- a/libcxx/include/new +++ b/libcxx/include/new @@ -234,7 +234,8 @@ #endif } -inline _LIBCPP_INLINE_VISIBILITY void *__libcpp_allocate(size_t __size, size_t __align) { +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC void* +__libcpp_allocate(size_t __size, size_t __align) { #ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION if (__is_overaligned_for_new(__align)) { const align_val_t __align_val = static_cast(__align); @@ -255,7 +256,40 @@ } struct _DeallocateCaller { - static inline _LIBCPP_INLINE_VISIBILITY + private: + template + static inline _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC + void __do_call(void *__ptr, _A1 __a1, _A2 __a2) { +#if defined(_LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE) || \ + defined(_LIBCPP_HAS_NO_BUILTIN_OVERLOADED_OPERATOR_NEW_DELETE) + return ::operator delete(__ptr, __a1, __a2); +#else + return __builtin_operator_delete(__ptr, __a1, __a2); +#endif + } + + template + static inline _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC + void __do_call(void *__ptr, _A1 __a1) { +#if defined(_LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE) || \ + defined(_LIBCPP_HAS_NO_BUILTIN_OVERLOADED_OPERATOR_NEW_DELETE) + return ::operator delete(__ptr, __a1); +#else + return __builtin_operator_delete(__ptr, __a1); +#endif + } + + static inline _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC + void __do_call(void *__ptr) { +#ifdef _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE + return ::operator delete(__ptr); +#else + return __builtin_operator_delete(__ptr); +#endif + } + + public: + static inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC void __do_deallocate_handle_size_align(void *__ptr, size_t __size, size_t __align) { #if defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) ((void)__align); @@ -286,7 +320,8 @@ } private: - static inline void __do_deallocate_handle_size(void *__ptr, size_t __size) { + static inline _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC void + __do_deallocate_handle_size(void* __ptr, size_t __size) { #ifdef _LIBCPP_HAS_NO_SIZED_DEALLOCATION ((void)__size); return __do_call(__ptr); @@ -296,7 +331,8 @@ } #ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION - static inline void __do_deallocate_handle_size(void *__ptr, size_t __size, align_val_t __align) { + static inline _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC void + __do_deallocate_handle_size(void *__ptr, size_t __size, align_val_t __align) { #ifdef _LIBCPP_HAS_NO_SIZED_DEALLOCATION ((void)__size); return __do_call(__ptr, __align); @@ -305,42 +341,15 @@ #endif } #endif - -private: - template - static inline void __do_call(void *__ptr, _A1 __a1, _A2 __a2) { -#if defined(_LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE) || \ - defined(_LIBCPP_HAS_NO_BUILTIN_OVERLOADED_OPERATOR_NEW_DELETE) - return ::operator delete(__ptr, __a1, __a2); -#else - return __builtin_operator_delete(__ptr, __a1, __a2); -#endif - } - - template - static inline void __do_call(void *__ptr, _A1 __a1) { -#if defined(_LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE) || \ - defined(_LIBCPP_HAS_NO_BUILTIN_OVERLOADED_OPERATOR_NEW_DELETE) - return ::operator delete(__ptr, __a1); -#else - return __builtin_operator_delete(__ptr, __a1); -#endif - } - - static inline void __do_call(void *__ptr) { -#ifdef _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE - return ::operator delete(__ptr); -#else - return __builtin_operator_delete(__ptr); -#endif - } }; -inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void* __ptr, size_t __size, size_t __align) { +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17_WITH_CONSTEXPR_DYNAMIC_ALLOC void +__libcpp_deallocate(void* __ptr, size_t __size, size_t __align) { _DeallocateCaller::__do_deallocate_handle_size_align(__ptr, __size, __align); } -inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate_unsized(void* __ptr, size_t __align) { +inline _LIBCPP_INLINE_VISIBILITY void +__libcpp_deallocate_unsized(void* __ptr, size_t __align) { _DeallocateCaller::__do_deallocate_handle_align(__ptr, __align); } diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.globals/eq.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.globals/eq.pass.cpp --- a/libcxx/test/std/utilities/memory/default.allocator/allocator.globals/eq.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.globals/eq.pass.cpp @@ -23,12 +23,24 @@ #include "test_macros.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool +test() { std::allocator a1; std::allocator a2; assert(a1 == a2); assert(!(a1 != a2)); + 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/default.allocator/allocator.members/allocate.fail.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.fail.cpp --- a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.fail.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.fail.cpp @@ -25,5 +25,14 @@ a.allocate(3); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}} a.allocate(3, nullptr); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}} +#if TEST_STD_VER > 17 && defined(__cpp_constexpr_dynamic_alloc) + static_assert([]() constexpr { // expected-error {{static_assert expression is not an integral constant expression}} + std::allocator a; + TEST_IGNORE_NODISCARD a.allocate(3); + + return true; + }()); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.pass.cpp --- a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.pass.cpp @@ -98,6 +98,18 @@ } } +#if TEST_STD_VER > 17 && defined(__cpp_constexpr_dynamic_alloc) +template +constexpr bool test_aligned_constexpr() { + typedef AlignedType T; + std::allocator a; + T* ap = a.allocate(3); + a.deallocate(ap, 3); + + return true; +} +#endif + int main(int, char**) { test_aligned<1>(); test_aligned<2>(); @@ -108,5 +120,16 @@ test_aligned(); test_aligned(); +#if TEST_STD_VER > 17 && defined(__cpp_constexpr_dynamic_alloc) + static_assert(test_aligned_constexpr<1>()); + static_assert(test_aligned_constexpr<2>()); + static_assert(test_aligned_constexpr<4>()); + static_assert(test_aligned_constexpr<8>()); + static_assert(test_aligned_constexpr<16>()); + static_assert(test_aligned_constexpr()); + static_assert(test_aligned_constexpr()); + static_assert(test_aligned_constexpr()); +#endif + return 0; } diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.fail.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.fail.cpp copy from libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.fail.cpp copy to libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.fail.cpp --- a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.fail.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.size.fail.cpp @@ -19,11 +19,20 @@ #include "test_macros.h" +template +constexpr bool test() +{ + std::allocator a; + TEST_IGNORE_NODISCARD a.allocate(((size_t) -1) / sizeof(T) + 1); + TEST_IGNORE_NODISCARD a.allocate((size_t) -1); + + return true; +} + int main(int, char**) { - std::allocator a; - a.allocate(3); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}} - a.allocate(3, nullptr); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}} + static_assert(test()); // expected-error {{static_assert expression is not an integral constant expression}} + LIBCPP_STATIC_ASSERT(test()); // expected-error {{static_assert expression is not an integral constant expression}} 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 --- a/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_types.pass.cpp @@ -33,7 +33,8 @@ #include "test_macros.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool +test() { static_assert((std::is_same::size_type, std::size_t>::value), ""); static_assert((std::is_same::difference_type, std::ptrdiff_t>::value), ""); @@ -54,5 +55,16 @@ std::allocator a3 = a2; ((void)a3); + 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/default.allocator/allocator_void.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator_void.pass.cpp --- a/libcxx/test/std/utilities/memory/default.allocator/allocator_void.pass.cpp +++ b/libcxx/test/std/utilities/memory/default.allocator/allocator_void.pass.cpp @@ -24,7 +24,8 @@ #include "test_macros.h" -int main(int, char**) +TEST_CONSTEXPR_CXX20 bool +test() { static_assert((std::is_same::pointer, void*>::value), ""); static_assert((std::is_same::const_pointer, const void*>::value), ""); @@ -35,5 +36,16 @@ std::allocator a2 = a; a2 = a; + return true; +} + +int main(int, char**) +{ + test(); + +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; }