summaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorTomasz Kamiński <tkaminsk@redhat.com>2025-11-12 11:16:58 +0100
committerTomasz Kamiński <tkaminsk@redhat.com>2025-11-13 13:23:23 +0100
commit427911622fcae352f086dd543b21c16071f7e4ab (patch)
treee081b7e2a5460d3672f6e1d80048a86808904f4c /libstdc++-v3
parentc9108d4dccb4b91e2ee4b8968891abe8ad7958a1 (diff)
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>
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_ref/address.cc7
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_ref/bool.cc10
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_ref/deduction.cc7
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_ref/float.cc34
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_ref/generic.cc9
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_ref/integral.cc9
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_ref/op_support.cc84
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_ref/pointer.cc9
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_ref/requirements.cc83
9 files changed, 155 insertions, 97 deletions
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/address.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/address.cc
index 42a080af55e..e2eda506efa 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/address.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/address.cc
@@ -24,8 +24,11 @@ void testAtomicRefAddressForCV()
{
testAtomicRefAddress<T>();
testAtomicRefAddress<const T>();
- testAtomicRefAddress<volatile T>();
- testAtomicRefAddress<const volatile T>();
+ if constexpr (std::atomic_ref<T>::is_always_lock_free)
+ {
+ testAtomicRefAddress<volatile T>();
+ testAtomicRefAddress<const volatile T>();
+ }
}
int
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/bool.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/bool.cc
index c73319010ee..76ba9fdbc63 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/bool.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/bool.cc
@@ -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() );
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/deduction.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/deduction.cc
index 01dbfce2375..bfc2080e566 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/deduction.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/deduction.cc
@@ -33,8 +33,11 @@ test(T v)
{
test_impl<T>(v);
test_impl<const T>(v);
- test_impl<volatile T>(v);
- test_impl<const volatile 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()
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/float.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/float.cc
index c69f3a711d3..5736668aeee 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/float.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/float.cc
@@ -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()
@@ -297,22 +302,19 @@ 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<float> a2(a0);
- a0 = 1.0f;
- VERIFY( a1 == 1.0f );
- VERIFY( a1c == 1.0f );
- VERIFY( a1v == 1.0f );
- VERIFY( a1cv == 1.0f );
- VERIFY( a2 == 1.0f );
- }
+ 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<volatile_<const float>> a1cv(i);
+ std::atomic_ref<float> a2(a0);
+ a0 = 1.0f;
+ VERIFY( a1 == 1.0f );
+ VERIFY( a1c == 1.0f );
+ VERIFY( a1v == 1.0f );
+ VERIFY( a1cv == 1.0f );
+ VERIFY( a2 == 1.0f );
}
int
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/generic.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/generic.cc
index 079ec1b1a78..7bdecdd9be8 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/generic.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/generic.cc
@@ -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 );
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/integral.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/integral.cc
index 310434cefb5..010b40b62a0 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/integral.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/integral.cc
@@ -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 );
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/op_support.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/op_support.cc
index 93c65dce263..3afa0bb6a8d 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/op_support.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/op_support.cc
@@ -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; };
@@ -16,53 +21,62 @@ template<typename T>
void
no_stores()
{
- static_assert( !HAS(a = t) );
- static_assert( !HAS(a.store(t)) );
- static_assert( !HAS(a.store(t, mo)) );
- static_assert( !HAS(a.exchange(t)) );
- static_assert( !HAS(a.exchange(t, mo)) );
-
- static_assert( !HAS(a.compare_exchange_weak(t, t)) );
- static_assert( !HAS(a.compare_exchange_weak(t, t, mo)) );
- static_assert( !HAS(a.compare_exchange_weak(t, t, mo, mo)) );
-
- static_assert( !HAS(a.compare_exchange_strong(t, t)) );
- static_assert( !HAS(a.compare_exchange_strong(t, t, mo)) );
- static_assert( !HAS(a.compare_exchange_strong(t, t, mo, mo)) );
+ if constexpr (is_supported<T>)
+ {
+ static_assert( !HAS(a = t) );
+ static_assert( !HAS(a.store(t)) );
+ static_assert( !HAS(a.store(t, mo)) );
+ static_assert( !HAS(a.exchange(t)) );
+ static_assert( !HAS(a.exchange(t, mo)) );
+
+ static_assert( !HAS(a.compare_exchange_weak(t, t)) );
+ static_assert( !HAS(a.compare_exchange_weak(t, t, mo)) );
+ static_assert( !HAS(a.compare_exchange_weak(t, t, mo, mo)) );
+
+ static_assert( !HAS(a.compare_exchange_strong(t, t)) );
+ 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()
{
- static_assert( !HAS(a++) );
- static_assert( !HAS(++a) );
- static_assert( !HAS(a += t) );
- static_assert( !HAS(a.fetch_add(t)) );
- static_assert( !HAS(a.fetch_add(t, mo)) );
-
- static_assert( !HAS(a--) );
- static_assert( !HAS(--a) );
- static_assert( !HAS(a -= t) );
- static_assert( !HAS(a.fetch_sub(t)) );
- static_assert( !HAS(a.fetch_sub(t, mo)) );
+ if constexpr (is_supported<T>)
+ {
+ static_assert( !HAS(a++) );
+ static_assert( !HAS(++a) );
+ static_assert( !HAS(a += t) );
+ static_assert( !HAS(a.fetch_add(t)) );
+ static_assert( !HAS(a.fetch_add(t, mo)) );
+
+ static_assert( !HAS(a--) );
+ static_assert( !HAS(--a) );
+ static_assert( !HAS(a -= t) );
+ static_assert( !HAS(a.fetch_sub(t)) );
+ static_assert( !HAS(a.fetch_sub(t, mo)) );
+ }
}
template<typename T>
void
no_bitops()
{
- static_assert( !HAS(a &= t) );
- static_assert( !HAS(a.fetch_and(t)) );
- static_assert( !HAS(a.fetch_and(t, mo)) );
-
- static_assert( !HAS(a |= t) );
- static_assert( !HAS(a.fetch_or(t)) );
- static_assert( !HAS(a.fetch_or(t, mo)) );
-
- static_assert( !HAS(a ^= t) );
- static_assert( !HAS(a.fetch_xor(t)) );
- static_assert( !HAS(a.fetch_xor(t, mo)) );
+ if constexpr (is_supported<T>)
+ {
+ static_assert( !HAS(a &= t) );
+ static_assert( !HAS(a.fetch_and(t)) );
+ static_assert( !HAS(a.fetch_and(t, mo)) );
+
+ static_assert( !HAS(a |= t) );
+ static_assert( !HAS(a.fetch_or(t)) );
+ static_assert( !HAS(a.fetch_or(t, mo)) );
+
+ static_assert( !HAS(a ^= t) );
+ static_assert( !HAS(a.fetch_xor(t)) );
+ static_assert( !HAS(a.fetch_xor(t, mo)) );
+ }
}
template<typename T>
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/pointer.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/pointer.cc
index 8db45c797c8..c503b330f9d 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/pointer.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/pointer.cc
@@ -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 );
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/requirements.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/requirements.cc
index 8617661f8e1..5d67c77daa8 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/requirements.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/requirements.cc
@@ -20,61 +20,78 @@
#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()
{
- using A = std::atomic_ref<T>;
- static_assert( std::is_standard_layout_v<A> );
- static_assert( std::is_nothrow_copy_constructible_v<A> );
- static_assert( std::is_trivially_destructible_v<A> );
- static_assert( std::is_same_v<typename A::value_type, std::remove_cv_t<T>> );
- static_assert( !requires { typename A::difference_type; } );
- static_assert( !std::is_copy_assignable_v<A> );
- static_assert( !std::is_move_assignable_v<A> );
+ if constexpr (is_supported<T>)
+ {
+ using A = std::atomic_ref<T>;
+ static_assert( std::is_standard_layout_v<A> );
+ static_assert( std::is_nothrow_copy_constructible_v<A> );
+ static_assert( std::is_trivially_destructible_v<A> );
+ static_assert( std::is_same_v<typename A::value_type, std::remove_cv_t<T>> );
+ static_assert( !requires { typename A::difference_type; } );
+ static_assert( !std::is_copy_assignable_v<A> );
+ static_assert( !std::is_move_assignable_v<A> );
+ }
}
template <class T>
void
test_integral()
{
- using A = std::atomic_ref<T>;
- static_assert( std::is_standard_layout_v<A> );
- static_assert( std::is_nothrow_copy_constructible_v<A> );
- static_assert( std::is_trivially_destructible_v<A> );
- static_assert( std::is_same_v<typename A::value_type, std::remove_cv_t<T>> );
- static_assert( std::is_same_v<typename A::difference_type, typename A::value_type> );
- static_assert( !std::is_copy_assignable_v<A> );
- static_assert( !std::is_move_assignable_v<A> );
+ if constexpr (is_supported<T>)
+ {
+ using A = std::atomic_ref<T>;
+ static_assert( std::is_standard_layout_v<A> );
+ static_assert( std::is_nothrow_copy_constructible_v<A> );
+ static_assert( std::is_trivially_destructible_v<A> );
+ static_assert( std::is_same_v<typename A::value_type, std::remove_cv_t<T>> );
+ static_assert( std::is_same_v<typename A::difference_type, typename A::value_type> );
+ static_assert( !std::is_copy_assignable_v<A> );
+ static_assert( !std::is_move_assignable_v<A> );
+ }
}
template <class T>
void
test_floating_point()
{
- using A = std::atomic_ref<T>;
- static_assert( std::is_standard_layout_v<A> );
- static_assert( std::is_nothrow_copy_constructible_v<A> );
- static_assert( std::is_trivially_destructible_v<A> );
- static_assert( std::is_same_v<typename A::value_type, std::remove_cv_t<T>> );
- static_assert( std::is_same_v<typename A::difference_type, typename A::value_type> );
- static_assert( !std::is_copy_assignable_v<A> );
- static_assert( !std::is_move_assignable_v<A> );
+ if constexpr (is_supported<T>)
+ {
+ using A = std::atomic_ref<T>;
+ static_assert( std::is_standard_layout_v<A> );
+ static_assert( std::is_nothrow_copy_constructible_v<A> );
+ static_assert( std::is_trivially_destructible_v<A> );
+ static_assert( std::is_same_v<typename A::value_type, std::remove_cv_t<T>> );
+ static_assert( std::is_same_v<typename A::difference_type, typename A::value_type> );
+ static_assert( !std::is_copy_assignable_v<A> );
+ static_assert( !std::is_move_assignable_v<A> );
+ }
}
template <class T>
void
test_pointer()
{
- using A = std::atomic_ref<T>;
- static_assert( std::is_standard_layout_v<A> );
- static_assert( std::is_nothrow_copy_constructible_v<A> );
- static_assert( std::is_trivially_destructible_v<A> );
- static_assert( std::is_same_v<typename A::value_type, std::remove_cv_t<T>> );
- static_assert( std::is_same_v<typename A::difference_type, std::ptrdiff_t> );
- static_assert( std::is_nothrow_copy_constructible_v<A> );
- static_assert( !std::is_copy_assignable_v<A> );
- static_assert( !std::is_move_assignable_v<A> );
+ if constexpr (is_supported<T>)
+ {
+ using A = std::atomic_ref<T>;
+ static_assert( std::is_standard_layout_v<A> );
+ static_assert( std::is_nothrow_copy_constructible_v<A> );
+ static_assert( std::is_trivially_destructible_v<A> );
+ static_assert( std::is_same_v<typename A::value_type, std::remove_cv_t<T>> );
+ static_assert( std::is_same_v<typename A::difference_type, std::ptrdiff_t> );
+ static_assert( std::is_nothrow_copy_constructible_v<A> );
+ static_assert( !std::is_copy_assignable_v<A> );
+ static_assert( !std::is_move_assignable_v<A> );
+ }
}
int