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<bool>::value_type, atomic<T>::value_type) (atomic<T*>::value_type, atomic<T*>::difference_type): Likewise. (atomic<T*>::operator++, atomic<T*>::operator--) (atomic<T*>::operator+=, atomic<T*>::operator-=) (atomic<T*>::fetch_add, atomic<T*>::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
This commit is contained in:
parent
8d39ea2f9d
commit
25999a112f
10 changed files with 791 additions and 123 deletions
|
@ -1,3 +1,42 @@
|
|||
2018-05-24 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
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<bool>::value_type, atomic<T>::value_type)
|
||||
(atomic<T*>::value_type, atomic<T*>::difference_type): Likewise.
|
||||
(atomic<T*>::operator++, atomic<T*>::operator--)
|
||||
(atomic<T*>::operator+=, atomic<T*>::operator-=)
|
||||
(atomic<T*>::fetch_add, atomic<T*>::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 <jwakely@redhat.com>
|
||||
|
||||
* include/bits/fs_path.h (path::__is_encoded_char): Change from class
|
||||
|
|
|
@ -237,6 +237,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _ITp>
|
||||
struct __atomic_base
|
||||
{
|
||||
using value_type = _ITp;
|
||||
using difference_type = value_type;
|
||||
|
||||
private:
|
||||
typedef _ITp __int_type;
|
||||
|
||||
|
|
|
@ -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<bool>
|
||||
{
|
||||
using value_type = bool;
|
||||
|
||||
private:
|
||||
__atomic_base<bool> _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<typename _Tp>
|
||||
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<void *>(-__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<typename _Tp>
|
||||
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<typename _Tp>
|
||||
using __atomic_val_t = typename atomic<_Tp>::value_type;
|
||||
template<typename _Tp>
|
||||
using __atomic_diff_t = typename atomic<_Tp>::difference_type;
|
||||
|
||||
// [atomics.nonmembers] Non-member functions.
|
||||
// Function templates generally applicable to atomic types.
|
||||
template<typename _ITp>
|
||||
inline bool
|
||||
|
@ -1059,23 +1152,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
|
@ -1157,18 +1255,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
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<typename _ITp>
|
||||
inline _ITp*
|
||||
atomic_fetch_add_explicit(atomic<_ITp*>* __a, ptrdiff_t __d,
|
||||
memory_order __m) noexcept
|
||||
{ return __a->fetch_add(__d, __m); }
|
||||
|
||||
template<typename _ITp>
|
||||
inline _ITp*
|
||||
atomic_fetch_add_explicit(volatile atomic<_ITp*>* __a, ptrdiff_t __d,
|
||||
memory_order __m) noexcept
|
||||
{ return __a->fetch_add(__d, __m); }
|
||||
|
||||
template<typename _ITp>
|
||||
inline _ITp*
|
||||
atomic_fetch_add(volatile atomic<_ITp*>* __a, ptrdiff_t __d) noexcept
|
||||
{ return __a->fetch_add(__d); }
|
||||
|
||||
template<typename _ITp>
|
||||
inline _ITp*
|
||||
atomic_fetch_add(atomic<_ITp*>* __a, ptrdiff_t __d) noexcept
|
||||
{ return __a->fetch_add(__d); }
|
||||
|
||||
template<typename _ITp>
|
||||
inline _ITp*
|
||||
atomic_fetch_sub_explicit(volatile atomic<_ITp*>* __a,
|
||||
ptrdiff_t __d, memory_order __m) noexcept
|
||||
{ return __a->fetch_sub(__d, __m); }
|
||||
|
||||
template<typename _ITp>
|
||||
inline _ITp*
|
||||
atomic_fetch_sub_explicit(atomic<_ITp*>* __a, ptrdiff_t __d,
|
||||
memory_order __m) noexcept
|
||||
{ return __a->fetch_sub(__d, __m); }
|
||||
|
||||
template<typename _ITp>
|
||||
inline _ITp*
|
||||
atomic_fetch_sub(volatile atomic<_ITp*>* __a, ptrdiff_t __d) noexcept
|
||||
{ return __a->fetch_sub(__d); }
|
||||
|
||||
template<typename _ITp>
|
||||
inline _ITp*
|
||||
atomic_fetch_sub(atomic<_ITp*>* __a, ptrdiff_t __d) noexcept
|
||||
{ return __a->fetch_sub(__d); }
|
||||
// @} group atomics
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
|
|
|
@ -27,4 +27,4 @@ struct X {
|
|||
char stuff[0]; // GNU extension, type has zero size
|
||||
};
|
||||
|
||||
std::atomic<X> a; // { dg-error "not supported" "" { target *-*-* } 190 }
|
||||
std::atomic<X> a; // { dg-error "not supported" "" { target *-*-* } 194 }
|
||||
|
|
80
libstdc++-v3/testsuite/29_atomics/atomic/69769.cc
Normal file
80
libstdc++-v3/testsuite/29_atomics/atomic/69769.cc
Normal file
|
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do compile { target c++17 } }
|
||||
// { dg-require-atomic-builtins "" }
|
||||
|
||||
#include <atomic>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
std::atomic<void*> 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<void(*)()> 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<void*> 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<void(*)()> 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" }
|
230
libstdc++-v3/testsuite/29_atomics/atomic/nonmembers.cc
Normal file
230
libstdc++-v3/testsuite/29_atomics/atomic/nonmembers.cc
Normal file
|
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-require-atomic-builtins "" }
|
||||
|
||||
#include <atomic>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
struct X { };
|
||||
struct Y { };
|
||||
// Primary template
|
||||
volatile std::atomic<X> v;
|
||||
std::atomic<Y> 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<decltype(r1), bool>::value, "" );
|
||||
auto r2 = atomic_is_lock_free(&a);
|
||||
static_assert( std::is_same<decltype(r2), bool>::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<decltype(r3), X>::value, "" );
|
||||
auto r4 = atomic_load(&a);
|
||||
static_assert( std::is_same<decltype(r4), Y>::value, "" );
|
||||
auto r5 = atomic_load_explicit(&v, mo);
|
||||
static_assert( std::is_same<decltype(r5), X>::value, "" );
|
||||
auto r6 = atomic_load_explicit(&a, mo);
|
||||
static_assert( std::is_same<decltype(r6), Y>::value, "" );
|
||||
auto r7 = atomic_exchange(&v, x);
|
||||
static_assert( std::is_same<decltype(r7), X>::value, "" );
|
||||
auto r8 = atomic_exchange(&a, y);
|
||||
static_assert( std::is_same<decltype(r8), Y>::value, "" );
|
||||
auto r9 = atomic_exchange_explicit(&v, x, mo);
|
||||
static_assert( std::is_same<decltype(r9), X>::value, "" );
|
||||
auto r10 = atomic_exchange_explicit(&a, y, mo);
|
||||
static_assert( std::is_same<decltype(r10), Y>::value, "" );
|
||||
auto r11 = atomic_compare_exchange_weak(&v, &x, x);
|
||||
static_assert( std::is_same<decltype(r11), bool>::value, "" );
|
||||
auto r12 = atomic_compare_exchange_weak(&a, &y, y);
|
||||
static_assert( std::is_same<decltype(r12), bool>::value, "" );
|
||||
auto r13 = atomic_compare_exchange_strong(&v, &x, x);
|
||||
static_assert( std::is_same<decltype(r13), bool>::value, "" );
|
||||
auto r14 = atomic_compare_exchange_strong(&a, &y, y);
|
||||
static_assert( std::is_same<decltype(r14), bool>::value, "" );
|
||||
auto r15 = atomic_compare_exchange_weak_explicit(&v, &x, x, mo, mo);
|
||||
static_assert( std::is_same<decltype(r15), bool>::value, "" );
|
||||
auto r16 = atomic_compare_exchange_weak_explicit(&a, &y, y, mo, mo);
|
||||
static_assert( std::is_same<decltype(r16), bool>::value, "" );
|
||||
auto r17 = atomic_compare_exchange_strong_explicit(&v, &x, x, mo, mo);
|
||||
static_assert( std::is_same<decltype(r17), bool>::value, "" );
|
||||
auto r18 = atomic_compare_exchange_strong_explicit(&a, &y, y, mo, mo);
|
||||
static_assert( std::is_same<decltype(r18), bool>::value, "" );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
// Specialization for bool
|
||||
volatile std::atomic<bool> v;
|
||||
std::atomic<bool> 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<decltype(r1), bool>::value, "" );
|
||||
auto r2 = atomic_is_lock_free(&a);
|
||||
static_assert( std::is_same<decltype(r2), bool>::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<decltype(r3), bool>::value, "" );
|
||||
auto r4 = atomic_load(&a);
|
||||
static_assert( std::is_same<decltype(r4), bool>::value, "" );
|
||||
auto r5 = atomic_load_explicit(&v, mo);
|
||||
static_assert( std::is_same<decltype(r5), bool>::value, "" );
|
||||
auto r6 = atomic_load_explicit(&a, mo);
|
||||
static_assert( std::is_same<decltype(r6), bool>::value, "" );
|
||||
auto r7 = atomic_exchange(&v, b);
|
||||
static_assert( std::is_same<decltype(r7), bool>::value, "" );
|
||||
auto r8 = atomic_exchange(&a, b);
|
||||
static_assert( std::is_same<decltype(r8), bool>::value, "" );
|
||||
auto r9 = atomic_exchange_explicit(&v, b, mo);
|
||||
static_assert( std::is_same<decltype(r9), bool>::value, "" );
|
||||
auto r10 = atomic_exchange_explicit(&a, b, mo);
|
||||
static_assert( std::is_same<decltype(r10), bool>::value, "" );
|
||||
auto r11 = atomic_compare_exchange_weak(&v, &b, b);
|
||||
static_assert( std::is_same<decltype(r11), bool>::value, "" );
|
||||
auto r12 = atomic_compare_exchange_weak(&a, &b, b);
|
||||
static_assert( std::is_same<decltype(r12), bool>::value, "" );
|
||||
auto r13 = atomic_compare_exchange_strong(&v, &b, b);
|
||||
static_assert( std::is_same<decltype(r13), bool>::value, "" );
|
||||
auto r14 = atomic_compare_exchange_strong(&a, &b, b);
|
||||
static_assert( std::is_same<decltype(r14), bool>::value, "" );
|
||||
auto r15 = atomic_compare_exchange_weak_explicit(&v, &b, b, mo, mo);
|
||||
static_assert( std::is_same<decltype(r15), bool>::value, "" );
|
||||
auto r16 = atomic_compare_exchange_weak_explicit(&a, &b, b, mo, mo);
|
||||
static_assert( std::is_same<decltype(r16), bool>::value, "" );
|
||||
auto r17 = atomic_compare_exchange_strong_explicit(&v, &b, b, mo, mo);
|
||||
static_assert( std::is_same<decltype(r17), bool>::value, "" );
|
||||
auto r18 = atomic_compare_exchange_strong_explicit(&a, &b, b, mo, mo);
|
||||
static_assert( std::is_same<decltype(r18), bool>::value, "" );
|
||||
}
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
// Partial specialization for pointers
|
||||
volatile std::atomic<int*> v;
|
||||
std::atomic<long*> 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<decltype(r1), bool>::value, "" );
|
||||
auto r2 = atomic_is_lock_free(&a);
|
||||
static_assert( std::is_same<decltype(r2), bool>::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<decltype(r3), int*>::value, "" );
|
||||
auto r4 = atomic_load(&a);
|
||||
static_assert( std::is_same<decltype(r4), long*>::value, "" );
|
||||
auto r5 = atomic_load_explicit(&v, mo);
|
||||
static_assert( std::is_same<decltype(r5), int*>::value, "" );
|
||||
auto r6 = atomic_load_explicit(&a, mo);
|
||||
static_assert( std::is_same<decltype(r6), long*>::value, "" );
|
||||
auto r7 = atomic_exchange(&v, i);
|
||||
static_assert( std::is_same<decltype(r7), int*>::value, "" );
|
||||
auto r8 = atomic_exchange(&a, l);
|
||||
static_assert( std::is_same<decltype(r8), long*>::value, "" );
|
||||
auto r9 = atomic_exchange_explicit(&v, i, mo);
|
||||
static_assert( std::is_same<decltype(r9), int*>::value, "" );
|
||||
auto r10 = atomic_exchange_explicit(&a, l, mo);
|
||||
static_assert( std::is_same<decltype(r10), long*>::value, "" );
|
||||
auto r11 = atomic_compare_exchange_weak(&v, &i, i);
|
||||
static_assert( std::is_same<decltype(r11), bool>::value, "" );
|
||||
auto r12 = atomic_compare_exchange_weak(&a, &l, l);
|
||||
static_assert( std::is_same<decltype(r12), bool>::value, "" );
|
||||
auto r13 = atomic_compare_exchange_strong(&v, &i, i);
|
||||
static_assert( std::is_same<decltype(r13), bool>::value, "" );
|
||||
auto r14 = atomic_compare_exchange_strong(&a, &l, l);
|
||||
static_assert( std::is_same<decltype(r14), bool>::value, "" );
|
||||
auto r15 = atomic_compare_exchange_weak_explicit(&v, &i, i, mo, mo);
|
||||
static_assert( std::is_same<decltype(r15), bool>::value, "" );
|
||||
auto r16 = atomic_compare_exchange_weak_explicit(&a, &l, l, mo, mo);
|
||||
static_assert( std::is_same<decltype(r16), bool>::value, "" );
|
||||
auto r17 = atomic_compare_exchange_strong_explicit(&v, &i, i, mo, mo);
|
||||
static_assert( std::is_same<decltype(r17), bool>::value, "" );
|
||||
auto r18 = atomic_compare_exchange_strong_explicit(&a, &l, l, mo, mo);
|
||||
static_assert( std::is_same<decltype(r18), bool>::value, "" );
|
||||
|
||||
auto r19 = atomic_fetch_add(&v, 1);
|
||||
static_assert( std::is_same<decltype(r19), int*>::value, "" );
|
||||
auto r20 = atomic_fetch_add(&a, 1);
|
||||
static_assert( std::is_same<decltype(r20), long*>::value, "" );
|
||||
auto r21 = atomic_fetch_add_explicit(&v, 1, mo);
|
||||
static_assert( std::is_same<decltype(r21), int*>::value, "" );
|
||||
auto r22 = atomic_fetch_add_explicit(&a, 1, mo);
|
||||
static_assert( std::is_same<decltype(r22), long*>::value, "" );
|
||||
auto r23 = atomic_fetch_sub(&v, 1);
|
||||
static_assert( std::is_same<decltype(r23), int*>::value, "" );
|
||||
auto r24 = atomic_fetch_sub(&a, 1);
|
||||
static_assert( std::is_same<decltype(r24), long*>::value, "" );
|
||||
auto r25 = atomic_fetch_sub_explicit(&v, 1, mo);
|
||||
static_assert( std::is_same<decltype(r25), int*>::value, "" );
|
||||
auto r26 = atomic_fetch_sub_explicit(&a, 1, mo);
|
||||
static_assert( std::is_same<decltype(r26), long*>::value, "" );
|
||||
}
|
||||
|
||||
void
|
||||
test04()
|
||||
{
|
||||
struct base { };
|
||||
struct derived : base { };
|
||||
// Partial specialization for pointers
|
||||
volatile std::atomic<base*> v;
|
||||
std::atomic<base*> 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);
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do compile { target c++17 } }
|
||||
// { dg-require-atomic-builtins "" }
|
||||
|
||||
#include <atomic>
|
||||
|
||||
template<typename T>
|
||||
constexpr bool check()
|
||||
{
|
||||
typename std::atomic<T>::value_type* pv = (T*)nullptr;
|
||||
typename std::atomic<T>::difference_type* pd = (std::ptrdiff_t*)nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( check<int*>(), "" );
|
||||
static_assert( check<void*>(), "" );
|
||||
static_assert( check<void(*)()>(), "" );
|
||||
struct X { };
|
||||
static_assert( check<X*>(), "" );
|
163
libstdc++-v3/testsuite/29_atomics/atomic_integral/nonmembers.cc
Normal file
163
libstdc++-v3/testsuite/29_atomics/atomic_integral/nonmembers.cc
Normal file
|
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-require-atomic-builtins "" }
|
||||
|
||||
#include <atomic>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
volatile std::atomic<int> v;
|
||||
std::atomic<long> 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<decltype(r1), bool>::value, "" );
|
||||
auto r2 = atomic_is_lock_free(&a);
|
||||
static_assert( std::is_same<decltype(r2), bool>::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<decltype(r3), int>::value, "" );
|
||||
auto r4 = atomic_load(&a);
|
||||
static_assert( std::is_same<decltype(r4), long>::value, "" );
|
||||
auto r5 = atomic_load_explicit(&v, mo);
|
||||
static_assert( std::is_same<decltype(r5), int>::value, "" );
|
||||
auto r6 = atomic_load_explicit(&a, mo);
|
||||
static_assert( std::is_same<decltype(r6), long>::value, "" );
|
||||
auto r7 = atomic_exchange(&v, i);
|
||||
static_assert( std::is_same<decltype(r7), int>::value, "" );
|
||||
auto r8 = atomic_exchange(&a, l);
|
||||
static_assert( std::is_same<decltype(r8), long>::value, "" );
|
||||
auto r9 = atomic_exchange_explicit(&v, i, mo);
|
||||
static_assert( std::is_same<decltype(r9), int>::value, "" );
|
||||
auto r10 = atomic_exchange_explicit(&a, l, mo);
|
||||
static_assert( std::is_same<decltype(r10), long>::value, "" );
|
||||
auto r11 = atomic_compare_exchange_weak(&v, &i, i);
|
||||
static_assert( std::is_same<decltype(r11), bool>::value, "" );
|
||||
auto r12 = atomic_compare_exchange_weak(&a, &l, l);
|
||||
static_assert( std::is_same<decltype(r12), bool>::value, "" );
|
||||
auto r13 = atomic_compare_exchange_strong(&v, &i, i);
|
||||
static_assert( std::is_same<decltype(r13), bool>::value, "" );
|
||||
auto r14 = atomic_compare_exchange_strong(&a, &l, l);
|
||||
static_assert( std::is_same<decltype(r14), bool>::value, "" );
|
||||
auto r15 = atomic_compare_exchange_weak_explicit(&v, &i, i, mo, mo);
|
||||
static_assert( std::is_same<decltype(r15), bool>::value, "" );
|
||||
auto r16 = atomic_compare_exchange_weak_explicit(&a, &l, l, mo, mo);
|
||||
static_assert( std::is_same<decltype(r16), bool>::value, "" );
|
||||
auto r17 = atomic_compare_exchange_strong_explicit(&v, &i, i, mo, mo);
|
||||
static_assert( std::is_same<decltype(r17), bool>::value, "" );
|
||||
auto r18 = atomic_compare_exchange_strong_explicit(&a, &l, l, mo, mo);
|
||||
static_assert( std::is_same<decltype(r18), bool>::value, "" );
|
||||
|
||||
auto r19 = atomic_fetch_add(&v, i);
|
||||
static_assert( std::is_same<decltype(r19), int>::value, "" );
|
||||
auto r20 = atomic_fetch_add(&a, l);
|
||||
static_assert( std::is_same<decltype(r20), long>::value, "" );
|
||||
auto r21 = atomic_fetch_add_explicit(&v, i, mo);
|
||||
static_assert( std::is_same<decltype(r21), int>::value, "" );
|
||||
auto r22 = atomic_fetch_add_explicit(&a, l, mo);
|
||||
static_assert( std::is_same<decltype(r22), long>::value, "" );
|
||||
auto r23 = atomic_fetch_sub(&v, i);
|
||||
static_assert( std::is_same<decltype(r23), int>::value, "" );
|
||||
auto r24 = atomic_fetch_sub(&a, l);
|
||||
static_assert( std::is_same<decltype(r24), long>::value, "" );
|
||||
auto r25 = atomic_fetch_sub_explicit(&v, i, mo);
|
||||
static_assert( std::is_same<decltype(r25), int>::value, "" );
|
||||
auto r26 = atomic_fetch_sub_explicit(&a, l, mo);
|
||||
static_assert( std::is_same<decltype(r26), long>::value, "" );
|
||||
auto r27 = atomic_fetch_and(&v, i);
|
||||
static_assert( std::is_same<decltype(r27), int>::value, "" );
|
||||
auto r28 = atomic_fetch_and(&a, l);
|
||||
static_assert( std::is_same<decltype(r28), long>::value, "" );
|
||||
auto r29 = atomic_fetch_and_explicit(&v, i, mo);
|
||||
static_assert( std::is_same<decltype(r29), int>::value, "" );
|
||||
auto r30 = atomic_fetch_and_explicit(&a, l, mo);
|
||||
static_assert( std::is_same<decltype(r30), long>::value, "" );
|
||||
auto r31 = atomic_fetch_or(&v, i);
|
||||
static_assert( std::is_same<decltype(r31), int>::value, "" );
|
||||
auto r32 = atomic_fetch_or(&a, l);
|
||||
static_assert( std::is_same<decltype(r32), long>::value, "" );
|
||||
auto r33 = atomic_fetch_or_explicit(&v, i, mo);
|
||||
static_assert( std::is_same<decltype(r33), int>::value, "" );
|
||||
auto r34 = atomic_fetch_or_explicit(&a, l, mo);
|
||||
static_assert( std::is_same<decltype(r34), long>::value, "" );
|
||||
auto r35 = atomic_fetch_xor(&v, i);
|
||||
static_assert( std::is_same<decltype(r35), int>::value, "" );
|
||||
auto r36 = atomic_fetch_xor(&a, l);
|
||||
static_assert( std::is_same<decltype(r36), long>::value, "" );
|
||||
auto r37 = atomic_fetch_xor_explicit(&v, i, mo);
|
||||
static_assert( std::is_same<decltype(r37), int>::value, "" );
|
||||
auto r38 = atomic_fetch_xor_explicit(&a, l, mo);
|
||||
static_assert( std::is_same<decltype(r38), long>::value, "" );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
volatile std::atomic<long> v;
|
||||
std::atomic<long> 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);
|
||||
}
|
|
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do compile { target c++17 } }
|
||||
// { dg-require-atomic-builtins "" }
|
||||
|
||||
#include <atomic>
|
||||
|
||||
template<typename T>
|
||||
constexpr bool check()
|
||||
{
|
||||
typename std::atomic<T>::value_type* pv = (T*)nullptr;
|
||||
typename std::atomic<T>::difference_type* pd = (T*)nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert( check<signed short>(), "" );
|
||||
static_assert( check<unsigned short>(), "" );
|
||||
static_assert( check<signed int>(), "" );
|
||||
static_assert( check<unsigned int>(), "" );
|
||||
static_assert( check<signed long>(), "" );
|
||||
static_assert( check<unsigned long>(), "" );
|
||||
static_assert( check<signed long long>(), "" );
|
||||
static_assert( check<unsigned long long>(), "" );
|
Loading…
Add table
Reference in a new issue