diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index a1506e115fe70..4e847bccc136b 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -404,6 +404,8 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_bitset`` ``202306L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_atomic`` ``202406L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_new`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_constrained_equality`` *unimplemented* diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h index bd3f659c22df0..5d16e965ee0ed 100644 --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -67,7 +67,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> { using value_type = _Tp*; using difference_type = ptrdiff_t; - _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 atomic() _NOEXCEPT = default; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {} @@ -75,7 +75,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> { __base::store(__d); return __d; } - _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator=(_Tp* __d) _NOEXCEPT { __base::store(__d); return __d; } @@ -86,7 +86,8 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> { return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* + fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); @@ -98,24 +99,29 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> { return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* + fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { // __atomic_fetch_add accepts function pointers, guard against them. static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); } _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT { return fetch_add(1); } - _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); } _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT { return fetch_sub(1); } - _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); } _LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT { return fetch_add(1) + 1; } - _LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; } _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT { return fetch_sub(1) - 1; } - _LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; } _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; } - _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { + return fetch_add(__op) + __op; + } _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; } - _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { + return fetch_sub(__op) - __op; + } atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; @@ -151,7 +157,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> { } template - _LIBCPP_HIDE_FROM_ABI static _Tp + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Tp __rmw_op(_This&& __self, _Tp __operand, memory_order __m, _Operation __operation, _BuiltinOp __builtin_op) { if constexpr (__has_rmw_builtin()) { return __builtin_op(std::addressof(std::forward<_This>(__self).__a_), __operand, __m); @@ -174,7 +180,8 @@ struct atomic<_Tp> : __atomic_base<_Tp> { } template - _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_add(_This&& __self, _Tp __operand, memory_order __m) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Tp + __fetch_add(_This&& __self, _Tp __operand, memory_order __m) { auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) { return std::__cxx_atomic_fetch_add(__a, __builtin_operand, __order); }; @@ -182,7 +189,8 @@ struct atomic<_Tp> : __atomic_base<_Tp> { } template - _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_sub(_This&& __self, _Tp __operand, memory_order __m) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Tp + __fetch_sub(_This&& __self, _Tp __operand, memory_order __m) { auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) { return std::__cxx_atomic_fetch_sub(__a, __builtin_operand, __order); }; @@ -207,7 +215,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> { __base::store(__d); return __d; } - _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator=(_Tp __d) noexcept { __base::store(__d); return __d; } @@ -218,7 +226,8 @@ struct atomic<_Tp> : __atomic_base<_Tp> { return __fetch_add(*this, __op, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept { return __fetch_add(*this, __op, __m); } @@ -228,7 +237,8 @@ struct atomic<_Tp> : __atomic_base<_Tp> { return __fetch_sub(*this, __op, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept { return __fetch_sub(*this, __op, __m); } @@ -238,7 +248,9 @@ struct atomic<_Tp> : __atomic_base<_Tp> { return fetch_add(__op) + __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) noexcept { return fetch_add(__op) + __op; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator+=(_Tp __op) noexcept { + return fetch_add(__op) + __op; + } _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile noexcept requires __base::is_always_lock_free @@ -246,7 +258,9 @@ struct atomic<_Tp> : __atomic_base<_Tp> { return fetch_sub(__op) - __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) noexcept { return fetch_sub(__op) - __op; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator-=(_Tp __op) noexcept { + return fetch_sub(__op) - __op; + } }; #endif // _LIBCPP_STD_VER >= 20 @@ -272,7 +286,7 @@ atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NO } template -_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void +_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { std::__cxx_atomic_init(std::addressof(__o->__a_), __d); } @@ -285,7 +299,8 @@ _LIBCPP_HIDE_FROM_ABI void atomic_store(volatile atomic<_Tp>* __o, typename atom } template -_LIBCPP_HIDE_FROM_ABI void atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void +atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { __o->store(__d); } @@ -299,7 +314,7 @@ atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_typ } template -_LIBCPP_HIDE_FROM_ABI void +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { __o->store(__d, __m); @@ -313,7 +328,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT } template -_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT { return __o->load(); } @@ -326,8 +341,8 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const volatile atomic<_Tp>* __o, } template -_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp +atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { return __o->load(__m); } @@ -339,7 +354,8 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(volatile atomic<_Tp>* __o, typename at } template -_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp +atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { return __o->exchange(__d); } @@ -352,7 +368,7 @@ atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_ } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT { return __o->exchange(__d, __m); } @@ -366,7 +382,7 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak( } template -_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool atomic_compare_exchange_weak( atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT { return __o->compare_exchange_weak(*__e, __d); } @@ -380,7 +396,7 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong( } template -_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool atomic_compare_exchange_strong( atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT { return __o->compare_exchange_strong(*__e, __d); } @@ -398,7 +414,7 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit( } template -_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool atomic_compare_exchange_weak_explicit( atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, @@ -420,7 +436,7 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit( } template -_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool atomic_compare_exchange_strong_explicit( atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, @@ -438,7 +454,7 @@ atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __ } template -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT { return __o->wait(__v); } @@ -453,7 +469,7 @@ atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::valu } template -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { return __o->wait(__v, __m); @@ -467,7 +483,7 @@ atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT { __o->notify_one(); } template -_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void +_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT { __o->notify_one(); } @@ -480,7 +496,7 @@ atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT { __o->notify_all(); } template -_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void +_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT { __o->notify_all(); } @@ -494,7 +510,8 @@ atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_typ } template -_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp +atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT { return __o->fetch_add(__op); } @@ -507,7 +524,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add_explicit( } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_add(__op, __m); } @@ -521,7 +538,8 @@ atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_typ } template -_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp +atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT { return __o->fetch_sub(__op); } @@ -534,7 +552,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub_explicit( } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_sub(__op, __m); } @@ -547,7 +565,8 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(volatile atomic<_Tp>* __o, typename a } template ::value && !is_same<_Tp, bool>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp +atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { return __o->fetch_and(__op); } @@ -560,7 +579,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and_explicit( } template ::value && !is_same<_Tp, bool>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_and(__op, __m); } @@ -573,7 +592,8 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(volatile atomic<_Tp>* __o, typename at } template ::value && !is_same<_Tp, bool>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp +atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { return __o->fetch_or(__op); } @@ -586,7 +606,7 @@ atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_ } template ::value && !is_same<_Tp, bool>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_or(__op, __m); } @@ -599,7 +619,8 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(volatile atomic<_Tp>* __o, typename a } template ::value && !is_same<_Tp, bool>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp +atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT { return __o->fetch_xor(__op); } @@ -612,7 +633,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor_explicit( } template ::value && !is_same<_Tp, bool>::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT { return __o->fetch_xor(__op, __m); } diff --git a/libcxx/include/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h index 7e26434c9c3a0..9d10aae1a72c1 100644 --- a/libcxx/include/__atomic/atomic_base.h +++ b/libcxx/include/__atomic/atomic_base.h @@ -40,30 +40,31 @@ struct __atomic_base // false return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>)); } _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const _NOEXCEPT { - return static_cast<__atomic_base const volatile*>(this)->is_lock_free(); + return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>)); } _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { std::__cxx_atomic_store(std::addressof(__a_), __d, __m); } - _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT - _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { std::__cxx_atomic_store(std::addressof(__a_), __d, __m); } _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { return std::__cxx_atomic_load(std::addressof(__a_), __m); } - _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { return std::__cxx_atomic_load(std::addressof(__a_), __m); } _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT { return load(); } - _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 operator _Tp() const _NOEXCEPT { return load(); } _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); } _LIBCPP_HIDE_FROM_ABI bool @@ -71,7 +72,8 @@ struct __atomic_base // false _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); } - _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); } @@ -80,7 +82,8 @@ struct __atomic_base // false _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); } - _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); } @@ -88,7 +91,7 @@ struct __atomic_base // false compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); } - _LIBCPP_HIDE_FROM_ABI bool + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); } @@ -96,7 +99,7 @@ struct __atomic_base // false compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); } - _LIBCPP_HIDE_FROM_ABI bool + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); } @@ -105,18 +108,32 @@ struct __atomic_base // false volatile _NOEXCEPT { std::__atomic_wait(*this, __v, __m); } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT { - std::__atomic_wait(*this, __v, __m); + if (__libcpp_is_constant_evaluated()) { + if (this->load(__m) != __v) { + __builtin_trap(); + } + } else { + std::__atomic_wait(*this, __v, __m); + } } _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { std::__atomic_notify_one(*this); } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void notify_one() _NOEXCEPT { + if (!__libcpp_is_constant_evaluated()) { + std::__atomic_notify_one(*this); + } + } _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { std::__atomic_notify_all(*this); } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void notify_all() _NOEXCEPT { + if (!__libcpp_is_constant_evaluated()) { + std::__atomic_notify_all(*this); + } + } #if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {} @@ -142,52 +159,67 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> { _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); } _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); } _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); } _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); } _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); } _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT { return fetch_add(_Tp(1)); } - _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); } _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT { return fetch_sub(_Tp(1)); } - _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); } _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); } - _LIBCPP_HIDE_FROM_ABI _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); } _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); } - _LIBCPP_HIDE_FROM_ABI _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); } _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) _NOEXCEPT { return fetch_add(__op) + __op; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator+=(_Tp __op) _NOEXCEPT { + return fetch_add(__op) + __op; + } _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) _NOEXCEPT { return fetch_sub(__op) - __op; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator-=(_Tp __op) _NOEXCEPT { + return fetch_sub(__op) - __op; + } _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT { return fetch_and(__op) & __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) _NOEXCEPT { return fetch_and(__op) & __op; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator&=(_Tp __op) _NOEXCEPT { + return fetch_and(__op) & __op; + } _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT { return fetch_or(__op) | __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) _NOEXCEPT { return fetch_or(__op) | __op; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator|=(_Tp __op) _NOEXCEPT { + return fetch_or(__op) | __op; + } _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT { return fetch_xor(__op) ^ __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator^=(_Tp __op) _NOEXCEPT { + return fetch_xor(__op) ^ __op; + } }; // Here we need _IsIntegral because the default template argument is not enough @@ -196,7 +228,8 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> { // __atomic_base. So specializing __atomic_base<_Tp> does not work template struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > { - static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_base<_Tp, _IsIntegral>& __a, memory_order __order) { + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + __atomic_load(const __atomic_base<_Tp, _IsIntegral>& __a, memory_order __order) { return __a.load(__order); } @@ -205,7 +238,7 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > { return __this.load(__order); } - static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<_Tp>* + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const __cxx_atomic_impl<_Tp>* __atomic_contention_address(const __atomic_base<_Tp, _IsIntegral>& __a) { return std::addressof(__a.__a_); } diff --git a/libcxx/include/__atomic/atomic_flag.h b/libcxx/include/__atomic/atomic_flag.h index 00b157cdff78b..1df5d7f28cb8f 100644 --- a/libcxx/include/__atomic/atomic_flag.h +++ b/libcxx/include/__atomic/atomic_flag.h @@ -31,20 +31,22 @@ struct atomic_flag { _LIBCPP_HIDE_FROM_ABI bool test(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT { return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m); } - _LIBCPP_HIDE_FROM_ABI bool test(memory_order __m = memory_order_seq_cst) const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + test(memory_order __m = memory_order_seq_cst) const _NOEXCEPT { return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m); } _LIBCPP_HIDE_FROM_ABI bool test_and_set(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m); } - _LIBCPP_HIDE_FROM_ABI bool test_and_set(memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool + test_and_set(memory_order __m = memory_order_seq_cst) _NOEXCEPT { return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m); } _LIBCPP_HIDE_FROM_ABI void clear(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { __cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m); } - _LIBCPP_HIDE_FROM_ABI void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT { __cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m); } @@ -52,20 +54,22 @@ struct atomic_flag { wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT { std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m); } - _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void + _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT { std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m); } _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { std::__atomic_notify_one(*this); } - _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { + _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); } _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { std::__atomic_notify_all(*this); } - _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { + _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); } @@ -75,7 +79,7 @@ struct atomic_flag { atomic_flag() _NOEXCEPT = default; #endif - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION atomic_flag(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) = delete; @@ -84,7 +88,8 @@ struct atomic_flag { template <> struct __atomic_waitable_traits { - static _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATOMIC_FLAG_TYPE __atomic_load(const atomic_flag& __a, memory_order __order) { + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_ATOMIC_FLAG_TYPE + __atomic_load(const atomic_flag& __a, memory_order __order) { return std::__cxx_atomic_load(&__a.__a_, __order); } @@ -93,7 +98,7 @@ struct __atomic_waitable_traits { return std::__cxx_atomic_load(&__a.__a_, __order); } - static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE>* + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE>* __atomic_contention_address(const atomic_flag& __a) { return std::addressof(__a.__a_); } @@ -106,14 +111,17 @@ struct __atomic_waitable_traits { inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); } -inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const atomic_flag* __o) _NOEXCEPT { return __o->test(); } +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool atomic_flag_test(const atomic_flag* __o) _NOEXCEPT { + return __o->test(); +} inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT { return __o->test(__m); } -inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool +atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT { return __o->test(__m); } @@ -121,26 +129,32 @@ inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(volatile atomic_flag* return __o->test_and_set(); } -inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT { return __o->test_and_set(); } +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT { + return __o->test_and_set(); +} inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT { return __o->test_and_set(__m); } -inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool +atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT { return __o->test_and_set(__m); } inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT { __o->clear(); } -inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear(atomic_flag* __o) _NOEXCEPT { __o->clear(); } +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_flag_clear(atomic_flag* __o) _NOEXCEPT { + __o->clear(); +} inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT { __o->clear(__m); } -inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT { +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void +atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT { __o->clear(__m); } @@ -149,7 +163,7 @@ atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT { __o->wait(__v); } -inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT { __o->wait(__v); } @@ -159,7 +173,7 @@ atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_orde __o->wait(__v, __m); } -inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT { __o->wait(__v, __m); } @@ -169,7 +183,7 @@ atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_one(); } -inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT { __o->notify_one(); } @@ -179,7 +193,7 @@ atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_all(); } -inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC _LIBCPP_CONSTEXPR_SINCE_CXX26 void atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT { __o->notify_all(); } diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h index 2849b82e1a3dd..a686f831c9d71 100644 --- a/libcxx/include/__atomic/atomic_ref.h +++ b/libcxx/include/__atomic/atomic_ref.h @@ -27,6 +27,7 @@ #include <__memory/addressof.h> #include <__type_traits/has_unique_object_representation.h> #include <__type_traits/is_trivially_copyable.h> +#include <__utility/exchange.h> #include #include #include @@ -60,10 +61,10 @@ struct __atomic_ref_base { protected: _Tp* __ptr_; - _LIBCPP_HIDE_FROM_ABI __atomic_ref_base(_Tp& __obj) : __ptr_(std::addressof(__obj)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __atomic_ref_base(_Tp& __obj) : __ptr_(std::addressof(__obj)) {} private: - _LIBCPP_HIDE_FROM_ABI static _Tp* __clear_padding(_Tp& __val) noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Tp* __clear_padding(_Tp& __val) noexcept { _Tp* __ptr = std::addressof(__val); # if __has_builtin(__builtin_clear_padding) __builtin_clear_padding(__ptr); @@ -71,7 +72,7 @@ struct __atomic_ref_base { return __ptr; } - _LIBCPP_HIDE_FROM_ABI static bool __compare_exchange( + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static bool __compare_exchange( _Tp* __ptr, _Tp* __expected, _Tp* __desired, bool __is_weak, int __success, int __failure) noexcept { if constexpr ( # if __has_builtin(__builtin_clear_padding) @@ -122,110 +123,187 @@ struct __atomic_ref_base { _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); } - _LIBCPP_HIDE_FROM_ABI void store(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + store(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept _LIBCPP_CHECK_STORE_MEMORY_ORDER(__order) { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( __order == memory_order::relaxed || __order == memory_order::release || __order == memory_order::seq_cst, "atomic_ref: memory order argument to atomic store operation is invalid"); - __atomic_store(__ptr_, __clear_padding(__desired), std::__to_gcc_order(__order)); + if (__libcpp_is_constant_evaluated()) { + *__ptr_ = __desired; + } else { + __atomic_store(__ptr_, __clear_padding(__desired), std::__to_gcc_order(__order)); + } } - _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator=(_Tp __desired) const noexcept { store(__desired); return __desired; } - _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __order = memory_order::seq_cst) const noexcept - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__order) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + load(memory_order __order = memory_order::seq_cst) const noexcept _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__order) { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( __order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire || __order == memory_order::seq_cst, "atomic_ref: memory order argument to atomic load operation is invalid"); - alignas(_Tp) byte __mem[sizeof(_Tp)]; - auto* __ret = reinterpret_cast<_Tp*>(__mem); - __atomic_load(__ptr_, __ret, std::__to_gcc_order(__order)); - return *__ret; + if (__libcpp_is_constant_evaluated()) { + return *__ptr_; + } else { + alignas(_Tp) byte __mem[sizeof(_Tp)]; + auto* __ret = reinterpret_cast<_Tp*>(__mem); + __atomic_load(__ptr_, __ret, std::__to_gcc_order(__order)); + return *__ret; + } } - _LIBCPP_HIDE_FROM_ABI operator _Tp() const noexcept { return load(); } - - _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { - alignas(_Tp) byte __mem[sizeof(_Tp)]; - auto* __ret = reinterpret_cast<_Tp*>(__mem); - __atomic_exchange(__ptr_, __clear_padding(__desired), __ret, std::__to_gcc_order(__order)); - return *__ret; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 operator _Tp() const noexcept { return load(); } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + exchange(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { + if (__libcpp_is_constant_evaluated()) { + return std::exchange(*__ptr_, __desired); + } else { + alignas(_Tp) byte __mem[sizeof(_Tp)]; + auto* __ret = reinterpret_cast<_Tp*>(__mem); + __atomic_exchange(__ptr_, __clear_padding(__desired), __ret, std::__to_gcc_order(__order)); + return *__ret; + } } - _LIBCPP_HIDE_FROM_ABI bool + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool compare_exchange_weak(_Tp& __expected, _Tp __desired, memory_order __success, memory_order __failure) const noexcept _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( __failure == memory_order::relaxed || __failure == memory_order::consume || __failure == memory_order::acquire || __failure == memory_order::seq_cst, "atomic_ref: failure memory order argument to weak atomic compare-and-exchange operation is invalid"); - return __compare_exchange( - __ptr_, - std::addressof(__expected), - std::addressof(__desired), - true, - std::__to_gcc_order(__success), - std::__to_gcc_order(__failure)); - } - _LIBCPP_HIDE_FROM_ABI bool + if (__libcpp_is_constant_evaluated()) { + const _Tp __original = *__ptr_; + if (__original == __expected) { + *__ptr_ = __desired; + __expected = __original; + return true; + } else { + __expected = __original; + return false; + } + } else { + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + true, + std::__to_gcc_order(__success), + std::__to_gcc_order(__failure)); + } + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool compare_exchange_strong(_Tp& __expected, _Tp __desired, memory_order __success, memory_order __failure) const noexcept _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( __failure == memory_order::relaxed || __failure == memory_order::consume || __failure == memory_order::acquire || __failure == memory_order::seq_cst, "atomic_ref: failure memory order argument to strong atomic compare-and-exchange operation is invalid"); - return __compare_exchange( - __ptr_, - std::addressof(__expected), - std::addressof(__desired), - false, - std::__to_gcc_order(__success), - std::__to_gcc_order(__failure)); + if (__libcpp_is_constant_evaluated()) { + const _Tp __original = *__ptr_; + if (__original == __expected) { + *__ptr_ = __desired; + __expected = __original; + return true; + } else { + __expected = __original; + return false; + } + } else { + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + false, + std::__to_gcc_order(__success), + std::__to_gcc_order(__failure)); + } } - _LIBCPP_HIDE_FROM_ABI bool + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool compare_exchange_weak(_Tp& __expected, _Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { - return __compare_exchange( - __ptr_, - std::addressof(__expected), - std::addressof(__desired), - true, - std::__to_gcc_order(__order), - std::__to_gcc_failure_order(__order)); - } - _LIBCPP_HIDE_FROM_ABI bool + if (__libcpp_is_constant_evaluated()) { + if (*__ptr_ == __expected) { + __expected = *__ptr_; + *__ptr_ = __desired; + return true; + } else { + __expected = *__ptr_; + return false; + } + } else { + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + true, + std::__to_gcc_order(__order), + std::__to_gcc_failure_order(__order)); + } + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool compare_exchange_strong(_Tp& __expected, _Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { - return __compare_exchange( - __ptr_, - std::addressof(__expected), - std::addressof(__desired), - false, - std::__to_gcc_order(__order), - std::__to_gcc_failure_order(__order)); + if (__libcpp_is_constant_evaluated()) { + if (*__ptr_ == __expected) { + __expected = *__ptr_; + *__ptr_ = __desired; + return true; + } else { + __expected = *__ptr_; + return false; + } + } else { + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + false, + std::__to_gcc_order(__order), + std::__to_gcc_failure_order(__order)); + } } - _LIBCPP_HIDE_FROM_ABI void wait(_Tp __old, memory_order __order = memory_order::seq_cst) const noexcept + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void + wait(_Tp __old, memory_order __order = memory_order::seq_cst) const noexcept _LIBCPP_CHECK_WAIT_MEMORY_ORDER(__order) { - _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( - __order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire || - __order == memory_order::seq_cst, - "atomic_ref: memory order argument to atomic wait operation is invalid"); - std::__atomic_wait(*this, __old, __order); + if (__libcpp_is_constant_evaluated()) { + if (*__ptr_ != __old) { + __builtin_trap(); + } + } else { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire || + __order == memory_order::seq_cst, + "atomic_ref: memory order argument to atomic wait operation is invalid"); + std::__atomic_wait(*this, __old, __order); + } + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void notify_one() const noexcept { + if (!__libcpp_is_constant_evaluated()) { + std::__atomic_notify_one(*this); + } + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void notify_all() const noexcept { + if (!__libcpp_is_constant_evaluated()) { + std::__atomic_notify_all(*this); + } } - _LIBCPP_HIDE_FROM_ABI void notify_one() const noexcept { std::__atomic_notify_one(*this); } - _LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); } }; template struct __atomic_waitable_traits<__atomic_ref_base<_Tp>> { - static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_ref_base<_Tp>& __a, memory_order __order) { + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + __atomic_load(const __atomic_ref_base<_Tp>& __a, memory_order __order) { return __a.load(__order); } - static _LIBCPP_HIDE_FROM_ABI const _Tp* __atomic_contention_address(const __atomic_ref_base<_Tp>& __a) { + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const _Tp* + __atomic_contention_address(const __atomic_ref_base<_Tp>& __a) { return __a.__ptr_; } }; @@ -236,15 +314,21 @@ struct atomic_ref : public __atomic_ref_base<_Tp> { using __base = __atomic_ref_base<_Tp>; - _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit atomic_ref(_Tp& __obj) : __base(__obj) { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( +# if __has_builtin(__builtin_is_aligned) + __builtin_is_aligned(std::addressof(__obj), __base::required_alignment), +# else reinterpret_cast(std::addressof(__obj)) % __base::required_alignment == 0, +# endif "atomic_ref ctor: referenced object must be aligned to required_alignment"); } - _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 atomic_ref(const atomic_ref&) noexcept = default; - _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator=(_Tp __desired) const noexcept { + return __base::operator=(__desired); + } atomic_ref& operator=(const atomic_ref&) = delete; }; @@ -256,43 +340,68 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { using difference_type = __base::value_type; - _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit atomic_ref(_Tp& __obj) : __base(__obj) { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( +# if __has_builtin(__builtin_is_aligned) + __builtin_is_aligned(std::addressof(__obj), __base::required_alignment), +# else reinterpret_cast(std::addressof(__obj)) % __base::required_alignment == 0, +# endif "atomic_ref ctor: referenced object must be aligned to required_alignment"); } - _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 atomic_ref(const atomic_ref&) noexcept = default; - _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator=(_Tp __desired) const noexcept { + return __base::operator=(__desired); + } atomic_ref& operator=(const atomic_ref&) = delete; - _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { return __atomic_fetch_add(this->__ptr_, __arg, std::__to_gcc_order(__order)); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { return __atomic_fetch_sub(this->__ptr_, __arg, std::__to_gcc_order(__order)); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_and(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { return __atomic_fetch_and(this->__ptr_, __arg, std::__to_gcc_order(__order)); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_or(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { return __atomic_fetch_or(this->__ptr_, __arg, std::__to_gcc_order(__order)); } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_xor(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { return __atomic_fetch_xor(this->__ptr_, __arg, std::__to_gcc_order(__order)); } - _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) const noexcept { return fetch_add(_Tp(1)); } - _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) const noexcept { return fetch_sub(_Tp(1)); } - _LIBCPP_HIDE_FROM_ABI _Tp operator++() const noexcept { return fetch_add(_Tp(1)) + _Tp(1); } - _LIBCPP_HIDE_FROM_ABI _Tp operator--() const noexcept { return fetch_sub(_Tp(1)) - _Tp(1); } - _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; } - _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; } - _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __arg) const noexcept { return fetch_and(__arg) & __arg; } - _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __arg) const noexcept { return fetch_or(__arg) | __arg; } - _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __arg) const noexcept { return fetch_xor(__arg) ^ __arg; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator++(int) const noexcept { return fetch_add(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator--(int) const noexcept { return fetch_sub(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator++() const noexcept { + return fetch_add(_Tp(1)) + _Tp(1); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator--() const noexcept { + return fetch_sub(_Tp(1)) - _Tp(1); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator+=(_Tp __arg) const noexcept { + return fetch_add(__arg) + __arg; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator-=(_Tp __arg) const noexcept { + return fetch_sub(__arg) - __arg; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator&=(_Tp __arg) const noexcept { + return fetch_and(__arg) & __arg; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator|=(_Tp __arg) const noexcept { + return fetch_or(__arg) | __arg; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator^=(_Tp __arg) const noexcept { + return fetch_xor(__arg) ^ __arg; + } }; template @@ -302,19 +411,26 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { using difference_type = __base::value_type; - _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit atomic_ref(_Tp& __obj) : __base(__obj) { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( +# if __has_builtin(__builtin_is_aligned) + __builtin_is_aligned(std::addressof(__obj), __base::required_alignment), +# else reinterpret_cast(std::addressof(__obj)) % __base::required_alignment == 0, +# endif "atomic_ref ctor: referenced object must be aligned to required_alignment"); } - _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 atomic_ref(const atomic_ref&) noexcept = default; - _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator=(_Tp __desired) const noexcept { + return __base::operator=(__desired); + } atomic_ref& operator=(const atomic_ref&) = delete; - _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { _Tp __old = this->load(memory_order_relaxed); _Tp __new = __old + __arg; while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) { @@ -322,7 +438,8 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { } return __old; } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp + fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { _Tp __old = this->load(memory_order_relaxed); _Tp __new = __old - __arg; while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) { @@ -331,8 +448,12 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { return __old; } - _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; } - _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator+=(_Tp __arg) const noexcept { + return fetch_add(__arg) + __arg; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator-=(_Tp __arg) const noexcept { + return fetch_sub(__arg) - __arg; + } }; template @@ -341,25 +462,33 @@ struct atomic_ref<_Tp*> : public __atomic_ref_base<_Tp*> { using difference_type = ptrdiff_t; - _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp*& __ptr) : __base(__ptr) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit atomic_ref(_Tp*& __ptr) : __base(__ptr) {} - _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __desired) const noexcept { return __base::operator=(__desired); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator=(_Tp* __desired) const noexcept { + return __base::operator=(__desired); + } atomic_ref& operator=(const atomic_ref&) = delete; - _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* + fetch_add(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept { return __atomic_fetch_add(this->__ptr_, __arg * sizeof(_Tp), std::__to_gcc_order(__order)); } - _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* + fetch_sub(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept { return __atomic_fetch_sub(this->__ptr_, __arg * sizeof(_Tp), std::__to_gcc_order(__order)); } - _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) const noexcept { return fetch_add(1); } - _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) const noexcept { return fetch_sub(1); } - _LIBCPP_HIDE_FROM_ABI _Tp* operator++() const noexcept { return fetch_add(1) + 1; } - _LIBCPP_HIDE_FROM_ABI _Tp* operator--() const noexcept { return fetch_sub(1) - 1; } - _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __arg) const noexcept { return fetch_add(__arg) + __arg; } - _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __arg) const noexcept { return fetch_sub(__arg) - __arg; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator++(int) const noexcept { return fetch_add(1); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator--(int) const noexcept { return fetch_sub(1); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator++() const noexcept { return fetch_add(1) + 1; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator--() const noexcept { return fetch_sub(1) - 1; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator+=(ptrdiff_t __arg) const noexcept { + return fetch_add(__arg) + __arg; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator-=(ptrdiff_t __arg) const noexcept { + return fetch_sub(__arg) - __arg; + } }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(atomic_ref); diff --git a/libcxx/include/__atomic/cxx_atomic_impl.h b/libcxx/include/__atomic/cxx_atomic_impl.h index 18e88aa97bec7..7ef64e93e5c95 100644 --- a/libcxx/include/__atomic/cxx_atomic_impl.h +++ b/libcxx/include/__atomic/cxx_atomic_impl.h @@ -14,6 +14,7 @@ #include <__config> #include <__memory/addressof.h> #include <__type_traits/is_assignable.h> +#include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_trivially_copyable.h> #include <__type_traits/remove_const.h> #include @@ -30,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // the default operator= in an object is not volatile, a byte-by-byte copy // is required. template ::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR void __cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) { __a_value = __val; } template ::value, int> = 0> @@ -44,7 +45,7 @@ _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp volatile& __a_value, template struct __cxx_atomic_base_impl { - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR # ifndef _LIBCPP_CXX03_LANG __cxx_atomic_base_impl() _NOEXCEPT = default; # else @@ -61,15 +62,15 @@ _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp } template -_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { __a->__a_value = __val; } -_LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR inline void __cxx_atomic_thread_fence(memory_order __order) { __atomic_thread_fence(__to_gcc_order(__order)); } -_LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR inline void __cxx_atomic_signal_fence(memory_order __order) { __atomic_signal_fence(__to_gcc_order(__order)); } @@ -80,7 +81,8 @@ __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_ } template -_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR void +__cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); } @@ -98,13 +100,14 @@ __cxx_atomic_load_inplace(const volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* } template -_LIBCPP_HIDE_FROM_ABI void +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR void __cxx_atomic_load_inplace(const __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) { __atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp +__cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { _Tp __ret; __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); return __ret; @@ -120,7 +123,8 @@ __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __value, me } template -_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp +__cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { _Tp __ret; __atomic_exchange( std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); @@ -144,7 +148,7 @@ _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( } template -_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __cxx_atomic_compare_exchange_strong( __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { return __atomic_compare_exchange( std::addressof(__a->__a_value), @@ -172,7 +176,7 @@ _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( } template -_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __cxx_atomic_compare_exchange_weak( __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { return __atomic_compare_exchange( std::addressof(__a->__a_value), @@ -207,7 +211,8 @@ __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, m } template -_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp +__cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } @@ -218,7 +223,8 @@ __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, m } template -_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp +__cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } @@ -229,7 +235,7 @@ __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); } @@ -241,7 +247,8 @@ __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, } template -_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp +__cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); } @@ -252,7 +259,7 @@ __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); } @@ -263,7 +270,7 @@ __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_o template struct __cxx_atomic_base_impl { - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR # ifndef _LIBCPP_CXX03_LANG __cxx_atomic_base_impl() _NOEXCEPT = default; # else @@ -276,12 +283,16 @@ struct __cxx_atomic_base_impl { # define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s) -_LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT { - __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order)); +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR inline void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT { + if (!__libcpp_is_constant_evaluated()) { + __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order)); + } } -_LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT { - __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order)); +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR inline void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT { + if (!__libcpp_is_constant_evaluated()) { + __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order)); + } } template @@ -289,7 +300,7 @@ _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatil __c11_atomic_init(std::addressof(__a->__a_value), __val); } template -_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) _NOEXCEPT { __c11_atomic_init(std::addressof(__a->__a_value), __val); } @@ -299,7 +310,7 @@ __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_ __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI void +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) _NOEXCEPT { __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); } @@ -312,7 +323,8 @@ __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp +__cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT { using __ptr_type = __remove_const_t__a_value)>*; return __c11_atomic_load( const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); @@ -326,7 +338,7 @@ __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const volatile* __a, _Tp* const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI void +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR void __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const* __a, _Tp* __dst, memory_order __order) _NOEXCEPT { using __ptr_type = __remove_const_t__a_value)>*; *__dst = __c11_atomic_load( @@ -340,13 +352,13 @@ __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, me std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) _NOEXCEPT { return __c11_atomic_exchange( std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); } -_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR inline memory_order __to_failure_order(memory_order __order) { // Avoid switch statement to make this a constexpr. return __order == memory_order_release ? memory_order_relaxed @@ -368,7 +380,7 @@ _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template -_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __cxx_atomic_compare_exchange_strong( __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { return __c11_atomic_compare_exchange_strong( @@ -394,7 +406,7 @@ _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template -_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __cxx_atomic_compare_exchange_weak( __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { return __c11_atomic_compare_exchange_weak( @@ -412,7 +424,7 @@ __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, m std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_add( std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); @@ -425,7 +437,7 @@ __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __d std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp* +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_add( std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); @@ -438,7 +450,7 @@ __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, m std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_sub( std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); @@ -450,7 +462,7 @@ __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __d std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp* +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_sub( std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); @@ -463,7 +475,7 @@ __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_and( std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); @@ -476,7 +488,7 @@ __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_or( std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); @@ -489,7 +501,7 @@ __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); } template -_LIBCPP_HIDE_FROM_ABI _Tp +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { return __c11_atomic_fetch_xor( std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); @@ -501,7 +513,7 @@ template > struct __cxx_atomic_impl : public _Base { static_assert(is_trivially_copyable<_Tp>::value, "std::atomic requires that 'T' be a trivially copyable type"); - _LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __cxx_atomic_impl() _NOEXCEPT = default; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {} }; diff --git a/libcxx/include/__config b/libcxx/include/__config index 0be25a5fd226f..64207c3ad7f9e 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -796,6 +796,12 @@ typedef __char32_t char32_t; # define _LIBCPP_CONSTEXPR_SINCE_CXX23 # endif +# if _LIBCPP_STD_VER >= 26 +# define _LIBCPP_CONSTEXPR_SINCE_CXX26 constexpr +# else +# define _LIBCPP_CONSTEXPR_SINCE_CXX26 +# endif + # ifndef _LIBCPP_WEAK # define _LIBCPP_WEAK __attribute__((__weak__)) # endif diff --git a/libcxx/include/version b/libcxx/include/version index fe64343eafbc9..f49a4c2ebeeef 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -61,6 +61,7 @@ __cpp_lib_clamp 201603L __cpp_lib_complex_udls 201309L __cpp_lib_concepts 202002L __cpp_lib_constexpr_algorithms 201806L +__cpp_lib_constexpr_atomic 202406L __cpp_lib_constexpr_bitset 202207L __cpp_lib_constexpr_charconv 202207L __cpp_lib_constexpr_cmath 202202L @@ -510,6 +511,9 @@ __cpp_lib_void_t 201411L # undef __cpp_lib_bind_front # define __cpp_lib_bind_front 202306L # define __cpp_lib_bitset 202306L +# if __has_constexpr_builtin(__c11_atomic_load) +# define __cpp_lib_constexpr_atomic 202406L +# endif // # define __cpp_lib_constexpr_new 202406L // # define __cpp_lib_constrained_equality 202403L // # define __cpp_lib_copyable_function 202306L diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp index 9ed18fbfe19ac..2d68d50cfca9e 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp @@ -26,6 +26,7 @@ __cpp_lib_atomic_value_initialization 201911L [C++20] __cpp_lib_atomic_wait 201907L [C++20] __cpp_lib_char8_t 201907L [C++20] + __cpp_lib_constexpr_atomic 202406L [C++26] */ #include @@ -73,6 +74,10 @@ # error "__cpp_lib_char8_t should not be defined before c++20" # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + #elif TEST_STD_VER == 14 # ifdef __cpp_lib_atomic_flag_test @@ -115,6 +120,10 @@ # error "__cpp_lib_char8_t should not be defined before c++20" # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + #elif TEST_STD_VER == 17 # ifdef __cpp_lib_atomic_flag_test @@ -160,6 +169,10 @@ # error "__cpp_lib_char8_t should not be defined before c++20" # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + #elif TEST_STD_VER == 20 # ifndef __cpp_lib_atomic_flag_test @@ -253,6 +266,10 @@ # endif # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + #elif TEST_STD_VER == 23 # ifndef __cpp_lib_atomic_flag_test @@ -346,6 +363,10 @@ # endif # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + #elif TEST_STD_VER > 23 # ifndef __cpp_lib_atomic_flag_test @@ -448,5 +469,18 @@ # endif # endif +# if __has_constexpr_builtin(__c11_atomic_load) +# ifndef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should be defined in c++26" +# endif +# if __cpp_lib_constexpr_atomic != 202406L +# error "__cpp_lib_constexpr_atomic should have the value 202406L in c++26" +# endif +# else +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined when the requirement '__has_constexpr_builtin(__c11_atomic_load)' is not met!" +# endif +# endif + #endif // TEST_STD_VER > 23 diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index b8bad696f1bae..59f4528b3c845 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -56,6 +56,7 @@ __cpp_lib_complex_udls 201309L [C++14] __cpp_lib_concepts 202002L [C++20] __cpp_lib_constexpr_algorithms 201806L [C++20] + __cpp_lib_constexpr_atomic 202406L [C++26] __cpp_lib_constexpr_bitset 202207L [C++23] __cpp_lib_constexpr_charconv 202207L [C++23] __cpp_lib_constexpr_cmath 202202L [C++23] @@ -402,6 +403,10 @@ # error "__cpp_lib_constexpr_algorithms should not be defined before c++20" # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + # ifdef __cpp_lib_constexpr_bitset # error "__cpp_lib_constexpr_bitset should not be defined before c++23" # endif @@ -1266,6 +1271,10 @@ # error "__cpp_lib_constexpr_algorithms should not be defined before c++20" # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + # ifdef __cpp_lib_constexpr_bitset # error "__cpp_lib_constexpr_bitset should not be defined before c++23" # endif @@ -2232,6 +2241,10 @@ # error "__cpp_lib_constexpr_algorithms should not be defined before c++20" # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + # ifdef __cpp_lib_constexpr_bitset # error "__cpp_lib_constexpr_bitset should not be defined before c++23" # endif @@ -3438,6 +3451,10 @@ # error "__cpp_lib_constexpr_algorithms should have the value 201806L in c++20" # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + # ifdef __cpp_lib_constexpr_bitset # error "__cpp_lib_constexpr_bitset should not be defined before c++23" # endif @@ -4857,6 +4874,10 @@ # error "__cpp_lib_constexpr_algorithms should have the value 201806L in c++23" # endif +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined before c++26" +# endif + # ifndef __cpp_lib_constexpr_bitset # error "__cpp_lib_constexpr_bitset should be defined in c++23" # endif @@ -6492,6 +6513,19 @@ # error "__cpp_lib_constexpr_algorithms should have the value 201806L in c++26" # endif +# if __has_constexpr_builtin(__c11_atomic_load) +# ifndef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should be defined in c++26" +# endif +# if __cpp_lib_constexpr_atomic != 202406L +# error "__cpp_lib_constexpr_atomic should have the value 202406L in c++26" +# endif +# else +# ifdef __cpp_lib_constexpr_atomic +# error "__cpp_lib_constexpr_atomic should not be defined when the requirement '__has_constexpr_builtin(__c11_atomic_load)' is not met!" +# endif +# endif + # ifndef __cpp_lib_constexpr_bitset # error "__cpp_lib_constexpr_bitset should be defined in c++26" # endif diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 6c42748002aee..7501e75f58cba 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -318,6 +318,13 @@ def add_version_header(tc): }, "headers": ["algorithm", "utility"], }, + { + "name": "__cpp_lib_constexpr_atomic", + "values": {"c++26": 202406}, + "headers": ["atomic"], + "libcxx_guard": "__has_constexpr_builtin(__c11_atomic_load)", + "test_suite_guard": "__has_constexpr_builtin(__c11_atomic_load)", + }, { "name": "__cpp_lib_constexpr_bitset", "values": {"c++23": 202207},