diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -14,6 +14,7 @@ #include <__atomic/cxx_atomic_impl.h> #include <__atomic/memory_order.h> #include <__config> +#include <__memory/addressof.h> #include <__type_traits/is_function.h> #include <__type_traits/is_same.h> #include <__type_traits/remove_pointer.h> @@ -82,28 +83,28 @@ _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _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(&this->__a_, __op, __m); + 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 { // __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(&this->__a_, __op, __m); + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); } _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _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(&this->__a_, __op, __m); + 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 { // __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(&this->__a_, __op, __m); + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); } _LIBCPP_HIDE_FROM_ABI @@ -160,7 +161,7 @@ void atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { - std::__cxx_atomic_init(&__o->__a_, __d); + std::__cxx_atomic_init(std::addressof(__o->__a_), __d); } template @@ -168,7 +169,7 @@ void atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { - std::__cxx_atomic_init(&__o->__a_, __d); + std::__cxx_atomic_init(std::addressof(__o->__a_), __d); } // atomic_store diff --git a/libcxx/include/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h --- a/libcxx/include/__atomic/atomic_base.h +++ b/libcxx/include/__atomic/atomic_base.h @@ -16,6 +16,7 @@ #include <__atomic/memory_order.h> #include <__availability> #include <__config> +#include <__memory/addressof.h> #include <__type_traits/is_integral.h> #include <__type_traits/is_nothrow_default_constructible.h> #include <__type_traits/is_same.h> @@ -42,81 +43,87 @@ _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const _NOEXCEPT {return static_cast<__atomic_base const volatile*>(this)->is_lock_free();} - _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(&__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) - {std::__cxx_atomic_store(&__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(&__a_, __m);} - _LIBCPP_HIDE_FROM_ABI - _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) - {return std::__cxx_atomic_load(&__a_, __m);} + _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) { + 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_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 - _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_exchange(&__a_, __d, __m);} - _LIBCPP_HIDE_FROM_ABI - _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_exchange(&__a_, __d, __m);} - _LIBCPP_HIDE_FROM_ABI - bool compare_exchange_weak(_Tp& __e, _Tp __d, - memory_order __s, memory_order __f) volatile _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __s, __f);} - _LIBCPP_HIDE_FROM_ABI - 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(&__a_, &__e, __d, __s, __f);} - _LIBCPP_HIDE_FROM_ABI - bool compare_exchange_strong(_Tp& __e, _Tp __d, - memory_order __s, memory_order __f) volatile _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __s, __f);} - _LIBCPP_HIDE_FROM_ABI - 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(&__a_, &__e, __d, __s, __f);} - _LIBCPP_HIDE_FROM_ABI - bool compare_exchange_weak(_Tp& __e, _Tp __d, - memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} - _LIBCPP_HIDE_FROM_ABI - bool compare_exchange_weak(_Tp& __e, _Tp __d, - memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} - _LIBCPP_HIDE_FROM_ABI - bool compare_exchange_strong(_Tp& __e, _Tp __d, - memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} - _LIBCPP_HIDE_FROM_ABI - bool compare_exchange_strong(_Tp& __e, _Tp __d, - memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} - - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT - {std::__cxx_atomic_wait(&__a_, __v, __m);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT - {std::__cxx_atomic_wait(&__a_, __v, __m);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT - {std::__cxx_atomic_notify_one(&__a_);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT - {std::__cxx_atomic_notify_one(&__a_);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT - {std::__cxx_atomic_notify_all(&__a_);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT - {std::__cxx_atomic_notify_all(&__a_);} + _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 { + return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT + _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_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_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT + _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_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_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 + 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); + } + _LIBCPP_HIDE_FROM_ABI bool + 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 + 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); + } + + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const + volatile _NOEXCEPT { + std::__cxx_atomic_wait(std::addressof(__a_), __v, __m); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void + wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT { + std::__cxx_atomic_wait(std::addressof(__a_), __v, __m); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { + std::__cxx_atomic_notify_one(std::addressof(__a_)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { + std::__cxx_atomic_notify_one(std::addressof(__a_)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { + std::__cxx_atomic_notify_all(std::addressof(__a_)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { + std::__cxx_atomic_notify_all(std::addressof(__a_)); + } #if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr @@ -151,36 +158,36 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} - _LIBCPP_HIDE_FROM_ABI - _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_fetch_add(&this->__a_, __op, __m);} - _LIBCPP_HIDE_FROM_ABI - _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_add(&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(&this->__a_, __op, __m);} - _LIBCPP_HIDE_FROM_ABI - _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_sub(&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(&this->__a_, __op, __m);} - _LIBCPP_HIDE_FROM_ABI - _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_and(&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(&this->__a_, __op, __m);} - _LIBCPP_HIDE_FROM_ABI - _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_or(&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(&this->__a_, __op, __m);} - _LIBCPP_HIDE_FROM_ABI - _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_xor(&this->__a_, __op, __m);} + _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 { + 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 { + 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 { + 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 { + 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 { + 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));} diff --git a/libcxx/include/__atomic/atomic_sync.h b/libcxx/include/__atomic/atomic_sync.h --- a/libcxx/include/__atomic/atomic_sync.h +++ b/libcxx/include/__atomic/atomic_sync.h @@ -15,6 +15,7 @@ #include <__availability> #include <__chrono/duration.h> #include <__config> +#include <__memory/addressof.h> #include <__thread/poll_with_backoff.h> #include <__threading_support> #include <__type_traits/decay.h> @@ -84,7 +85,7 @@ template _LIBCPP_HIDE_FROM_ABI bool __cxx_nonatomic_compare_equal(_Tp const& __lhs, _Tp const& __rhs) { - return std::memcmp(&__lhs, &__rhs, sizeof(_Tp)) == 0; + return std::memcmp(std::addressof(__lhs), std::addressof(__rhs), sizeof(_Tp)) == 0; } template diff --git a/libcxx/include/__atomic/cxx_atomic_impl.h b/libcxx/include/__atomic/cxx_atomic_impl.h --- a/libcxx/include/__atomic/cxx_atomic_impl.h +++ b/libcxx/include/__atomic/cxx_atomic_impl.h @@ -12,6 +12,7 @@ #include <__atomic/is_always_lock_free.h> #include <__atomic/memory_order.h> #include <__config> +#include <__memory/addressof.h> #include <__type_traits/conditional.h> #include <__type_traits/is_assignable.h> #include <__type_traits/is_trivially_copyable.h> @@ -39,9 +40,9 @@ template _LIBCPP_HIDE_FROM_ABI typename enable_if::value>::type __cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) { - volatile char* __to = reinterpret_cast(&__a_value); + volatile char* __to = reinterpret_cast(std::addressof(__a_value)); volatile char* __end = __to + sizeof(_Tp); - volatile const char* __from = reinterpret_cast(&__val); + volatile const char* __from = reinterpret_cast(std::addressof(__val)); while (__to != __end) *__to++ = *__from++; } @@ -110,16 +111,14 @@ _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { - __atomic_store(&__a->__a_value, &__val, - __to_gcc_order(__order)); + __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) { - __atomic_store(&__a->__a_value, &__val, - __to_gcc_order(__order)); + __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); } template @@ -127,8 +126,7 @@ _Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { _Tp __ret; - __atomic_load(&__a->__a_value, &__ret, - __to_gcc_order(__order)); + __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); return __ret; } @@ -136,8 +134,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { _Tp __ret; - __atomic_load(&__a->__a_value, &__ret, - __to_gcc_order(__order)); + __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); return __ret; } @@ -146,8 +143,8 @@ _Tp __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { _Tp __ret; - __atomic_exchange(&__a->__a_value, &__value, &__ret, - __to_gcc_order(__order)); + __atomic_exchange( + std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); return __ret; } @@ -156,8 +153,8 @@ _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) { _Tp __ret; - __atomic_exchange(&__a->__a_value, &__value, &__ret, - __to_gcc_order(__order)); + __atomic_exchange( + std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); return __ret; } @@ -166,10 +163,13 @@ bool __cxx_atomic_compare_exchange_strong( volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { - return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, - false, - __to_gcc_order(__success), - __to_gcc_failure_order(__failure)); + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + false, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); } template @@ -177,10 +177,13 @@ 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(&__a->__a_value, __expected, &__value, - false, - __to_gcc_order(__success), - __to_gcc_failure_order(__failure)); + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + false, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); } template @@ -188,10 +191,13 @@ bool __cxx_atomic_compare_exchange_weak( volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) { - return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, - true, - __to_gcc_order(__success), - __to_gcc_failure_order(__failure)); + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + true, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); } template @@ -199,10 +205,13 @@ 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(&__a->__a_value, __expected, &__value, - true, - __to_gcc_order(__success), - __to_gcc_failure_order(__failure)); + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + true, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); } template @@ -222,80 +231,70 @@ _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { - return __atomic_fetch_add(&__a->__a_value, __delta * __skip_amt<_Tp>::value, - __to_gcc_order(__order)); + return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { - return __atomic_fetch_add(&__a->__a_value, __delta * __skip_amt<_Tp>::value, - __to_gcc_order(__order)); + return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { - return __atomic_fetch_sub(&__a->__a_value, __delta * __skip_amt<_Tp>::value, - __to_gcc_order(__order)); + return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) { - return __atomic_fetch_sub(&__a->__a_value, __delta * __skip_amt<_Tp>::value, - __to_gcc_order(__order)); + return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { - return __atomic_fetch_and(&__a->__a_value, __pattern, - __to_gcc_order(__order)); + return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { - return __atomic_fetch_and(&__a->__a_value, __pattern, - __to_gcc_order(__order)); + return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { - return __atomic_fetch_or(&__a->__a_value, __pattern, - __to_gcc_order(__order)); + return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { - return __atomic_fetch_or(&__a->__a_value, __pattern, - __to_gcc_order(__order)); + return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { - return __atomic_fetch_xor(&__a->__a_value, __pattern, - __to_gcc_order(__order)); + return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) { - return __atomic_fetch_xor(&__a->__a_value, __pattern, - __to_gcc_order(__order)); + return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); } #define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0) @@ -331,47 +330,51 @@ template _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val) _NOEXCEPT { - __c11_atomic_init(&__a->__a_value, __val); + __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 { - __c11_atomic_init(&__a->__a_value, __val); + __c11_atomic_init(std::addressof(__a->__a_value), __val); } template _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_order __order) _NOEXCEPT { - __c11_atomic_store(&__a->__a_value, __val, static_cast<__memory_order_underlying_t>(__order)); + __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> * __a, _Tp __val, memory_order __order) _NOEXCEPT { - __c11_atomic_store(&__a->__a_value, __val, static_cast<__memory_order_underlying_t>(__order)); + __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order __order) _NOEXCEPT { using __ptr_type = __remove_const_t__a_value)>*; - return __c11_atomic_load(const_cast<__ptr_type>(&__a->__a_value), static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_load( + 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 { using __ptr_type = __remove_const_t__a_value)>*; - return __c11_atomic_load(const_cast<__ptr_type>(&__a->__a_value), static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_load( + const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, memory_order __order) _NOEXCEPT { - return __c11_atomic_exchange(&__a->__a_value, __value, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_exchange( + std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> * __a, _Tp __value, memory_order __order) _NOEXCEPT { - return __c11_atomic_exchange(&__a->__a_value, __value, static_cast<__memory_order_underlying_t>(__order)); + 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) { @@ -384,99 +387,133 @@ template _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { - return __c11_atomic_compare_exchange_strong(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); + return __c11_atomic_compare_exchange_strong( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template _LIBCPP_HIDE_FROM_ABI 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(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); + return __c11_atomic_compare_exchange_strong( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { - return __c11_atomic_compare_exchange_weak(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); + return __c11_atomic_compare_exchange_weak( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template _LIBCPP_HIDE_FROM_ABI 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(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); + return __c11_atomic_compare_exchange_weak( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_and(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_and( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_and(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_and( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_or(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_or( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_or(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_or( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_xor(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_xor( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); } template _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_xor(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); + return __c11_atomic_fetch_xor( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); } #endif // _LIBCPP_HAS_GCC_ATOMIC_IMP, _LIBCPP_HAS_C_ATOMIC_IMP diff --git a/libcxx/test/std/atomics/atomics.types.generic/general.compile.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/general.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.types.generic/general.compile.pass.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03 + +// This test requires the dylib support introduced in D68480, which shipped in macOS 11.0. +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} + +// + +// Tests the basic features and makes sure they work with a hijacking operator&. + +// template struct atomic { +// using value_type = T; +// +// static constexpr bool is_always_lock_free = implementation-defined; +// bool is_lock_free() const volatile noexcept; +// bool is_lock_free() const noexcept; +// +// // [atomics.types.operations], operations on atomic types +// constexpr atomic() noexcept(is_nothrow_default_constructible_v); +// constexpr atomic(T) noexcept; +// atomic(const atomic&) = delete; +// atomic& operator=(const atomic&) = delete; +// atomic& operator=(const atomic&) volatile = delete; +// +// T load(memory_order = memory_order::seq_cst) const volatile noexcept; +// T load(memory_order = memory_order::seq_cst) const noexcept; +// operator T() const volatile noexcept; +// operator T() const noexcept; +// void store(T, memory_order = memory_order::seq_cst) volatile noexcept; +// void store(T, memory_order = memory_order::seq_cst) noexcept; +// T operator=(T) volatile noexcept; +// T operator=(T) noexcept; +// +// T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept; +// T exchange(T, memory_order = memory_order::seq_cst) noexcept; +// bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept; +// bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept; +// bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept; +// bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept; +// bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; +// bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept; +// bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; +// bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept; +// +// void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept; +// void wait(T, memory_order = memory_order::seq_cst) const noexcept; +// void notify_one() volatile noexcept; +// void notify_one() noexcept; +// void notify_all() volatile noexcept; +// void notify_all() noexcept; +// }; + +#include +#include + +#include "operator_hijacker.h" +#include "test_macros.h" + +template +void test() { + T a; + typename T::value_type v; +#if TEST_STD_VER >= 20 + std::memory_order m = std::memory_order::seq_cst; +#else + std::memory_order m = std::memory_order_seq_cst; +#endif + + TEST_IGNORE_NODISCARD a.is_lock_free(); + + TEST_IGNORE_NODISCARD T(); + TEST_IGNORE_NODISCARD T(v); + + TEST_IGNORE_NODISCARD a.load(); + TEST_IGNORE_NODISCARD static_cast(a); + a.store(v); + a = v; + + TEST_IGNORE_NODISCARD a.exchange(v); + TEST_IGNORE_NODISCARD a.compare_exchange_weak(v, v, m, m); + TEST_IGNORE_NODISCARD a.compare_exchange_strong(v, v, m, m); + TEST_IGNORE_NODISCARD a.compare_exchange_weak(v, v); + TEST_IGNORE_NODISCARD a.compare_exchange_strong(v, v, m); + + a.wait(v); + a.notify_one(); + a.notify_all(); +} + +void test() { + test>(); + test>(); +} diff --git a/libcxx/test/std/atomics/atomics.types.generic/pointer.compile.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/pointer.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.types.generic/pointer.compile.pass.cpp @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03 + +// This test requires the dylib support introduced in D68480, which shipped in macOS 11.0. +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} + +// + +// Tests the basic features and makes sure they work with a hijacking operator&. + +// template struct atomic { +// using value_type = T*; +// using difference_type = ptrdiff_t; +// +// static constexpr bool is_always_lock_free = implementation-defined; +// bool is_lock_free() const volatile noexcept; +// bool is_lock_free() const noexcept; +// +// constexpr atomic() noexcept; +// constexpr atomic(T*) noexcept; +// atomic(const atomic&) = delete; +// atomic& operator=(const atomic&) = delete; +// atomic& operator=(const atomic&) volatile = delete; +// +// void store(T*, memory_order = memory_order::seq_cst) volatile noexcept; +// void store(T*, memory_order = memory_order::seq_cst) noexcept; +// T* operator=(T*) volatile noexcept; +// T* operator=(T*) noexcept; +// T* load(memory_order = memory_order::seq_cst) const volatile noexcept; +// T* load(memory_order = memory_order::seq_cst) const noexcept; +// operator T*() const volatile noexcept; +// operator T*() const noexcept; +// +// T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept; +// T* exchange(T*, memory_order = memory_order::seq_cst) noexcept; +// bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept; +// bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept; +// bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept; +// bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept; +// bool compare_exchange_weak(T*&, T*, +// memory_order = memory_order::seq_cst) volatile noexcept; +// bool compare_exchange_weak(T*&, T*, +// memory_order = memory_order::seq_cst) noexcept; +// bool compare_exchange_strong(T*&, T*, +// memory_order = memory_order::seq_cst) volatile noexcept; +// bool compare_exchange_strong(T*&, T*, +// memory_order = memory_order::seq_cst) noexcept; +// +// T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; +// T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; +// T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; +// T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; +// +// T* operator++(int) volatile noexcept; +// T* operator++(int) noexcept; +// T* operator--(int) volatile noexcept; +// T* operator--(int) noexcept; +// T* operator++() volatile noexcept; +// T* operator++() noexcept; +// T* operator--() volatile noexcept; +// T* operator--() noexcept; +// T* operator+=(ptrdiff_t) volatile noexcept; +// T* operator+=(ptrdiff_t) noexcept; +// T* operator-=(ptrdiff_t) volatile noexcept; +// T* operator-=(ptrdiff_t) noexcept; +// +// void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; +// void wait(T*, memory_order = memory_order::seq_cst) const noexcept; +// void notify_one() volatile noexcept; +// void notify_one() noexcept; +// void notify_all() volatile noexcept; +// void notify_all() noexcept; +// }; + +#include +#include + +#include "operator_hijacker.h" +#include "test_macros.h" + +template +void test() { + T a; + typename T::value_type v = nullptr; +#if TEST_STD_VER >= 20 + std::memory_order m = std::memory_order::seq_cst; +#else + std::memory_order m = std::memory_order_seq_cst; +#endif + + TEST_IGNORE_NODISCARD a.is_lock_free(); + + a.store(v); + a = v; + TEST_IGNORE_NODISCARD T(); + TEST_IGNORE_NODISCARD T(v); + TEST_IGNORE_NODISCARD a.load(); + TEST_IGNORE_NODISCARD static_cast(a); + TEST_IGNORE_NODISCARD* a; + + TEST_IGNORE_NODISCARD a.exchange(v); + TEST_IGNORE_NODISCARD a.compare_exchange_weak(v, v, m, m); + TEST_IGNORE_NODISCARD a.compare_exchange_strong(v, v, m, m); + TEST_IGNORE_NODISCARD a.compare_exchange_weak(v, v); + TEST_IGNORE_NODISCARD a.compare_exchange_strong(v, v, m); + + TEST_IGNORE_NODISCARD a.fetch_add(0); + TEST_IGNORE_NODISCARD a.fetch_sub(0); + + TEST_IGNORE_NODISCARD a++; + TEST_IGNORE_NODISCARD a--; + TEST_IGNORE_NODISCARD++ a; + TEST_IGNORE_NODISCARD-- a; + a += 0; + a -= 0; + + a.wait(v); + a.notify_one(); + a.notify_all(); +} + +void test() { + test>(); + test>(); +} diff --git a/libcxx/test/support/operator_hijacker.h b/libcxx/test/support/operator_hijacker.h --- a/libcxx/test/support/operator_hijacker.h +++ b/libcxx/test/support/operator_hijacker.h @@ -31,6 +31,13 @@ friend void operator||(T&&, U&&) = delete; }; +static_assert(std::is_trivially_copyable::value && // + std::is_copy_constructible::value && // + std::is_move_constructible::value && // + std::is_copy_assignable::value && // + std::is_move_assignable::value, // + "does not satisfy the requirements for atomic"); + template <> struct std::hash { size_t operator()(const operator_hijacker&) const { return 0; }