mirror of git://gcc.gnu.org/git/gcc.git
libtdc++: Test atomic_ref<volatile T> only if operations are lock-free [PR122584]
For non-templated tests, a volatile_<T> alias is used. This alias expands to volatile T if std::atomic_ref<T>::is_always_lock_free is true, and to T otherwise. For templated functions, testing is controlled using if constexpr. PR libstdc++/115402 PR libstdc++/122584 libstdc++-v3/ChangeLog: * testsuite/29_atomics/atomic_ref/address.cc: Guard test for volatile with if constexpr. * testsuite/29_atomics/atomic_ref/deduction.cc: Likewise. * testsuite/29_atomics/atomic_ref/op_support.cc: Likewise. * testsuite/29_atomics/atomic_ref/requirements.cc: Likewise. * testsuite/29_atomics/atomic_ref/bool.cc: Use volatile_t alias. * testsuite/29_atomics/atomic_ref/generic.cc: Likewise. * testsuite/29_atomics/atomic_ref/integral.cc: Likewise. * testsuite/29_atomics/atomic_ref/pointer.cc: Likewise. * testsuite/29_atomics/atomic_ref/float.cc: Likewise, and remove not discarding if constexpr. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
This commit is contained in:
parent
c9108d4dcc
commit
427911622f
|
|
@ -24,9 +24,12 @@ void testAtomicRefAddressForCV()
|
|||
{
|
||||
testAtomicRefAddress<T>();
|
||||
testAtomicRefAddress<const T>();
|
||||
if constexpr (std::atomic_ref<T>::is_always_lock_free)
|
||||
{
|
||||
testAtomicRefAddress<volatile T>();
|
||||
testAtomicRefAddress<const volatile T>();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
|
|
|
|||
|
|
@ -21,12 +21,16 @@
|
|||
|
||||
#include <atomic>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <type_traits>
|
||||
|
||||
template<typename T>
|
||||
using volatile_
|
||||
= std::conditional_t<std::atomic_ref<T>::is_always_lock_free, volatile T, T>;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool value;
|
||||
|
||||
{
|
||||
const auto mo = std::memory_order_relaxed;
|
||||
std::atomic_ref<bool> a(value);
|
||||
|
|
@ -66,8 +70,8 @@ test02()
|
|||
std::atomic_ref<bool> a0(b);
|
||||
std::atomic_ref<bool> a1(b);
|
||||
std::atomic_ref<const bool> a1c(b);
|
||||
std::atomic_ref<volatile bool> a1v(b);
|
||||
std::atomic_ref<const volatile bool> a1cv(b);
|
||||
std::atomic_ref<volatile_<bool>> a1v(b);
|
||||
std::atomic_ref<volatile_<const bool>> a1cv(b);
|
||||
std::atomic_ref<bool> a2(a0);
|
||||
b = true;
|
||||
VERIFY( a1.load() );
|
||||
|
|
|
|||
|
|
@ -33,9 +33,12 @@ test(T v)
|
|||
{
|
||||
test_impl<T>(v);
|
||||
test_impl<const T>(v);
|
||||
if constexpr (std::atomic_ref<T>::is_always_lock_free)
|
||||
{
|
||||
test_impl<volatile T>(v);
|
||||
test_impl<const volatile T>(v);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
#include <atomic>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <type_traits>
|
||||
|
||||
template<typename T>
|
||||
using volatile_
|
||||
= std::conditional_t<std::atomic_ref<T>::is_always_lock_free, volatile T, T>;
|
||||
|
||||
void
|
||||
test01()
|
||||
|
|
@ -296,15 +301,13 @@ test03()
|
|||
|
||||
void
|
||||
test04()
|
||||
{
|
||||
if constexpr (std::atomic_ref<float>::is_always_lock_free)
|
||||
{
|
||||
float i = 0.0f;
|
||||
std::atomic_ref<float> a0(i);
|
||||
std::atomic_ref<float> a1(i);
|
||||
std::atomic_ref<const float> a1c(i);
|
||||
std::atomic_ref<volatile float> a1v(i);
|
||||
std::atomic_ref<const volatile float> a1cv(i);
|
||||
std::atomic_ref<volatile_<float>> a1v(i);
|
||||
std::atomic_ref<volatile_<const float>> a1cv(i);
|
||||
std::atomic_ref<float> a2(a0);
|
||||
a0 = 1.0f;
|
||||
VERIFY( a1 == 1.0f );
|
||||
|
|
@ -313,7 +316,6 @@ test04()
|
|||
VERIFY( a1cv == 1.0f );
|
||||
VERIFY( a2 == 1.0f );
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@
|
|||
#include <atomic>
|
||||
#include <limits.h>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <type_traits>
|
||||
|
||||
template<typename T>
|
||||
using volatile_
|
||||
= std::conditional_t<std::atomic_ref<T>::is_always_lock_free, volatile T, T>;
|
||||
|
||||
struct X
|
||||
{
|
||||
|
|
@ -109,8 +114,8 @@ test02()
|
|||
std::atomic_ref<X> a0(i);
|
||||
std::atomic_ref<X> a1(i);
|
||||
std::atomic_ref<const X> a1c(i);
|
||||
std::atomic_ref<volatile X> a1v(i);
|
||||
std::atomic_ref<const volatile X> a1cv(i);
|
||||
std::atomic_ref<volatile_<X>> a1v(i);
|
||||
std::atomic_ref<volatile_<const X>> a1cv(i);
|
||||
std::atomic_ref<X> a2(a0);
|
||||
a0 = 42;
|
||||
VERIFY( a1.load() == 42 );
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@
|
|||
#include <atomic>
|
||||
#include <limits.h>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <type_traits>
|
||||
|
||||
template<typename T>
|
||||
using volatile_
|
||||
= std::conditional_t<std::atomic_ref<T>::is_always_lock_free, volatile T, T>;
|
||||
|
||||
void
|
||||
test01()
|
||||
|
|
@ -303,8 +308,8 @@ test03()
|
|||
std::atomic_ref<int> a0(i);
|
||||
std::atomic_ref<int> a1(i);
|
||||
std::atomic_ref<const int> a1c(i);
|
||||
std::atomic_ref<volatile int> a1v(i);
|
||||
std::atomic_ref<const volatile int> a1cv(i);
|
||||
std::atomic_ref<volatile_<int>> a1v(i);
|
||||
std::atomic_ref<volatile_<const int>> a1cv(i);
|
||||
std::atomic_ref<int> a2(a0);
|
||||
a0 = 42;
|
||||
VERIFY( a1 == 42 );
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
#include <atomic>
|
||||
|
||||
template<typename T>
|
||||
concept is_supported
|
||||
= !std::is_volatile_v<T>
|
||||
|| std::atomic_ref<std::remove_cv_t<T>>::is_always_lock_free;
|
||||
|
||||
template<class T> concept has_and = requires (T& a) { a &= false; };
|
||||
template<class T> concept has_or = requires (T& a) { a |= false; };
|
||||
template<class T> concept has_xor = requires (T& a) { a ^= false; };
|
||||
|
|
@ -15,6 +20,8 @@ static constexpr std::memory_order mo = std::memory_order_seq_cst;
|
|||
template<typename T>
|
||||
void
|
||||
no_stores()
|
||||
{
|
||||
if constexpr (is_supported<T>)
|
||||
{
|
||||
static_assert( !HAS(a = t) );
|
||||
static_assert( !HAS(a.store(t)) );
|
||||
|
|
@ -30,10 +37,13 @@ no_stores()
|
|||
static_assert( !HAS(a.compare_exchange_strong(t, t, mo)) );
|
||||
static_assert( !HAS(a.compare_exchange_strong(t, t, mo, mo)) );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
no_additions()
|
||||
{
|
||||
if constexpr (is_supported<T>)
|
||||
{
|
||||
static_assert( !HAS(a++) );
|
||||
static_assert( !HAS(++a) );
|
||||
|
|
@ -47,10 +57,13 @@ no_additions()
|
|||
static_assert( !HAS(a.fetch_sub(t)) );
|
||||
static_assert( !HAS(a.fetch_sub(t, mo)) );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
no_bitops()
|
||||
{
|
||||
if constexpr (is_supported<T>)
|
||||
{
|
||||
static_assert( !HAS(a &= t) );
|
||||
static_assert( !HAS(a.fetch_and(t)) );
|
||||
|
|
@ -64,6 +77,7 @@ no_bitops()
|
|||
static_assert( !HAS(a.fetch_xor(t)) );
|
||||
static_assert( !HAS(a.fetch_xor(t, mo)) );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@
|
|||
|
||||
#include <atomic>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <type_traits>
|
||||
|
||||
template<typename T>
|
||||
using volatile_
|
||||
= std::conditional_t<std::atomic_ref<T>::is_always_lock_free, volatile T, T>;
|
||||
|
||||
void
|
||||
test01()
|
||||
|
|
@ -211,8 +216,8 @@ test03()
|
|||
std::atomic_ref<int*> a0(ptr);
|
||||
std::atomic_ref<int*> a1(ptr);
|
||||
std::atomic_ref<int* const> a1c(ptr);
|
||||
std::atomic_ref<int* volatile> a1v(ptr);
|
||||
std::atomic_ref<int* const volatile> a1cv(ptr);
|
||||
std::atomic_ref<volatile_<int*>> a1v(ptr);
|
||||
std::atomic_ref<volatile_<int* const>> a1cv(ptr);
|
||||
std::atomic_ref<int*> a2(a0);
|
||||
a0 = &i;
|
||||
VERIFY( a1 == &i );
|
||||
|
|
|
|||
|
|
@ -20,9 +20,16 @@
|
|||
#include <atomic>
|
||||
#include <type_traits>
|
||||
|
||||
template<typename T>
|
||||
concept is_supported
|
||||
= !std::is_volatile_v<T>
|
||||
|| std::atomic_ref<std::remove_cv_t<T>>::is_always_lock_free;
|
||||
|
||||
template <class T>
|
||||
void
|
||||
test_generic()
|
||||
{
|
||||
if constexpr (is_supported<T>)
|
||||
{
|
||||
using A = std::atomic_ref<T>;
|
||||
static_assert( std::is_standard_layout_v<A> );
|
||||
|
|
@ -33,10 +40,13 @@ test_generic()
|
|||
static_assert( !std::is_copy_assignable_v<A> );
|
||||
static_assert( !std::is_move_assignable_v<A> );
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
test_integral()
|
||||
{
|
||||
if constexpr (is_supported<T>)
|
||||
{
|
||||
using A = std::atomic_ref<T>;
|
||||
static_assert( std::is_standard_layout_v<A> );
|
||||
|
|
@ -47,10 +57,13 @@ test_integral()
|
|||
static_assert( !std::is_copy_assignable_v<A> );
|
||||
static_assert( !std::is_move_assignable_v<A> );
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
test_floating_point()
|
||||
{
|
||||
if constexpr (is_supported<T>)
|
||||
{
|
||||
using A = std::atomic_ref<T>;
|
||||
static_assert( std::is_standard_layout_v<A> );
|
||||
|
|
@ -61,10 +74,13 @@ test_floating_point()
|
|||
static_assert( !std::is_copy_assignable_v<A> );
|
||||
static_assert( !std::is_move_assignable_v<A> );
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
test_pointer()
|
||||
{
|
||||
if constexpr (is_supported<T>)
|
||||
{
|
||||
using A = std::atomic_ref<T>;
|
||||
static_assert( std::is_standard_layout_v<A> );
|
||||
|
|
@ -76,6 +92,7 @@ test_pointer()
|
|||
static_assert( !std::is_copy_assignable_v<A> );
|
||||
static_assert( !std::is_move_assignable_v<A> );
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
|
|
|
|||
Loading…
Reference in New Issue