+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
template<typename _ITp>
struct __atomic_base
{
+ using value_type = _ITp;
+ using difference_type = value_type;
+
private:
typedef _ITp __int_type;
* @{
*/
-#if __cplusplus > 201402L
+#if __cplusplus >= 201703L
# define __cpp_lib_atomic_is_always_lock_free 201603
#endif
template<>
struct atomic<bool>
{
+ using value_type = bool;
+
private:
__atomic_base<bool> _M_base;
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
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
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
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;
__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
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
__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);
+ }
};
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
};
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
};
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
};
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
};
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
};
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
};
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
};
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
};
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
};
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
};
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
};
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
};
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
};
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
};
{ 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
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); }
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); }
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); }
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); }
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); }
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>
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,
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,
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,
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
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 }
--- /dev/null
+// 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" }
--- /dev/null
+// 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);
+}
-// { 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.
--- /dev/null
+// 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*>(), "" );
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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>(), "" );