From 25999a112f1567a841dafb22020eca17c3406f25 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 24 May 2018 16:28:26 +0100 Subject: [PATCH] Implement P0558R2 changes to std::atomic The restrictions forbidding arithmetic on atomic pointer types are only enabled for C++17 and later, retaining the GNU extension for older standards. The new nested typedefs and changes to prevent scalar parameters participating in template argument deduction are enabled unconditionally. PR libstdc++/69769 PR libstdc++/85886 * include/bits/atomic_base.h (__atomic_base::value_type) (__atomic_base::difference_type): Add new typedefs. * include/std/atomic (atomic::value_type, atomic::value_type) (atomic::value_type, atomic::difference_type): Likewise. (atomic::operator++, atomic::operator--) (atomic::operator+=, atomic::operator-=) (atomic::fetch_add, atomic::fetch_sub): Add static assertion to enforce C++17 requirement on pointer arithmetic. (__atomic_val_t, __atomic_diff_t): New alias templates. (atomic_init, atomic_store_explicit, atomic_exchange_explicit) (atomic_compare_exchange_weak_explicit) (atomic_compare_exchange_strong_explicit, atomic_store) (atomic_exchange, atomic_compare_exchange_weak) (atomic_compare_exchange_strong): Use __atomic_val_t to make scalar parameters be non-deduced contexts. (atomic_fetch_add_explicit, atomic_fetch_sub_explicit) (atomic_fetch_add, atomic_fetch_sub): Change first parameter to be atomic instead of __atomic_base, and use __atomic_diff_t for scalar parameters. (atomic_fetch_and_explicit, atomic_fetch_or_explicit) (atomic_fetch_xor_explicit, atomic_fetch_and, atomic_fetch_or) (atomic_fetch_xor): Use __atomic_val_t for scalar parameters. (atomic_fetch_add_explicit, atomic_fetch_sub_explicit) (atomic_fetch_add, atomic_fetch_sub): Remove overloads for atomic address types. * testsuite/29_atomics/atomic/60695.cc: Adjust dg-error lineno. * testsuite/29_atomics/atomic/69769.cc: New test. * testsuite/29_atomics/atomic/nonmembers.cc: New test. * testsuite/29_atomics/atomic/operators/pointer_partial_void.cc: Disable test for C++17 and later. * testsuite/29_atomics/atomic/requirements/typedefs.cc: New test. * testsuite/29_atomics/atomic_integral/nonmembers.cc: New test. * testsuite/29_atomics/atomic_integral/requirements/typedefs.cc: New test. From-SVN: r260676 --- libstdc++-v3/ChangeLog | 39 +++ libstdc++-v3/include/bits/atomic_base.h | 3 + libstdc++-v3/include/std/atomic | 320 +++++++++++------- .../testsuite/29_atomics/atomic/60695.cc | 2 +- .../testsuite/29_atomics/atomic/69769.cc | 80 +++++ .../testsuite/29_atomics/atomic/nonmembers.cc | 230 +++++++++++++ .../atomic/operators/pointer_partial_void.cc | 2 +- .../atomic/requirements/typedefs.cc | 36 ++ .../29_atomics/atomic_integral/nonmembers.cc | 163 +++++++++ .../atomic_integral/requirements/typedefs.cc | 39 +++ 10 files changed, 791 insertions(+), 123 deletions(-) create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic/69769.cc create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic/nonmembers.cc create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic/requirements/typedefs.cc create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_integral/nonmembers.cc create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_integral/requirements/typedefs.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 9fa9d1f4cf5..0f73c6a5531 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,42 @@ +2018-05-24 Jonathan Wakely + + PR libstdc++/69769 + PR libstdc++/85886 + * include/bits/atomic_base.h (__atomic_base::value_type) + (__atomic_base::difference_type): Add new typedefs. + * include/std/atomic (atomic::value_type, atomic::value_type) + (atomic::value_type, atomic::difference_type): Likewise. + (atomic::operator++, atomic::operator--) + (atomic::operator+=, atomic::operator-=) + (atomic::fetch_add, atomic::fetch_sub): Add static assertion + to enforce C++17 requirement on pointer arithmetic. + (__atomic_val_t, __atomic_diff_t): New alias templates. + (atomic_init, atomic_store_explicit, atomic_exchange_explicit) + (atomic_compare_exchange_weak_explicit) + (atomic_compare_exchange_strong_explicit, atomic_store) + (atomic_exchange, atomic_compare_exchange_weak) + (atomic_compare_exchange_strong): Use __atomic_val_t to make + scalar parameters be non-deduced contexts. + (atomic_fetch_add_explicit, atomic_fetch_sub_explicit) + (atomic_fetch_add, atomic_fetch_sub): Change first parameter to be + atomic instead of __atomic_base, and use __atomic_diff_t for scalar + parameters. + (atomic_fetch_and_explicit, atomic_fetch_or_explicit) + (atomic_fetch_xor_explicit, atomic_fetch_and, atomic_fetch_or) + (atomic_fetch_xor): Use __atomic_val_t for scalar parameters. + (atomic_fetch_add_explicit, atomic_fetch_sub_explicit) + (atomic_fetch_add, atomic_fetch_sub): Remove overloads for atomic + address types. + * testsuite/29_atomics/atomic/60695.cc: Adjust dg-error lineno. + * testsuite/29_atomics/atomic/69769.cc: New test. + * testsuite/29_atomics/atomic/nonmembers.cc: New test. + * testsuite/29_atomics/atomic/operators/pointer_partial_void.cc: + Disable test for C++17 and later. + * testsuite/29_atomics/atomic/requirements/typedefs.cc: New test. + * testsuite/29_atomics/atomic_integral/nonmembers.cc: New test. + * testsuite/29_atomics/atomic_integral/requirements/typedefs.cc: New + test. + 2018-05-23 Jonathan Wakely * include/bits/fs_path.h (path::__is_encoded_char): Change from class diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index a1fadcd8056..7a3354d9e6f 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -237,6 +237,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __atomic_base { + using value_type = _ITp; + using difference_type = value_type; + private: typedef _ITp __int_type; diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic index c234af83c2e..002604676cd 100644 --- a/libstdc++-v3/include/std/atomic +++ b/libstdc++-v3/include/std/atomic @@ -50,7 +50,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ -#if __cplusplus > 201402L +#if __cplusplus >= 201703L # define __cpp_lib_atomic_is_always_lock_free 201603 #endif @@ -62,6 +62,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<> struct atomic { + using value_type = bool; + private: __atomic_base _M_base; @@ -94,7 +96,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool is_lock_free() const volatile noexcept { return _M_base.is_lock_free(); } -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_BOOL_LOCK_FREE == 2; #endif @@ -173,6 +175,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct atomic { + using value_type = _Tp; + private: // Align 1/2/4/8/16-byte types to at least their size. static constexpr int _S_min_alignment @@ -229,7 +233,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION reinterpret_cast(-__alignof(_M_i))); } -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = __atomic_always_lock_free(sizeof(_M_i), 0); #endif @@ -351,6 +355,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct atomic<_Tp*> { + using value_type = _Tp*; + using difference_type = ptrdiff_t; + typedef _Tp* __pointer_type; typedef __atomic_base<_Tp*> __base_type; __base_type _M_b; @@ -379,51 +386,111 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __pointer_type operator++(int) noexcept - { return _M_b++; } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b++; + } __pointer_type operator++(int) volatile noexcept - { return _M_b++; } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b++; + } __pointer_type operator--(int) noexcept - { return _M_b--; } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b--; + } __pointer_type operator--(int) volatile noexcept - { return _M_b--; } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b--; + } __pointer_type operator++() noexcept - { return ++_M_b; } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return ++_M_b; + } __pointer_type operator++() volatile noexcept - { return ++_M_b; } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return ++_M_b; + } __pointer_type operator--() noexcept - { return --_M_b; } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return --_M_b; + } __pointer_type operator--() volatile noexcept - { return --_M_b; } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return --_M_b; + } __pointer_type operator+=(ptrdiff_t __d) noexcept - { return _M_b.operator+=(__d); } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator+=(__d); + } __pointer_type operator+=(ptrdiff_t __d) volatile noexcept - { return _M_b.operator+=(__d); } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator+=(__d); + } __pointer_type operator-=(ptrdiff_t __d) noexcept - { return _M_b.operator-=(__d); } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator-=(__d); + } __pointer_type operator-=(ptrdiff_t __d) volatile noexcept - { return _M_b.operator-=(__d); } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator-=(__d); + } bool is_lock_free() const noexcept @@ -433,7 +500,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION is_lock_free() const volatile noexcept { return _M_b.is_lock_free(); } -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; #endif @@ -522,22 +589,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __pointer_type fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) noexcept - { return _M_b.fetch_add(__d, __m); } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_add(__d, __m); + } __pointer_type fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile noexcept - { return _M_b.fetch_add(__d, __m); } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_add(__d, __m); + } __pointer_type fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) noexcept - { return _M_b.fetch_sub(__d, __m); } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_sub(__d, __m); + } __pointer_type fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile noexcept - { return _M_b.fetch_sub(__d, __m); } + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_sub(__d, __m); + } }; @@ -559,7 +646,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; #endif }; @@ -582,7 +669,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; #endif }; @@ -605,7 +692,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; #endif }; @@ -628,7 +715,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; #endif }; @@ -651,7 +738,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; #endif }; @@ -674,7 +761,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; #endif }; @@ -697,7 +784,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; #endif }; @@ -720,7 +807,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; #endif }; @@ -743,7 +830,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; #endif }; @@ -766,7 +853,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; #endif }; @@ -789,7 +876,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; #endif }; @@ -812,7 +899,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_WCHAR_T_LOCK_FREE == 2; #endif }; @@ -835,7 +922,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_CHAR16_T_LOCK_FREE == 2; #endif }; @@ -858,7 +945,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __base_type::operator __integral_type; using __base_type::operator=; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L static constexpr bool is_always_lock_free = ATOMIC_CHAR32_T_LOCK_FREE == 2; #endif }; @@ -1046,6 +1133,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } + template + using __atomic_val_t = typename atomic<_Tp>::value_type; + template + using __atomic_diff_t = typename atomic<_Tp>::difference_type; + + // [atomics.nonmembers] Non-member functions. // Function templates generally applicable to atomic types. template inline bool @@ -1059,23 +1152,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline void - atomic_init(atomic<_ITp>* __a, _ITp __i) noexcept + atomic_init(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept { __a->store(__i, memory_order_relaxed); } template inline void - atomic_init(volatile atomic<_ITp>* __a, _ITp __i) noexcept + atomic_init(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept { __a->store(__i, memory_order_relaxed); } template inline void - atomic_store_explicit(atomic<_ITp>* __a, _ITp __i, + atomic_store_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, memory_order __m) noexcept { __a->store(__i, __m); } template inline void - atomic_store_explicit(volatile atomic<_ITp>* __a, _ITp __i, + atomic_store_explicit(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, memory_order __m) noexcept { __a->store(__i, __m); } @@ -1092,20 +1185,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline _ITp - atomic_exchange_explicit(atomic<_ITp>* __a, _ITp __i, + atomic_exchange_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, memory_order __m) noexcept { return __a->exchange(__i, __m); } template inline _ITp - atomic_exchange_explicit(volatile atomic<_ITp>* __a, _ITp __i, + atomic_exchange_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp> __i, memory_order __m) noexcept { return __a->exchange(__i, __m); } template inline bool atomic_compare_exchange_weak_explicit(atomic<_ITp>* __a, - _ITp* __i1, _ITp __i2, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, memory_order __m1, memory_order __m2) noexcept { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } @@ -1113,7 +1208,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline bool atomic_compare_exchange_weak_explicit(volatile atomic<_ITp>* __a, - _ITp* __i1, _ITp __i2, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, memory_order __m1, memory_order __m2) noexcept { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } @@ -1121,7 +1217,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline bool atomic_compare_exchange_strong_explicit(atomic<_ITp>* __a, - _ITp* __i1, _ITp __i2, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, memory_order __m1, memory_order __m2) noexcept { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } @@ -1129,7 +1226,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline bool atomic_compare_exchange_strong_explicit(volatile atomic<_ITp>* __a, - _ITp* __i1, _ITp __i2, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, memory_order __m1, memory_order __m2) noexcept { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } @@ -1137,12 +1235,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline void - atomic_store(atomic<_ITp>* __a, _ITp __i) noexcept + atomic_store(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept { atomic_store_explicit(__a, __i, memory_order_seq_cst); } template inline void - atomic_store(volatile atomic<_ITp>* __a, _ITp __i) noexcept + atomic_store(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept { atomic_store_explicit(__a, __i, memory_order_seq_cst); } template @@ -1157,18 +1255,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline _ITp - atomic_exchange(atomic<_ITp>* __a, _ITp __i) noexcept + atomic_exchange(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_exchange(volatile atomic<_ITp>* __a, _ITp __i) noexcept + atomic_exchange(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } template inline bool atomic_compare_exchange_weak(atomic<_ITp>* __a, - _ITp* __i1, _ITp __i2) noexcept + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept { return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, memory_order_seq_cst, @@ -1178,7 +1278,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline bool atomic_compare_exchange_weak(volatile atomic<_ITp>* __a, - _ITp* __i1, _ITp __i2) noexcept + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept { return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, memory_order_seq_cst, @@ -1188,7 +1289,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline bool atomic_compare_exchange_strong(atomic<_ITp>* __a, - _ITp* __i1, _ITp __i2) noexcept + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept { return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, memory_order_seq_cst, @@ -1198,172 +1300,148 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline bool atomic_compare_exchange_strong(volatile atomic<_ITp>* __a, - _ITp* __i1, _ITp __i2) noexcept + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept { return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, memory_order_seq_cst, memory_order_seq_cst); } - // Function templates for atomic_integral operations only, using - // __atomic_base. Template argument should be constricted to - // intergral types as specified in the standard, excluding address - // types. + // Function templates for atomic_integral and atomic_pointer operations only. + // Some operations (and, or, xor) are only available for atomic integrals, + // which is implemented by taking a parameter of type __atomic_base<_ITp>*. + template inline _ITp - atomic_fetch_add_explicit(__atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_add_explicit(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_add(__i, __m); } template inline _ITp - atomic_fetch_add_explicit(volatile __atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_add_explicit(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_add(__i, __m); } template inline _ITp - atomic_fetch_sub_explicit(__atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_sub_explicit(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_sub(__i, __m); } template inline _ITp - atomic_fetch_sub_explicit(volatile __atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_sub_explicit(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_sub(__i, __m); } template inline _ITp - atomic_fetch_and_explicit(__atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_and_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_and(__i, __m); } template inline _ITp - atomic_fetch_and_explicit(volatile __atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_and_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_and(__i, __m); } template inline _ITp - atomic_fetch_or_explicit(__atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_or_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_or(__i, __m); } template inline _ITp - atomic_fetch_or_explicit(volatile __atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_or_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_or(__i, __m); } template inline _ITp - atomic_fetch_xor_explicit(__atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_xor_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_xor(__i, __m); } template inline _ITp - atomic_fetch_xor_explicit(volatile __atomic_base<_ITp>* __a, _ITp __i, + atomic_fetch_xor_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, memory_order __m) noexcept { return __a->fetch_xor(__i, __m); } template inline _ITp - atomic_fetch_add(__atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_add(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_fetch_add(volatile __atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_add(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_fetch_sub(__atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_sub(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_fetch_sub(volatile __atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_sub(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_fetch_and(__atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_and(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_fetch_and(volatile __atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_and(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_fetch_or(__atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_or(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_fetch_or(volatile __atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_or(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_fetch_xor(__atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_xor(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } template inline _ITp - atomic_fetch_xor(volatile __atomic_base<_ITp>* __a, _ITp __i) noexcept + atomic_fetch_xor(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } - - // Partial specializations for pointers. - template - inline _ITp* - atomic_fetch_add_explicit(atomic<_ITp*>* __a, ptrdiff_t __d, - memory_order __m) noexcept - { return __a->fetch_add(__d, __m); } - - template - inline _ITp* - atomic_fetch_add_explicit(volatile atomic<_ITp*>* __a, ptrdiff_t __d, - memory_order __m) noexcept - { return __a->fetch_add(__d, __m); } - - template - inline _ITp* - atomic_fetch_add(volatile atomic<_ITp*>* __a, ptrdiff_t __d) noexcept - { return __a->fetch_add(__d); } - - template - inline _ITp* - atomic_fetch_add(atomic<_ITp*>* __a, ptrdiff_t __d) noexcept - { return __a->fetch_add(__d); } - - template - inline _ITp* - atomic_fetch_sub_explicit(volatile atomic<_ITp*>* __a, - ptrdiff_t __d, memory_order __m) noexcept - { return __a->fetch_sub(__d, __m); } - - template - inline _ITp* - atomic_fetch_sub_explicit(atomic<_ITp*>* __a, ptrdiff_t __d, - memory_order __m) noexcept - { return __a->fetch_sub(__d, __m); } - - template - inline _ITp* - atomic_fetch_sub(volatile atomic<_ITp*>* __a, ptrdiff_t __d) noexcept - { return __a->fetch_sub(__d); } - - template - inline _ITp* - atomic_fetch_sub(atomic<_ITp*>* __a, ptrdiff_t __d) noexcept - { return __a->fetch_sub(__d); } // @} group atomics _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/60695.cc b/libstdc++-v3/testsuite/29_atomics/atomic/60695.cc index 8411895eda5..cf2dfb2d28c 100644 --- a/libstdc++-v3/testsuite/29_atomics/atomic/60695.cc +++ b/libstdc++-v3/testsuite/29_atomics/atomic/60695.cc @@ -27,4 +27,4 @@ struct X { char stuff[0]; // GNU extension, type has zero size }; -std::atomic a; // { dg-error "not supported" "" { target *-*-* } 190 } +std::atomic a; // { dg-error "not supported" "" { target *-*-* } 194 } diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/69769.cc b/libstdc++-v3/testsuite/29_atomics/atomic/69769.cc new file mode 100644 index 00000000000..38fc49d0f25 --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic/69769.cc @@ -0,0 +1,80 @@ +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do compile { target c++17 } } +// { dg-require-atomic-builtins "" } + +#include + +void +test01() +{ + std::atomic p; + p.fetch_add(1); // { dg-error "from here" } + p.fetch_sub(1); // { dg-error "from here" } + p += 1; // { dg-error "from here" } + p -= 1; // { dg-error "from here" } + ++p; // { dg-error "from here" } + p++; // { dg-error "from here" } + --p; // { dg-error "from here" } + p--; // { dg-error "from here" } +} + +void +test02() +{ + std::atomic p; + p.fetch_add(1); // { dg-error "from here" } + p.fetch_sub(1); // { dg-error "from here" } + p += 1; // { dg-error "from here" } + p -= 1; // { dg-error "from here" } + ++p; // { dg-error "from here" } + p++; // { dg-error "from here" } + --p; // { dg-error "from here" } + p--; // { dg-error "from here" } +} + +void +test03() +{ + volatile std::atomic p; + p.fetch_add(1); // { dg-error "from here" } + p.fetch_sub(1); // { dg-error "from here" } + p += 1; // { dg-error "from here" } + p -= 1; // { dg-error "from here" } + ++p; // { dg-error "from here" } + p++; // { dg-error "from here" } + --p; // { dg-error "from here" } + p--; // { dg-error "from here" } +} + +void +test04() +{ + volatile std::atomic p; + p.fetch_add(1); // { dg-error "from here" } + p.fetch_sub(1); // { dg-error "from here" } + p += 1; // { dg-error "from here" } + p -= 1; // { dg-error "from here" } + ++p; // { dg-error "from here" } + p++; // { dg-error "from here" } + --p; // { dg-error "from here" } + p--; // { dg-error "from here" } +} + +// { dg-prune-output "static assertion failed" } diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/nonmembers.cc b/libstdc++-v3/testsuite/29_atomics/atomic/nonmembers.cc new file mode 100644 index 00000000000..886ad7be863 --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic/nonmembers.cc @@ -0,0 +1,230 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do compile { target c++11 } } +// { dg-require-atomic-builtins "" } + +#include + +void +test01() +{ + struct X { }; + struct Y { }; + // Primary template + volatile std::atomic v; + std::atomic a; + const std::memory_order mo = std::memory_order_seq_cst; + X x; + Y y; + auto r1 = atomic_is_lock_free(&v); + static_assert( std::is_same::value, "" ); + auto r2 = atomic_is_lock_free(&a); + static_assert( std::is_same::value, "" ); + atomic_init(&v, x); + atomic_init(&a, y); + atomic_store(&v, x); + atomic_store(&a, y); + atomic_store_explicit(&v, x, mo); + atomic_store_explicit(&a, y, mo); + auto r3 = atomic_load(&v); + static_assert( std::is_same::value, "" ); + auto r4 = atomic_load(&a); + static_assert( std::is_same::value, "" ); + auto r5 = atomic_load_explicit(&v, mo); + static_assert( std::is_same::value, "" ); + auto r6 = atomic_load_explicit(&a, mo); + static_assert( std::is_same::value, "" ); + auto r7 = atomic_exchange(&v, x); + static_assert( std::is_same::value, "" ); + auto r8 = atomic_exchange(&a, y); + static_assert( std::is_same::value, "" ); + auto r9 = atomic_exchange_explicit(&v, x, mo); + static_assert( std::is_same::value, "" ); + auto r10 = atomic_exchange_explicit(&a, y, mo); + static_assert( std::is_same::value, "" ); + auto r11 = atomic_compare_exchange_weak(&v, &x, x); + static_assert( std::is_same::value, "" ); + auto r12 = atomic_compare_exchange_weak(&a, &y, y); + static_assert( std::is_same::value, "" ); + auto r13 = atomic_compare_exchange_strong(&v, &x, x); + static_assert( std::is_same::value, "" ); + auto r14 = atomic_compare_exchange_strong(&a, &y, y); + static_assert( std::is_same::value, "" ); + auto r15 = atomic_compare_exchange_weak_explicit(&v, &x, x, mo, mo); + static_assert( std::is_same::value, "" ); + auto r16 = atomic_compare_exchange_weak_explicit(&a, &y, y, mo, mo); + static_assert( std::is_same::value, "" ); + auto r17 = atomic_compare_exchange_strong_explicit(&v, &x, x, mo, mo); + static_assert( std::is_same::value, "" ); + auto r18 = atomic_compare_exchange_strong_explicit(&a, &y, y, mo, mo); + static_assert( std::is_same::value, "" ); +} + +void +test02() +{ + // Specialization for bool + volatile std::atomic v; + std::atomic a; + const std::memory_order mo = std::memory_order_seq_cst; + bool b = false; + auto r1 = atomic_is_lock_free(&v); + static_assert( std::is_same::value, "" ); + auto r2 = atomic_is_lock_free(&a); + static_assert( std::is_same::value, "" ); + atomic_init(&v, b); + atomic_init(&a, b); + atomic_store(&v, b); + atomic_store(&a, b); + atomic_store_explicit(&v, b, mo); + atomic_store_explicit(&a, b, mo); + auto r3 = atomic_load(&v); + static_assert( std::is_same::value, "" ); + auto r4 = atomic_load(&a); + static_assert( std::is_same::value, "" ); + auto r5 = atomic_load_explicit(&v, mo); + static_assert( std::is_same::value, "" ); + auto r6 = atomic_load_explicit(&a, mo); + static_assert( std::is_same::value, "" ); + auto r7 = atomic_exchange(&v, b); + static_assert( std::is_same::value, "" ); + auto r8 = atomic_exchange(&a, b); + static_assert( std::is_same::value, "" ); + auto r9 = atomic_exchange_explicit(&v, b, mo); + static_assert( std::is_same::value, "" ); + auto r10 = atomic_exchange_explicit(&a, b, mo); + static_assert( std::is_same::value, "" ); + auto r11 = atomic_compare_exchange_weak(&v, &b, b); + static_assert( std::is_same::value, "" ); + auto r12 = atomic_compare_exchange_weak(&a, &b, b); + static_assert( std::is_same::value, "" ); + auto r13 = atomic_compare_exchange_strong(&v, &b, b); + static_assert( std::is_same::value, "" ); + auto r14 = atomic_compare_exchange_strong(&a, &b, b); + static_assert( std::is_same::value, "" ); + auto r15 = atomic_compare_exchange_weak_explicit(&v, &b, b, mo, mo); + static_assert( std::is_same::value, "" ); + auto r16 = atomic_compare_exchange_weak_explicit(&a, &b, b, mo, mo); + static_assert( std::is_same::value, "" ); + auto r17 = atomic_compare_exchange_strong_explicit(&v, &b, b, mo, mo); + static_assert( std::is_same::value, "" ); + auto r18 = atomic_compare_exchange_strong_explicit(&a, &b, b, mo, mo); + static_assert( std::is_same::value, "" ); +} + +void +test03() +{ + // Partial specialization for pointers + volatile std::atomic v; + std::atomic a; + const std::memory_order mo = std::memory_order_seq_cst; + int* i = nullptr; + long* l = nullptr; + auto r1 = atomic_is_lock_free(&v); + static_assert( std::is_same::value, "" ); + auto r2 = atomic_is_lock_free(&a); + static_assert( std::is_same::value, "" ); + atomic_init(&v, i); + atomic_init(&a, l); + atomic_store(&v, i); + atomic_store(&a, l); + atomic_store_explicit(&v, i, mo); + atomic_store_explicit(&a, l, mo); + auto r3 = atomic_load(&v); + static_assert( std::is_same::value, "" ); + auto r4 = atomic_load(&a); + static_assert( std::is_same::value, "" ); + auto r5 = atomic_load_explicit(&v, mo); + static_assert( std::is_same::value, "" ); + auto r6 = atomic_load_explicit(&a, mo); + static_assert( std::is_same::value, "" ); + auto r7 = atomic_exchange(&v, i); + static_assert( std::is_same::value, "" ); + auto r8 = atomic_exchange(&a, l); + static_assert( std::is_same::value, "" ); + auto r9 = atomic_exchange_explicit(&v, i, mo); + static_assert( std::is_same::value, "" ); + auto r10 = atomic_exchange_explicit(&a, l, mo); + static_assert( std::is_same::value, "" ); + auto r11 = atomic_compare_exchange_weak(&v, &i, i); + static_assert( std::is_same::value, "" ); + auto r12 = atomic_compare_exchange_weak(&a, &l, l); + static_assert( std::is_same::value, "" ); + auto r13 = atomic_compare_exchange_strong(&v, &i, i); + static_assert( std::is_same::value, "" ); + auto r14 = atomic_compare_exchange_strong(&a, &l, l); + static_assert( std::is_same::value, "" ); + auto r15 = atomic_compare_exchange_weak_explicit(&v, &i, i, mo, mo); + static_assert( std::is_same::value, "" ); + auto r16 = atomic_compare_exchange_weak_explicit(&a, &l, l, mo, mo); + static_assert( std::is_same::value, "" ); + auto r17 = atomic_compare_exchange_strong_explicit(&v, &i, i, mo, mo); + static_assert( std::is_same::value, "" ); + auto r18 = atomic_compare_exchange_strong_explicit(&a, &l, l, mo, mo); + static_assert( std::is_same::value, "" ); + + auto r19 = atomic_fetch_add(&v, 1); + static_assert( std::is_same::value, "" ); + auto r20 = atomic_fetch_add(&a, 1); + static_assert( std::is_same::value, "" ); + auto r21 = atomic_fetch_add_explicit(&v, 1, mo); + static_assert( std::is_same::value, "" ); + auto r22 = atomic_fetch_add_explicit(&a, 1, mo); + static_assert( std::is_same::value, "" ); + auto r23 = atomic_fetch_sub(&v, 1); + static_assert( std::is_same::value, "" ); + auto r24 = atomic_fetch_sub(&a, 1); + static_assert( std::is_same::value, "" ); + auto r25 = atomic_fetch_sub_explicit(&v, 1, mo); + static_assert( std::is_same::value, "" ); + auto r26 = atomic_fetch_sub_explicit(&a, 1, mo); + static_assert( std::is_same::value, "" ); +} + +void +test04() +{ + struct base { }; + struct derived : base { }; + // Partial specialization for pointers + volatile std::atomic v; + std::atomic a; + const std::memory_order mo = std::memory_order_seq_cst; + // Repeat tests with arguments of type different to value_type. + derived* const p = nullptr; + base* b = nullptr; + atomic_init(&v, p); + atomic_init(&a, p); + atomic_store(&v, p); + atomic_store(&a, p); + atomic_store_explicit(&v, p, mo); + atomic_store_explicit(&a, p, mo); + atomic_exchange(&v, p); + atomic_exchange(&a, p); + atomic_exchange_explicit(&v, p, mo); + atomic_exchange_explicit(&a, p, mo); + atomic_compare_exchange_weak(&v, &b, p); + atomic_compare_exchange_weak(&a, &b, p); + atomic_compare_exchange_strong(&v, &b, p); + atomic_compare_exchange_strong(&a, &b, p); + atomic_compare_exchange_weak_explicit(&v, &b, p, mo, mo); + atomic_compare_exchange_weak_explicit(&a, &b, p, mo, mo); + atomic_compare_exchange_strong_explicit(&v, &b, p, mo, mo); + atomic_compare_exchange_strong_explicit(&a, &b, p, mo, mo); +} diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc b/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc index e1865b7fb5b..f4668b3e259 100644 --- a/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc +++ b/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc @@ -1,4 +1,4 @@ -// { dg-do run { target c++11 } } +// { dg-do run { target { c++11_only || c++14_only } } } // { dg-require-atomic-builtins "" } // Copyright (C) 2012-2018 Free Software Foundation, Inc. diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/requirements/typedefs.cc b/libstdc++-v3/testsuite/29_atomics/atomic/requirements/typedefs.cc new file mode 100644 index 00000000000..96d263e8fbf --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic/requirements/typedefs.cc @@ -0,0 +1,36 @@ +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do compile { target c++17 } } +// { dg-require-atomic-builtins "" } + +#include + +template +constexpr bool check() +{ + typename std::atomic::value_type* pv = (T*)nullptr; + typename std::atomic::difference_type* pd = (std::ptrdiff_t*)nullptr; + return true; +} + +static_assert( check(), "" ); +static_assert( check(), "" ); +static_assert( check(), "" ); +struct X { }; +static_assert( check(), "" ); diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_integral/nonmembers.cc b/libstdc++-v3/testsuite/29_atomics/atomic_integral/nonmembers.cc new file mode 100644 index 00000000000..96a234d620a --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic_integral/nonmembers.cc @@ -0,0 +1,163 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do compile { target c++11 } } +// { dg-require-atomic-builtins "" } + +#include + +void +test01() +{ + volatile std::atomic v; + std::atomic a; + const std::memory_order mo = std::memory_order_seq_cst; + int i = 0; + long l = 0; + auto r1 = atomic_is_lock_free(&v); + static_assert( std::is_same::value, "" ); + auto r2 = atomic_is_lock_free(&a); + static_assert( std::is_same::value, "" ); + atomic_init(&v, i); + atomic_init(&a, l); + atomic_store(&v, i); + atomic_store(&a, l); + atomic_store_explicit(&v, i, mo); + atomic_store_explicit(&a, l, mo); + auto r3 = atomic_load(&v); + static_assert( std::is_same::value, "" ); + auto r4 = atomic_load(&a); + static_assert( std::is_same::value, "" ); + auto r5 = atomic_load_explicit(&v, mo); + static_assert( std::is_same::value, "" ); + auto r6 = atomic_load_explicit(&a, mo); + static_assert( std::is_same::value, "" ); + auto r7 = atomic_exchange(&v, i); + static_assert( std::is_same::value, "" ); + auto r8 = atomic_exchange(&a, l); + static_assert( std::is_same::value, "" ); + auto r9 = atomic_exchange_explicit(&v, i, mo); + static_assert( std::is_same::value, "" ); + auto r10 = atomic_exchange_explicit(&a, l, mo); + static_assert( std::is_same::value, "" ); + auto r11 = atomic_compare_exchange_weak(&v, &i, i); + static_assert( std::is_same::value, "" ); + auto r12 = atomic_compare_exchange_weak(&a, &l, l); + static_assert( std::is_same::value, "" ); + auto r13 = atomic_compare_exchange_strong(&v, &i, i); + static_assert( std::is_same::value, "" ); + auto r14 = atomic_compare_exchange_strong(&a, &l, l); + static_assert( std::is_same::value, "" ); + auto r15 = atomic_compare_exchange_weak_explicit(&v, &i, i, mo, mo); + static_assert( std::is_same::value, "" ); + auto r16 = atomic_compare_exchange_weak_explicit(&a, &l, l, mo, mo); + static_assert( std::is_same::value, "" ); + auto r17 = atomic_compare_exchange_strong_explicit(&v, &i, i, mo, mo); + static_assert( std::is_same::value, "" ); + auto r18 = atomic_compare_exchange_strong_explicit(&a, &l, l, mo, mo); + static_assert( std::is_same::value, "" ); + + auto r19 = atomic_fetch_add(&v, i); + static_assert( std::is_same::value, "" ); + auto r20 = atomic_fetch_add(&a, l); + static_assert( std::is_same::value, "" ); + auto r21 = atomic_fetch_add_explicit(&v, i, mo); + static_assert( std::is_same::value, "" ); + auto r22 = atomic_fetch_add_explicit(&a, l, mo); + static_assert( std::is_same::value, "" ); + auto r23 = atomic_fetch_sub(&v, i); + static_assert( std::is_same::value, "" ); + auto r24 = atomic_fetch_sub(&a, l); + static_assert( std::is_same::value, "" ); + auto r25 = atomic_fetch_sub_explicit(&v, i, mo); + static_assert( std::is_same::value, "" ); + auto r26 = atomic_fetch_sub_explicit(&a, l, mo); + static_assert( std::is_same::value, "" ); + auto r27 = atomic_fetch_and(&v, i); + static_assert( std::is_same::value, "" ); + auto r28 = atomic_fetch_and(&a, l); + static_assert( std::is_same::value, "" ); + auto r29 = atomic_fetch_and_explicit(&v, i, mo); + static_assert( std::is_same::value, "" ); + auto r30 = atomic_fetch_and_explicit(&a, l, mo); + static_assert( std::is_same::value, "" ); + auto r31 = atomic_fetch_or(&v, i); + static_assert( std::is_same::value, "" ); + auto r32 = atomic_fetch_or(&a, l); + static_assert( std::is_same::value, "" ); + auto r33 = atomic_fetch_or_explicit(&v, i, mo); + static_assert( std::is_same::value, "" ); + auto r34 = atomic_fetch_or_explicit(&a, l, mo); + static_assert( std::is_same::value, "" ); + auto r35 = atomic_fetch_xor(&v, i); + static_assert( std::is_same::value, "" ); + auto r36 = atomic_fetch_xor(&a, l); + static_assert( std::is_same::value, "" ); + auto r37 = atomic_fetch_xor_explicit(&v, i, mo); + static_assert( std::is_same::value, "" ); + auto r38 = atomic_fetch_xor_explicit(&a, l, mo); + static_assert( std::is_same::value, "" ); +} + +void +test02() +{ + volatile std::atomic v; + std::atomic a; + std::memory_order mo = std::memory_order_seq_cst; + // Repeat tests with arguments of type different to value_type. + const int i = 0; + long l = 0; + atomic_init(&v, i); + atomic_init(&a, i); + atomic_store(&v, i); + atomic_store(&a, i); + atomic_store_explicit(&v, i, mo); + atomic_store_explicit(&a, i, mo); + atomic_exchange(&v, i); + atomic_exchange(&a, i); + atomic_exchange_explicit(&v, i, mo); + atomic_exchange_explicit(&a, i, mo); + atomic_compare_exchange_weak(&v, &l, i); + atomic_compare_exchange_weak(&a, &l, i); + atomic_compare_exchange_strong(&v, &l, i); + atomic_compare_exchange_strong(&a, &l, i); + atomic_compare_exchange_weak_explicit(&v, &l, i, mo, mo); + atomic_compare_exchange_weak_explicit(&a, &l, i, mo, mo); + atomic_compare_exchange_strong_explicit(&v, &l, i, mo, mo); + atomic_compare_exchange_strong_explicit(&a, &l, i, mo, mo); + atomic_fetch_add(&v, i); + atomic_fetch_add(&a, i); + atomic_fetch_add_explicit(&v, i, mo); + atomic_fetch_add_explicit(&a, i, mo); + atomic_fetch_sub(&v, i); + atomic_fetch_sub(&a, i); + atomic_fetch_sub_explicit(&v, i, mo); + atomic_fetch_sub_explicit(&a, i, mo); + atomic_fetch_and(&v, i); + atomic_fetch_and(&a, i); + atomic_fetch_and_explicit(&v, i, mo); + atomic_fetch_and_explicit(&a, i, mo); + atomic_fetch_or(&v, i); + atomic_fetch_or(&a, i); + atomic_fetch_or_explicit(&v, i, mo); + atomic_fetch_or_explicit(&a, i, mo); + atomic_fetch_xor(&v, i); + atomic_fetch_xor(&a, i); + atomic_fetch_xor_explicit(&v, i, mo); + atomic_fetch_xor_explicit(&a, i, mo); +} diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_integral/requirements/typedefs.cc b/libstdc++-v3/testsuite/29_atomics/atomic_integral/requirements/typedefs.cc new file mode 100644 index 00000000000..2cd20844701 --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic_integral/requirements/typedefs.cc @@ -0,0 +1,39 @@ +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } +// { dg-do compile { target c++17 } } +// { dg-require-atomic-builtins "" } + +#include + +template +constexpr bool check() +{ + typename std::atomic::value_type* pv = (T*)nullptr; + typename std::atomic::difference_type* pd = (T*)nullptr; + return true; +} + +static_assert( check(), "" ); +static_assert( check(), "" ); +static_assert( check(), "" ); +static_assert( check(), "" ); +static_assert( check(), "" ); +static_assert( check(), "" ); +static_assert( check(), "" ); +static_assert( check(), "" ); -- 2.30.2