[libcxx-commits] [libcxx] [libc++][atomics] P3936R1: Safer ``atomic_ref::address`` (PR #189761)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Mar 31 22:44:47 PDT 2026
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/189761
>From 65495a97ff6272c0a581bd9905b8d0992ad1daec Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 1 Apr 2026 00:57:07 +0300
Subject: [PATCH 1/5] [libc++][atomics] P3936R1: Safer ``atomic_ref::address``
Implements P3936R1
Closes #
References:
- https://llvm.org/PR162236
- https://wg21.link/p3936r1
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +-
libcxx/docs/ReleaseNotes/23.rst | 1 +
libcxx/include/__atomic/atomic_ref.h | 6 +-
libcxx/include/version | 4 +-
.../std/atomics/atomics.ref/address.pass.cpp | 132 +++++++++++++++++-
.../atomic.version.compile.pass.cpp | 4 +-
.../version.version.compile.pass.cpp | 4 +-
.../generate_feature_test_macro_components.py | 3 +-
8 files changed, 143 insertions(+), 13 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 0f65770a4fa14..1447261645a7b 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -420,7 +420,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_atomic_min_max`` *unimplemented*
---------------------------------------------------------- -----------------
- ``__cpp_lib_atomic_ref`` ``202411L``
+ ``__cpp_lib_atomic_ref`` ``202603L``
---------------------------------------------------------- -----------------
``__cpp_lib_bind_front`` ``202306L``
---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index aeabfeedfbc5e..f64491eca98d0 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -39,6 +39,7 @@ Implemented Papers
------------------
- P2440R1: ``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right`` (`Github <https://llvm.org/PR105184>`__)
+- P3936R1: Safer ``atomic_ref::address``
Improvements and New Features
-----------------------------
diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h
index a5bc0aba38bd2..30910d81c976a 100644
--- a/libcxx/include/__atomic/atomic_ref.h
+++ b/libcxx/include/__atomic/atomic_ref.h
@@ -31,6 +31,7 @@
#include <__cstddef/ptrdiff_t.h>
#include <__memory/addressof.h>
#include <__memory/is_sufficiently_aligned.h>
+#include <__type_traits/copy_cv.h>
#include <__type_traits/has_unique_object_representation.h>
#include <__type_traits/is_trivially_copyable.h>
#include <cstring>
@@ -113,6 +114,9 @@ struct __atomic_ref_base {
public:
using value_type = _Tp;
+# if _LIBCPP_STD_VER >= 26
+ using __address_return_t = __copy_cv_t<_Tp, void>*;
+# endif
static constexpr size_t required_alignment = alignof(_Tp) > __min_alignment ? alignof(_Tp) : __min_alignment;
@@ -224,7 +228,7 @@ struct __atomic_ref_base {
_LIBCPP_HIDE_FROM_ABI void notify_one() const noexcept { std::__atomic_notify_one(*this); }
_LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); }
# if _LIBCPP_STD_VER >= 26
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp* address() const noexcept { return __ptr_; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __address_return_t address() const noexcept { return __ptr_; }
# endif
protected:
diff --git a/libcxx/include/version b/libcxx/include/version
index c43d36e569efb..105a04545da0e 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -37,7 +37,7 @@ __cpp_lib_atomic_float 201711L <atomic>
__cpp_lib_atomic_is_always_lock_free 201603L <atomic>
__cpp_lib_atomic_lock_free_type_aliases 201907L <atomic>
__cpp_lib_atomic_min_max 202403L <atomic>
-__cpp_lib_atomic_ref 202411L <atomic>
+__cpp_lib_atomic_ref 202603L <atomic>
201806L // C++20
__cpp_lib_atomic_shared_ptr 201711L <atomic>
__cpp_lib_atomic_value_initialization 201911L <atomic> <memory>
@@ -551,7 +551,7 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_associative_heterogeneous_insertion 202306L
// # define __cpp_lib_atomic_min_max 202403L
# undef __cpp_lib_atomic_ref
-# define __cpp_lib_atomic_ref 202411L
+# define __cpp_lib_atomic_ref 202603L
# undef __cpp_lib_bind_front
# define __cpp_lib_bind_front 202306L
# define __cpp_lib_bitset 202306L
diff --git a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
index 27f0c198e89ef..299bcd6e75f7b 100644
--- a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
@@ -8,7 +8,7 @@
// REQUIRES: std-at-least-c++26
-// constexpr T* address() const noexcept;
+// constexpr address-return-type address() const noexcept;
#include <atomic>
#include <cassert>
@@ -18,21 +18,145 @@
#include "atomic_helpers.h"
#include "test_macros.h"
+// Let COPYCV(FROM, TO) be an alias for type TO with the addition of FROM's
+// top-level cv-qualifiers.
+template <class _From>
+struct copy_cv {
+ template <class _To>
+ using apply _LIBCPP_NODEBUG = _To;
+};
+
+template <class _From>
+struct copy_cv<const _From> {
+ template <class _To>
+ using apply _LIBCPP_NODEBUG = const _To;
+};
+
+template <class _From>
+struct copy_cv<volatile _From> {
+ template <class _To>
+ using apply _LIBCPP_NODEBUG = volatile _To;
+};
+
+template <class _From>
+struct copy_cv<const volatile _From> {
+ template <class _To>
+ using apply _LIBCPP_NODEBUG = const volatile _To;
+};
+
+template <class _From, class _To>
+using copy_cv_t _LIBCPP_NODEBUG = typename copy_cv<_From>::template apply<_To>;
+
+template <template <class TestArg> class TestFunctor>
+struct TestEachCVAtomicType {
+ void operator()() const {
+ // integral types
+
+ TestFunctor<char>()();
+ TestFunctor<signed char>()();
+ TestFunctor<unsigned char>()();
+ TestFunctor<short>()();
+ TestFunctor<unsigned short>()();
+ TestFunctor<int>()();
+ TestFunctor<unsigned int>()();
+ TestFunctor<long>()();
+ TestFunctor<unsigned long>()();
+ TestFunctor<long long>()();
+ TestFunctor<unsigned long long>()();
+ TestFunctor<wchar_t>()();
+#if TEST_STD_VER >= 20 && defined(__cpp_char8_t)
+ TestFunctor<char8_t>()();
+#endif
+ TestFunctor<char16_t>()();
+ TestFunctor<char32_t>()();
+ TestFunctor<std::int8_t>()();
+ TestFunctor<std::uint8_t>()();
+ TestFunctor<std::int16_t>()();
+ TestFunctor<std::uint16_t>()();
+ TestFunctor<std::int32_t>()();
+ TestFunctor<std::uint32_t>()();
+ TestFunctor<std::int64_t>()();
+ TestFunctor<std::uint64_t>()();
+
+ TestFunctor<const char>()();
+ TestFunctor<const signed char>()();
+ TestFunctor<const unsigned char>()();
+ TestFunctor<const short>()();
+ TestFunctor<const unsigned short>()();
+ TestFunctor<const int>()();
+ TestFunctor<const unsigned int>()();
+ TestFunctor<const long>()();
+ TestFunctor<const unsigned long>()();
+ TestFunctor<const long long>()();
+ TestFunctor<const unsigned long long>()();
+ TestFunctor<const wchar_t>()();
+#if TEST_STD_VER >= 20 && defined(__cpp_char8_t)
+ TestFunctor<const char8_t>()();
+#endif
+ TestFunctor<const char16_t>()();
+ TestFunctor<const char32_t>()();
+ TestFunctor<const std::int8_t>()();
+ TestFunctor<const std::uint8_t>()();
+ TestFunctor<const std::int16_t>()();
+ TestFunctor<const std::uint16_t>()();
+ TestFunctor<const std::int32_t>()();
+ TestFunctor<const std::uint32_t>()();
+ TestFunctor<const std::int64_t>()();
+ TestFunctor<const std::uint64_t>()();
+
+ TestFunctor<char>()();
+ TestFunctor<signed char>()();
+ TestFunctor<unsigned char>()();
+ TestFunctor<short>()();
+ TestFunctor<unsigned short>()();
+ TestFunctor<int>()();
+ TestFunctor<unsigned int>()();
+ TestFunctor<long>()();
+ TestFunctor<unsigned long>()();
+ TestFunctor<long long>()();
+ TestFunctor<unsigned long long>()();
+ TestFunctor<wchar_t>()();
+#if TEST_STD_VER >= 20 && defined(__cpp_char8_t)
+ TestFunctor<char8_t>()();
+#endif
+ TestFunctor<char16_t>()();
+ TestFunctor<char32_t>()();
+ TestFunctor<std::int8_t>()();
+ TestFunctor<std::uint8_t>()();
+ TestFunctor<std::int16_t>()();
+ TestFunctor<std::uint16_t>()();
+ TestFunctor<std::int32_t>()();
+ TestFunctor<std::uint32_t>()();
+ TestFunctor<std::int64_t>()();
+ TestFunctor<std::uint64_t>()();
+
+ // floating-point types
+
+ TestFunctor<float>()();
+ TestFunctor<double>()();
+
+ TestFunctor<const float>()();
+ TestFunctor<const double>()();
+ }
+};
+
template <typename T>
struct TestAddress {
void operator()() const {
alignas(std::atomic_ref<T>::required_alignment) T x(T(1));
const std::atomic_ref<T> a(x);
- std::same_as<T*> decltype(auto) p = a.address();
+ using AddressReturnT = copy_cv_t<T, void>*;
+
+ std::same_as<AddressReturnT> decltype(auto) p = a.address();
assert(std::addressof(x) == p);
- static_assert(noexcept((a.address())));
+ static_assert(noexcept(a.address()));
}
};
int main(int, char**) {
- TestEachAtomicType<TestAddress>()();
+ TestEachCVAtomicType<TestAddress>()();
return 0;
}
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp
index 8bd027445c85b..e62416257a696 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.compile.pass.cpp
@@ -355,8 +355,8 @@
# ifndef __cpp_lib_atomic_ref
# error "__cpp_lib_atomic_ref should be defined in c++26"
# endif
-# if __cpp_lib_atomic_ref != 202411L
-# error "__cpp_lib_atomic_ref should have the value 202411L in c++26"
+# if __cpp_lib_atomic_ref != 202603L
+# error "__cpp_lib_atomic_ref should have the value 202603L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index a1c8755af4ad9..71b9d573a1778 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -6341,8 +6341,8 @@
# ifndef __cpp_lib_atomic_ref
# error "__cpp_lib_atomic_ref should be defined in c++26"
# endif
-# if __cpp_lib_atomic_ref != 202411L
-# error "__cpp_lib_atomic_ref should have the value 202411L in c++26"
+# if __cpp_lib_atomic_ref != 202603L
+# error "__cpp_lib_atomic_ref should have the value 202603L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index c5f81ca172f5a..55748bde39fb5 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -197,7 +197,8 @@ def add_version_header(tc):
"name": "__cpp_lib_atomic_ref",
"values": {
"c++20": 201806,
- "c++26": 202411, # P2835R7: Expose std::atomic_ref 's object address
+ # "c++26": 202411, # P2835R7: Expose std::atomic_ref 's object address
+ "c++26": 202603, # P3936R1: Safer atomic_ref::address
},
"headers": ["atomic"],
},
>From bb7ea3a7b86fcd00fc8543137a5c727b880d7174 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 1 Apr 2026 01:17:00 +0300
Subject: [PATCH 2/5] Full coverage
---
.../std/atomics/atomics.ref/address.pass.cpp | 115 +++++-------------
1 file changed, 28 insertions(+), 87 deletions(-)
diff --git a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
index 299bcd6e75f7b..c90c740eb819a 100644
--- a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++26
+// ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-deprecated-volatile
+// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated-volatile
// constexpr address-return-type address() const noexcept;
@@ -47,96 +49,35 @@ struct copy_cv<const volatile _From> {
template <class _From, class _To>
using copy_cv_t _LIBCPP_NODEBUG = typename copy_cv<_From>::template apply<_To>;
+template <class T>
+using identity_t = T;
+
+template <class T>
+using add_const_t = const T;
+
+template <class T>
+using add_volatile_t = volatile T;
+
+template <class T>
+using add_const_volatile_t = const volatile T;
+
+template <template <class TestArg> class TestFunctor, template <class> class AddQualifier>
+struct TestEachAtomicTypeWithCV {
+ template <class T>
+ struct Qualified {
+ void operator()() const { TestFunctor<AddQualifier<T>>()(); }
+ };
+
+ void operator()() const { TestEachAtomicType<Qualified>()(); }
+};
+
template <template <class TestArg> class TestFunctor>
struct TestEachCVAtomicType {
void operator()() const {
- // integral types
-
- TestFunctor<char>()();
- TestFunctor<signed char>()();
- TestFunctor<unsigned char>()();
- TestFunctor<short>()();
- TestFunctor<unsigned short>()();
- TestFunctor<int>()();
- TestFunctor<unsigned int>()();
- TestFunctor<long>()();
- TestFunctor<unsigned long>()();
- TestFunctor<long long>()();
- TestFunctor<unsigned long long>()();
- TestFunctor<wchar_t>()();
-#if TEST_STD_VER >= 20 && defined(__cpp_char8_t)
- TestFunctor<char8_t>()();
-#endif
- TestFunctor<char16_t>()();
- TestFunctor<char32_t>()();
- TestFunctor<std::int8_t>()();
- TestFunctor<std::uint8_t>()();
- TestFunctor<std::int16_t>()();
- TestFunctor<std::uint16_t>()();
- TestFunctor<std::int32_t>()();
- TestFunctor<std::uint32_t>()();
- TestFunctor<std::int64_t>()();
- TestFunctor<std::uint64_t>()();
-
- TestFunctor<const char>()();
- TestFunctor<const signed char>()();
- TestFunctor<const unsigned char>()();
- TestFunctor<const short>()();
- TestFunctor<const unsigned short>()();
- TestFunctor<const int>()();
- TestFunctor<const unsigned int>()();
- TestFunctor<const long>()();
- TestFunctor<const unsigned long>()();
- TestFunctor<const long long>()();
- TestFunctor<const unsigned long long>()();
- TestFunctor<const wchar_t>()();
-#if TEST_STD_VER >= 20 && defined(__cpp_char8_t)
- TestFunctor<const char8_t>()();
-#endif
- TestFunctor<const char16_t>()();
- TestFunctor<const char32_t>()();
- TestFunctor<const std::int8_t>()();
- TestFunctor<const std::uint8_t>()();
- TestFunctor<const std::int16_t>()();
- TestFunctor<const std::uint16_t>()();
- TestFunctor<const std::int32_t>()();
- TestFunctor<const std::uint32_t>()();
- TestFunctor<const std::int64_t>()();
- TestFunctor<const std::uint64_t>()();
-
- TestFunctor<char>()();
- TestFunctor<signed char>()();
- TestFunctor<unsigned char>()();
- TestFunctor<short>()();
- TestFunctor<unsigned short>()();
- TestFunctor<int>()();
- TestFunctor<unsigned int>()();
- TestFunctor<long>()();
- TestFunctor<unsigned long>()();
- TestFunctor<long long>()();
- TestFunctor<unsigned long long>()();
- TestFunctor<wchar_t>()();
-#if TEST_STD_VER >= 20 && defined(__cpp_char8_t)
- TestFunctor<char8_t>()();
-#endif
- TestFunctor<char16_t>()();
- TestFunctor<char32_t>()();
- TestFunctor<std::int8_t>()();
- TestFunctor<std::uint8_t>()();
- TestFunctor<std::int16_t>()();
- TestFunctor<std::uint16_t>()();
- TestFunctor<std::int32_t>()();
- TestFunctor<std::uint32_t>()();
- TestFunctor<std::int64_t>()();
- TestFunctor<std::uint64_t>()();
-
- // floating-point types
-
- TestFunctor<float>()();
- TestFunctor<double>()();
-
- TestFunctor<const float>()();
- TestFunctor<const double>()();
+ TestEachAtomicTypeWithCV<TestFunctor, identity_t>()();
+ TestEachAtomicTypeWithCV<TestFunctor, add_const_t>()();
+ TestEachAtomicTypeWithCV<TestFunctor, add_volatile_t>()();
+ TestEachAtomicTypeWithCV<TestFunctor, add_const_volatile_t>()();
}
};
>From de1406ab257bbf682ce2bfaaef1312601d5e6808 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hristo.goshev.hristov at gmail.com>
Date: Wed, 1 Apr 2026 08:23:35 +0300
Subject: [PATCH 3/5] Apply suggestions from code review
Co-authored-by: A. Jiang <de34 at live.cn>
---
libcxx/docs/ReleaseNotes/23.rst | 2 +-
libcxx/include/__atomic/atomic_ref.h | 2 +-
libcxx/test/std/atomics/atomics.ref/address.pass.cpp | 8 ++++----
libcxx/utils/generate_feature_test_macro_components.py | 3 +--
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index f64491eca98d0..462c90ded8701 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -39,7 +39,7 @@ Implemented Papers
------------------
- P2440R1: ``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right`` (`Github <https://llvm.org/PR105184>`__)
-- P3936R1: Safer ``atomic_ref::address``
+- P3936R1: Safer ``atomic_ref::address`` (`Github <https://llvm.org/PR189594>`__)
Improvements and New Features
-----------------------------
diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h
index 30910d81c976a..ec1b24e730ac8 100644
--- a/libcxx/include/__atomic/atomic_ref.h
+++ b/libcxx/include/__atomic/atomic_ref.h
@@ -228,7 +228,7 @@ struct __atomic_ref_base {
_LIBCPP_HIDE_FROM_ABI void notify_one() const noexcept { std::__atomic_notify_one(*this); }
_LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); }
# if _LIBCPP_STD_VER >= 26
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __address_return_t address() const noexcept { return __ptr_; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __copy_cv_t<_Tp, void>* address() const noexcept { return __ptr_; }
# endif
protected:
diff --git a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
index c90c740eb819a..c7d9c8c6152e0 100644
--- a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
@@ -74,10 +74,10 @@ struct TestEachAtomicTypeWithCV {
template <template <class TestArg> class TestFunctor>
struct TestEachCVAtomicType {
void operator()() const {
- TestEachAtomicTypeWithCV<TestFunctor, identity_t>()();
- TestEachAtomicTypeWithCV<TestFunctor, add_const_t>()();
- TestEachAtomicTypeWithCV<TestFunctor, add_volatile_t>()();
- TestEachAtomicTypeWithCV<TestFunctor, add_const_volatile_t>()();
+ TestEachAtomicTypeWithCV<TestFunctor, std::type_identity_t>()();
+ TestEachAtomicTypeWithCV<TestFunctor, std::add_const_t>()();
+ TestEachAtomicTypeWithCV<TestFunctor, std::add_volatile_t>()();
+ TestEachAtomicTypeWithCV<TestFunctor, std::add_cv_t>()();
}
};
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 55748bde39fb5..a1d5aca1d3442 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -197,8 +197,7 @@ def add_version_header(tc):
"name": "__cpp_lib_atomic_ref",
"values": {
"c++20": 201806,
- # "c++26": 202411, # P2835R7: Expose std::atomic_ref 's object address
- "c++26": 202603, # P3936R1: Safer atomic_ref::address
+ "c++26": 202603,
},
"headers": ["atomic"],
},
>From b29afd811adc04349d579810c19967a20f6710f5 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 1 Apr 2026 08:27:19 +0300
Subject: [PATCH 4/5] Cleanup
---
libcxx/include/__atomic/atomic_ref.h | 3 ---
libcxx/test/std/atomics/atomics.ref/address.pass.cpp | 11 ++++++-----
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h
index ec1b24e730ac8..c551f99024931 100644
--- a/libcxx/include/__atomic/atomic_ref.h
+++ b/libcxx/include/__atomic/atomic_ref.h
@@ -114,9 +114,6 @@ struct __atomic_ref_base {
public:
using value_type = _Tp;
-# if _LIBCPP_STD_VER >= 26
- using __address_return_t = __copy_cv_t<_Tp, void>*;
-# endif
static constexpr size_t required_alignment = alignof(_Tp) > __min_alignment ? alignof(_Tp) : __min_alignment;
diff --git a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
index c7d9c8c6152e0..db56be9080a25 100644
--- a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++26
+
// ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-deprecated-volatile
// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated-volatile
@@ -25,29 +26,29 @@
template <class _From>
struct copy_cv {
template <class _To>
- using apply _LIBCPP_NODEBUG = _To;
+ using apply = _To;
};
template <class _From>
struct copy_cv<const _From> {
template <class _To>
- using apply _LIBCPP_NODEBUG = const _To;
+ using apply = const _To;
};
template <class _From>
struct copy_cv<volatile _From> {
template <class _To>
- using apply _LIBCPP_NODEBUG = volatile _To;
+ using apply = volatile _To;
};
template <class _From>
struct copy_cv<const volatile _From> {
template <class _To>
- using apply _LIBCPP_NODEBUG = const volatile _To;
+ using apply = const volatile _To;
};
template <class _From, class _To>
-using copy_cv_t _LIBCPP_NODEBUG = typename copy_cv<_From>::template apply<_To>;
+using copy_cv_t = typename copy_cv<_From>::template apply<_To>;
template <class T>
using identity_t = T;
>From 12cf1d7f1499aa46ccece5eb6807cfb9dedceaf2 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 1 Apr 2026 08:44:29 +0300
Subject: [PATCH 5/5] Applied suggestion
---
.../std/atomics/atomics.ref/address.pass.cpp | 49 +++----------------
1 file changed, 7 insertions(+), 42 deletions(-)
diff --git a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
index db56be9080a25..ec94e639b9598 100644
--- a/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.ref/address.pass.cpp
@@ -17,51 +17,11 @@
#include <cassert>
#include <concepts>
#include <memory>
+#include <type_traits>
#include "atomic_helpers.h"
#include "test_macros.h"
-// Let COPYCV(FROM, TO) be an alias for type TO with the addition of FROM's
-// top-level cv-qualifiers.
-template <class _From>
-struct copy_cv {
- template <class _To>
- using apply = _To;
-};
-
-template <class _From>
-struct copy_cv<const _From> {
- template <class _To>
- using apply = const _To;
-};
-
-template <class _From>
-struct copy_cv<volatile _From> {
- template <class _To>
- using apply = volatile _To;
-};
-
-template <class _From>
-struct copy_cv<const volatile _From> {
- template <class _To>
- using apply = const volatile _To;
-};
-
-template <class _From, class _To>
-using copy_cv_t = typename copy_cv<_From>::template apply<_To>;
-
-template <class T>
-using identity_t = T;
-
-template <class T>
-using add_const_t = const T;
-
-template <class T>
-using add_volatile_t = volatile T;
-
-template <class T>
-using add_const_volatile_t = const volatile T;
-
template <template <class TestArg> class TestFunctor, template <class> class AddQualifier>
struct TestEachAtomicTypeWithCV {
template <class T>
@@ -88,7 +48,12 @@ struct TestAddress {
alignas(std::atomic_ref<T>::required_alignment) T x(T(1));
const std::atomic_ref<T> a(x);
- using AddressReturnT = copy_cv_t<T, void>*;
+ using AddressReturnT =
+ std::conditional_t<std::is_const_v<T> && std::is_volatile_v<T>,
+ const volatile void,
+ std::conditional_t<std::is_volatile_v<T>,
+ volatile void,
+ std::conditional_t<std::is_const_v<T>, const void, void>>>*;
std::same_as<AddressReturnT> decltype(auto) p = a.address();
assert(std::addressof(x) == p);
More information about the libcxx-commits
mailing list