[libcxx-commits] [libcxx] [libcxx] Implementation of P1831R1 (PR #101439)

Josh Karns via libcxx-commits libcxx-commits at lists.llvm.org
Sun Aug 4 01:19:17 PDT 2024


https://github.com/jkarns275 updated https://github.com/llvm/llvm-project/pull/101439

>From 92261c5c95f503d01465048cd1d8e5e36e5ced14 Mon Sep 17 00:00:00 2001
From: Joshua Karns <jkarns275 at gmail.com>
Date: Wed, 31 Jul 2024 20:42:59 -0400
Subject: [PATCH 1/6] Initial implementation of P1831R1

---
 libcxx/include/__atomic/atomic.h       |  61 ++++++++++---
 libcxx/include/__atomic/atomic_base.h  | 117 ++++++++++++++++++++-----
 libcxx/include/__tuple/tuple_element.h |  10 ---
 libcxx/include/__tuple/tuple_size.h    |  11 ---
 libcxx/include/variant                 |  12 ---
 5 files changed, 146 insertions(+), 65 deletions(-)

diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index bcea21f5ce2e1..ceb9ae773940e 100644
--- a/libcxx/include/__atomic/atomic.h
+++ b/libcxx/include/__atomic/atomic.h
@@ -46,7 +46,9 @@ struct atomic : public __atomic_base<_Tp> {
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT 
+    requires __base::is_always_lock_free
+  {
     __base::store(__d);
     return __d;
   }
@@ -71,7 +73,9 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT 
+    requires __base::is_always_lock_free
+  {
     __base::store(__d);
     return __d;
   }
@@ -80,7 +84,9 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
     return __d;
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT 
+    requires __base::is_always_lock_free
+  {
     // __atomic_fetch_add accepts function pointers, guard against them.
     static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
@@ -92,7 +98,9 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT 
+    requires __base::is_always_lock_free
+  {
     // __atomic_fetch_add accepts function pointers, guard against them.
     static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
     return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
@@ -104,18 +112,47 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
     return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT { return fetch_add(1); }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT { return fetch_sub(1); }
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT
+    requires __base::is_always_lock_free 
+  {
+    return fetch_add(1);
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT { return fetch_add(1) + 1; }
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_sub(1);
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT { return fetch_sub(1) - 1; }
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_add(1) + 1;
+  }
+  
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_sub(1) - 1;
+  }
+  
   _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT 
+    requires __base::is_always_lock_free
+  {
+    return fetch_add(__op) + __op;
+  }
+  
   _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_sub(__op) - __op;
+  }
 
   atomic& operator=(const atomic&)          = delete;
   atomic& operator=(const atomic&) volatile = delete;
@@ -267,7 +304,9 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT
 
 template <class _Tp>
 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void
-atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
+atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
+  requires __atomic_base<_Tp>::is_always_lock_free
+{
   std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
 }
 
diff --git a/libcxx/include/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h
index 93f5c4cff0d1b..d9a9aa341a600 100644
--- a/libcxx/include/__atomic/atomic_base.h
+++ b/libcxx/include/__atomic/atomic_base.h
@@ -43,7 +43,7 @@ struct __atomic_base // false
     return static_cast<__atomic_base const volatile*>(this)->is_lock_free();
   }
   _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-      _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
+    requires is_always_lock_free _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
     std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT
@@ -51,7 +51,7 @@ struct __atomic_base // false
     std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT
-      _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
+    requires is_always_lock_free _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
     return std::__cxx_atomic_load(std::addressof(__a_), __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT
@@ -60,7 +60,8 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT { return load(); }
   _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); }
-  _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
+    requires is_always_lock_free {
     return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
@@ -68,7 +69,7 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
-      _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
+    requires is_always_lock_free _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
   _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -77,7 +78,7 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
-      _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
+    requires is_always_lock_free _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
   _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -85,7 +86,8 @@ struct __atomic_base // false
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
   _LIBCPP_HIDE_FROM_ABI bool
-  compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+  compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
+    requires is_always_lock_free {
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
   _LIBCPP_HIDE_FROM_ABI bool
@@ -93,7 +95,8 @@ struct __atomic_base // false
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
   _LIBCPP_HIDE_FROM_ABI bool
-  compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+  compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
+    requires is_always_lock_free {
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
   _LIBCPP_HIDE_FROM_ABI bool
@@ -141,55 +144,127 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {}
 
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
   }
+
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
     return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
   }
+
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
     return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
     return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);
   }
+
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
     return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
     return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);
   }
+
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
     return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
     return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);
   }
+
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
     return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT { return fetch_add(_Tp(1)); }
   _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT { return fetch_sub(_Tp(1)); }
+
+  _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT
+  requires __base::is_always_lock_free
+  {
+    return fetch_add(_Tp(1));
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }
+
+  _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_sub(_Tp(1));
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }
+
+  _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_add(_Tp(1)) + _Tp(1);
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }
+
+  _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_sub(_Tp(1)) - _Tp(1);
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) _NOEXCEPT { return fetch_add(__op) + __op; }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }
+
+  _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_add(__op) + __op;
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT { return fetch_and(__op) & __op; }
+
+  _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_sub(__op) - __op;
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) _NOEXCEPT { return fetch_and(__op) & __op; }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT { return fetch_or(__op) | __op; }
+
+  _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_and(__op) & __op;
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) _NOEXCEPT { return fetch_or(__op) | __op; }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT { return fetch_xor(__op) ^ __op; }
+
+  _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_or(__op) | __op;
+  }
+
   _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; }
+
+  _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT
+    requires __base::is_always_lock_free
+  {
+    return fetch_xor(__op) ^ __op;
+  }
 };
 
 // Here we need _IsIntegral because the default template argument is not enough
diff --git a/libcxx/include/__tuple/tuple_element.h b/libcxx/include/__tuple/tuple_element.h
index 9127c47dc8f1a..bcffc540eaf02 100644
--- a/libcxx/include/__tuple/tuple_element.h
+++ b/libcxx/include/__tuple/tuple_element.h
@@ -28,16 +28,6 @@ struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const _Tp> {
   typedef _LIBCPP_NODEBUG const typename tuple_element<_Ip, _Tp>::type type;
 };
 
-template <size_t _Ip, class _Tp>
-struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, volatile _Tp> {
-  typedef _LIBCPP_NODEBUG volatile typename tuple_element<_Ip, _Tp>::type type;
-};
-
-template <size_t _Ip, class _Tp>
-struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const volatile _Tp> {
-  typedef _LIBCPP_NODEBUG const volatile typename tuple_element<_Ip, _Tp>::type type;
-};
-
 #ifndef _LIBCPP_CXX03_LANG
 
 template <size_t _Ip, class... _Types>
diff --git a/libcxx/include/__tuple/tuple_size.h b/libcxx/include/__tuple/tuple_size.h
index 18a17fd4d5878..8dc6bfdb828d8 100644
--- a/libcxx/include/__tuple/tuple_size.h
+++ b/libcxx/include/__tuple/tuple_size.h
@@ -35,17 +35,6 @@ struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp< const _Tp,
                                                                    integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
     : public integral_constant<size_t, tuple_size<_Tp>::value> {};
 
-template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp< volatile _Tp,
-                                                                   __enable_if_t<!is_const<_Tp>::value>,
-                                                                   integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
-    : public integral_constant<size_t, tuple_size<_Tp>::value> {};
-
-template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS
-tuple_size<__enable_if_tuple_size_imp<const volatile _Tp, integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
-    : public integral_constant<size_t, tuple_size<_Tp>::value> {};
-
 #else
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_size<const _Tp> : public tuple_size<_Tp> {};
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 5f2d03b7227b8..94767e482bcca 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -317,12 +317,6 @@ inline constexpr size_t variant_size_v = variant_size<_Tp>::value;
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS variant_size<const _Tp> : variant_size<_Tp> {};
 
-template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS variant_size<volatile _Tp> : variant_size<_Tp> {};
-
-template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS variant_size<const volatile _Tp> : variant_size<_Tp> {};
-
 template <class... _Types>
 struct _LIBCPP_TEMPLATE_VIS variant_size<variant<_Types...>> : integral_constant<size_t, sizeof...(_Types)> {};
 
@@ -335,12 +329,6 @@ using variant_alternative_t = typename variant_alternative<_Ip, _Tp>::type;
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const _Tp> : add_const<variant_alternative_t<_Ip, _Tp>> {};
 
-template <size_t _Ip, class _Tp>
-struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, volatile _Tp> : add_volatile<variant_alternative_t<_Ip, _Tp>> {};
-
-template <size_t _Ip, class _Tp>
-struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const volatile _Tp> : add_cv<variant_alternative_t<_Ip, _Tp>> {};
-
 template <size_t _Ip, class... _Types>
 struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, variant<_Types...>> {
   static_assert(_Ip < sizeof...(_Types), "Index out of bounds in std::variant_alternative<>");

>From c7f73947eca6d144e4edc2c0d2f95c2c0f2e312b Mon Sep 17 00:00:00 2001
From: Joshua Karns <jkarns275 at gmail.com>
Date: Wed, 31 Jul 2024 20:55:41 -0400
Subject: [PATCH 2/6] ran clang-format

---
 libcxx/include/__atomic/atomic.h      | 18 +++++++++---------
 libcxx/include/__atomic/atomic_base.h | 23 +++++++++++++++--------
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index ceb9ae773940e..74c7d49c65055 100644
--- a/libcxx/include/__atomic/atomic.h
+++ b/libcxx/include/__atomic/atomic.h
@@ -46,7 +46,7 @@ struct atomic : public __atomic_base<_Tp> {
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT 
+  _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT
     requires __base::is_always_lock_free
   {
     __base::store(__d);
@@ -73,7 +73,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT 
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT
     requires __base::is_always_lock_free
   {
     __base::store(__d);
@@ -84,7 +84,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
     return __d;
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT 
+  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
     requires __base::is_always_lock_free
   {
     // __atomic_fetch_add accepts function pointers, guard against them.
@@ -98,7 +98,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT 
+  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
     requires __base::is_always_lock_free
   {
     // __atomic_fetch_add accepts function pointers, guard against them.
@@ -114,7 +114,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT
-    requires __base::is_always_lock_free 
+    requires __base::is_always_lock_free
   {
     return fetch_add(1);
   }
@@ -132,21 +132,21 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
   {
     return fetch_add(1) + 1;
   }
-  
+
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT
     requires __base::is_always_lock_free
   {
     return fetch_sub(1) - 1;
   }
-  
+
   _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT 
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT
     requires __base::is_always_lock_free
   {
     return fetch_add(__op) + __op;
   }
-  
+
   _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT
     requires __base::is_always_lock_free
diff --git a/libcxx/include/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h
index d9a9aa341a600..35a6fb00dbc3e 100644
--- a/libcxx/include/__atomic/atomic_base.h
+++ b/libcxx/include/__atomic/atomic_base.h
@@ -43,7 +43,8 @@ struct __atomic_base // false
     return static_cast<__atomic_base const volatile*>(this)->is_lock_free();
   }
   _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires is_always_lock_free _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
+    requires is_always_lock_free
+  _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
     std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT
@@ -51,7 +52,8 @@ struct __atomic_base // false
     std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT
-    requires is_always_lock_free _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
+    requires is_always_lock_free
+  _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
     return std::__cxx_atomic_load(std::addressof(__a_), __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT
@@ -61,7 +63,8 @@ struct __atomic_base // false
   _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT { return load(); }
   _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); }
   _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires is_always_lock_free {
+    requires is_always_lock_free
+  {
     return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
@@ -69,7 +72,8 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
-    requires is_always_lock_free _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
+    requires is_always_lock_free
+  _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
   _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -78,7 +82,8 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
-    requires is_always_lock_free _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
+    requires is_always_lock_free
+  _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
   _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -87,7 +92,8 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires is_always_lock_free {
+    requires is_always_lock_free
+  {
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
   _LIBCPP_HIDE_FROM_ABI bool
@@ -96,7 +102,8 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires is_always_lock_free {
+    requires is_always_lock_free
+  {
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
   _LIBCPP_HIDE_FROM_ABI bool
@@ -197,7 +204,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT
-  requires __base::is_always_lock_free
+    requires __base::is_always_lock_free
   {
     return fetch_add(_Tp(1));
   }

>From 9602a0a0a7c9b1451cb3de2b9761904dd56db501 Mon Sep 17 00:00:00 2001
From: Joshua Karns <jkarns275 at gmail.com>
Date: Thu, 1 Aug 2024 22:00:58 -0400
Subject: [PATCH 3/6] feature gate atomic changes to c++, update synopses,
 revert tuple and variant changes

---
 libcxx/include/__atomic/atomic.h              | 20 ++---
 libcxx/include/__atomic/atomic_base.h         | 55 +++++++-----
 libcxx/include/__tuple/tuple_element.h        | 10 +++
 libcxx/include/__tuple/tuple_size.h           | 11 +++
 libcxx/include/tuple                          | 11 ++-
 libcxx/include/variant                        | 20 ++++-
 ...tile_require_lock_free_in_cxx20.verify.cpp | 83 +++++++++++++++++++
 7 files changed, 173 insertions(+), 37 deletions(-)
 create mode 100644 libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp

diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index 74c7d49c65055..e7aa5d01a27b4 100644
--- a/libcxx/include/__atomic/atomic.h
+++ b/libcxx/include/__atomic/atomic.h
@@ -47,7 +47,7 @@ struct atomic : public __atomic_base<_Tp> {
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     __base::store(__d);
     return __d;
@@ -74,7 +74,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     __base::store(__d);
     return __d;
@@ -85,7 +85,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     // __atomic_fetch_add accepts function pointers, guard against them.
     static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
@@ -99,7 +99,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     // __atomic_fetch_add accepts function pointers, guard against them.
     static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
@@ -114,42 +114,42 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_add(1);
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_sub(1);
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_add(1) + 1;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_sub(1) - 1;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_add(__op) + __op;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
   _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_sub(__op) - __op;
   }
diff --git a/libcxx/include/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h
index 35a6fb00dbc3e..e19f70104a595 100644
--- a/libcxx/include/__atomic/atomic_base.h
+++ b/libcxx/include/__atomic/atomic_base.h
@@ -27,6 +27,12 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER >= 20
+#define _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE requires is_always_lock_free
+#else
+#define _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
+#endif
+
 template <class _Tp, bool = is_integral<_Tp>::value && !is_same<_Tp, bool>::value>
 struct __atomic_base // false
 {
@@ -43,7 +49,7 @@ struct __atomic_base // false
     return static_cast<__atomic_base const volatile*>(this)->is_lock_free();
   }
   _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
     std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
   }
@@ -52,7 +58,7 @@ struct __atomic_base // false
     std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT
-    requires is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
     return std::__cxx_atomic_load(std::addressof(__a_), __m);
   }
@@ -60,10 +66,10 @@ struct __atomic_base // false
       _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
     return std::__cxx_atomic_load(std::addressof(__a_), __m);
   }
-  _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT { return load(); }
+  _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE { return load(); }
   _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); }
   _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);
   }
@@ -72,7 +78,7 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
-    requires is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
@@ -82,7 +88,7 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
-    requires is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
@@ -92,7 +98,7 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
@@ -102,7 +108,7 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
@@ -141,6 +147,11 @@ struct __atomic_base // false
   __atomic_base(const __atomic_base&) = delete;
 };
 
+#if _LIBCPP_STD_VER >= 20
+#undef _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
+#define _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE requires __base::is_always_lock_free
+#endif
+
 // atomic<Integral>
 
 template <class _Tp>
@@ -152,7 +163,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {}
 
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
   }
@@ -162,7 +173,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
   }
@@ -172,7 +183,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);
   }
@@ -182,7 +193,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);
   }
@@ -192,7 +203,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);
   }
@@ -204,7 +215,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_add(_Tp(1));
   }
@@ -212,7 +223,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_sub(_Tp(1));
   }
@@ -220,7 +231,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_add(_Tp(1)) + _Tp(1);
   }
@@ -228,7 +239,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_sub(_Tp(1)) - _Tp(1);
   }
@@ -236,7 +247,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) _NOEXCEPT { return fetch_add(__op) + __op; }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_add(__op) + __op;
   }
@@ -244,7 +255,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_sub(__op) - __op;
   }
@@ -252,7 +263,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) _NOEXCEPT { return fetch_and(__op) & __op; }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_and(__op) & __op;
   }
@@ -260,7 +271,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) _NOEXCEPT { return fetch_or(__op) | __op; }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_or(__op) | __op;
   }
@@ -268,7 +279,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT
-    requires __base::is_always_lock_free
+    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
   {
     return fetch_xor(__op) ^ __op;
   }
diff --git a/libcxx/include/__tuple/tuple_element.h b/libcxx/include/__tuple/tuple_element.h
index bcffc540eaf02..9127c47dc8f1a 100644
--- a/libcxx/include/__tuple/tuple_element.h
+++ b/libcxx/include/__tuple/tuple_element.h
@@ -28,6 +28,16 @@ struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const _Tp> {
   typedef _LIBCPP_NODEBUG const typename tuple_element<_Ip, _Tp>::type type;
 };
 
+template <size_t _Ip, class _Tp>
+struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, volatile _Tp> {
+  typedef _LIBCPP_NODEBUG volatile typename tuple_element<_Ip, _Tp>::type type;
+};
+
+template <size_t _Ip, class _Tp>
+struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const volatile _Tp> {
+  typedef _LIBCPP_NODEBUG const volatile typename tuple_element<_Ip, _Tp>::type type;
+};
+
 #ifndef _LIBCPP_CXX03_LANG
 
 template <size_t _Ip, class... _Types>
diff --git a/libcxx/include/__tuple/tuple_size.h b/libcxx/include/__tuple/tuple_size.h
index 8dc6bfdb828d8..18a17fd4d5878 100644
--- a/libcxx/include/__tuple/tuple_size.h
+++ b/libcxx/include/__tuple/tuple_size.h
@@ -35,6 +35,17 @@ struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp< const _Tp,
                                                                    integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
     : public integral_constant<size_t, tuple_size<_Tp>::value> {};
 
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp< volatile _Tp,
+                                                                   __enable_if_t<!is_const<_Tp>::value>,
+                                                                   integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
+    : public integral_constant<size_t, tuple_size<_Tp>::value> {};
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS
+tuple_size<__enable_if_tuple_size_imp<const volatile _Tp, integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
+    : public integral_constant<size_t, tuple_size<_Tp>::value> {};
+
 #else
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_size<const _Tp> : public tuple_size<_Tp> {};
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 081b90c7bbec5..154f114bfb6d0 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -154,12 +154,21 @@ template <class T, class Tuple>
 template <class T> struct tuple_size; // undefined
 template <class... T> struct tuple_size<tuple<T...>>;
 template <class T>
- inline constexpr size_t tuple_size_v = tuple_size<T>::value; // C++17
+  inline constexpr size_t tuple_size_v = tuple_size<T>::value; // C++17
+
+template <class T> struct tuple_size<const T>;
+template <class T> struct tuple_size<volatile T>;       // Deprecated in C++20
+template <class T> struct tuple_size<const volatile T>; // Deprecated in C++20
+
 template <size_t I, class T> struct tuple_element; // undefined
 template <size_t I, class... T> struct tuple_element<I, tuple<T...>>;
 template <size_t I, class T>
   using tuple_element_t = typename tuple_element <I, T>::type; // C++14
 
+template <size_t I, class T> struct tuple_element<I, const T>;
+template <size_t I, class T> struct tuple_element<I, volatile T>;       // Deprecated in C++20
+template <size_t I, class T> struct tuple_element<I, const volatile T>; // Deprecated in C++20
+
 // 20.4.1.5, element access:
 template <size_t I, class... T>
     typename tuple_element<I, tuple<T...>>::type&
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 94767e482bcca..aadc264f68c8c 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -86,8 +86,8 @@ namespace std {
   inline constexpr size_t variant_size_v = variant_size<T>::value;
 
   template <class T> struct variant_size<const T>;
-  template <class T> struct variant_size<volatile T>;
-  template <class T> struct variant_size<const volatile T>;
+  template <class T> struct variant_size<volatile T>;       // Deprecated in C++20
+  template <class T> struct variant_size<const volatile T>; // Deprecated in C++20
 
   template <class... Types>
   struct variant_size<variant<Types...>>;
@@ -98,8 +98,8 @@ namespace std {
   using variant_alternative_t = typename variant_alternative<I, T>::type;
 
   template <size_t I, class T> struct variant_alternative<I, const T>;
-  template <size_t I, class T> struct variant_alternative<I, volatile T>;
-  template <size_t I, class T> struct variant_alternative<I, const volatile T>;
+  template <size_t I, class T> struct variant_alternative<I, volatile T>;       // Deprecated in C++20
+  template <size_t I, class T> struct variant_alternative<I, const volatile T>; // Deprecated in C++20
 
   template <size_t I, class... Types>
   struct variant_alternative<I, variant<Types...>>;
@@ -317,6 +317,12 @@ inline constexpr size_t variant_size_v = variant_size<_Tp>::value;
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS variant_size<const _Tp> : variant_size<_Tp> {};
 
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS variant_size<volatile _Tp> : variant_size<_Tp> {};
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS variant_size<const volatile _Tp> : variant_size<_Tp> {};
+
 template <class... _Types>
 struct _LIBCPP_TEMPLATE_VIS variant_size<variant<_Types...>> : integral_constant<size_t, sizeof...(_Types)> {};
 
@@ -329,6 +335,12 @@ using variant_alternative_t = typename variant_alternative<_Ip, _Tp>::type;
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const _Tp> : add_const<variant_alternative_t<_Ip, _Tp>> {};
 
+template <size_t _Ip, class _Tp>
+struct _LIBCPP_TEMPLATE_VIS  variant_alternative<_Ip, volatile _Tp> : add_volatile<variant_alternative_t<_Ip, _Tp>> {};
+
+template <size_t _Ip, class _Tp>
+struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const volatile _Tp> : add_cv<variant_alternative_t<_Ip, _Tp>> {};
+
 template <size_t _Ip, class... _Types>
 struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, variant<_Types...>> {
   static_assert(_Ip < sizeof...(_Types), "Index out of bounds in std::variant_alternative<>");
diff --git a/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp b/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp
new file mode 100644
index 0000000000000..9c12125e714ea
--- /dev/null
+++ b/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <atomic>
+
+// UNSUPPORTED: c++03, c++11, c++17
+
+#include <atomic>
+
+struct arr {
+  int x[32];
+  int y;
+
+  void method() {}
+};
+
+void f() {
+  std::memory_order ord = std::memory_order_relaxed;
+
+  int expected = 0, desired = 0;
+  std::atomic<int> i{};
+  i.operator=(0);
+  i.store(0, ord);
+  i.load(ord);
+  i.operator int();
+  i.exchange(0, ord);
+  i.compare_exchange_weak(expected, desired, ord);
+  i.compare_exchange_weak(expected, desired, ord, ord);
+  i.compare_exchange_strong(expected, desired, ord);
+  i.compare_exchange_strong(expected, desired, ord, ord);
+
+  volatile std::atomic<int> vi{};
+  vi.operator=(0);
+  vi.store(0, ord);
+  vi.load(ord);
+  vi.operator int();
+  vi.exchange(0, ord);
+  vi.compare_exchange_weak(expected, desired, ord);
+  vi.compare_exchange_weak(expected, desired, ord, ord);
+  vi.compare_exchange_strong(expected, desired, ord);
+  vi.compare_exchange_strong(expected, desired, ord, ord);
+
+  arr test_value;
+
+  volatile std::atomic<arr> va{};
+  // expected-error at +1 {{call to deleted member function 'operator='}}
+  va.operator=(test_value); 
+  
+  // expected-error at +1 {{no matching member function for call to 'store'}}
+  va.store(test_value, ord);
+  
+  // expected-error at +1 {{no matching member function for call to 'load'}}
+  va.load(ord);
+  
+  // expected-error at +1 {{no matching member function for call to 'operator arr'}}
+  va.operator arr();
+
+  // expected-error at +1 {{no matching member function for call to 'exchange'}}
+  va.exchange(test_value, ord);
+
+  // expected-error at +1 {{no matching member function for call to 'compare_exchange_weak'}}
+  va.compare_exchange_weak(test_value, test_value, ord);
+
+  // expected-error at +1 {{no matching member function for call to 'compare_exchange_weak'}}
+  va.compare_exchange_weak(test_value, test_value, ord, ord);
+
+  // expected-error at +1 {{no matching member function for call to 'compare_exchange_strong'}}
+  va.compare_exchange_strong(test_value, test_value, ord);
+  
+  // expected-error at +1 {{no matching member function for call to 'compare_exchange_strong'}}
+  va.compare_exchange_strong(test_value, test_value, ord, ord);
+
+  void (arr::*fptr)();
+
+  std::atomic<void (arr::*)()> vfp;
+  vfp.store(&test_value.method);
+
+}

>From f0b074a3eef77ddfcc042200bf946a536348b5d0 Mon Sep 17 00:00:00 2001
From: Joshua Karns <jkarns275 at gmail.com>
Date: Sat, 3 Aug 2024 18:18:00 -0400
Subject: [PATCH 4/6] Deprecate volatile atomics w/ static assertion warning

---
 libcxx/include/__atomic/atomic.h              |  57 ++++-----
 libcxx/include/__atomic/atomic_base.h         | 121 +++++++++---------
 ...tile_require_lock_free_in_cxx20.verify.cpp |  34 +++--
 3 files changed, 95 insertions(+), 117 deletions(-)

diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index e7aa5d01a27b4..838dc6017e7c0 100644
--- a/libcxx/include/__atomic/atomic.h
+++ b/libcxx/include/__atomic/atomic.h
@@ -46,9 +46,8 @@ struct atomic : public __atomic_base<_Tp> {
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     __base::store(__d);
     return __d;
   }
@@ -73,9 +72,8 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp*, __base::is_always_lock_free>);
     __base::store(__d);
     return __d;
   }
@@ -84,10 +82,9 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
     return __d;
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
     // __atomic_fetch_add accepts function pointers, guard against them.
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp*, __base::is_always_lock_free>);
     static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
   }
@@ -98,10 +95,9 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
     // __atomic_fetch_add accepts function pointers, guard against them.
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp*, __base::is_always_lock_free>);
     static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
     return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
   }
@@ -113,44 +109,38 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp*, __base::is_always_lock_free>);
     return fetch_add(1);
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp*, __base::is_always_lock_free>);
     return fetch_sub(1);
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp*, __base::is_always_lock_free>);
     return fetch_add(1) + 1;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp*, __base::is_always_lock_free>);
     return fetch_sub(1) - 1;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp*, __base::is_always_lock_free>);
     return fetch_add(__op) + __op;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp*, __base::is_always_lock_free>);
     return fetch_sub(__op) - __op;
   }
 
@@ -303,16 +293,15 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT
 // atomic_init
 
 template <class _Tp>
-_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void
-atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
+_LIBCPP_HIDE_FROM_ABI void atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
   requires __atomic_base<_Tp>::is_always_lock_free
 {
+  static_assert(__deprecated_if_not_awlays_lock_free<_Tp, atomic<_Tp>::__base::is_always_lock_free>);
   std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
 }
 
 template <class _Tp>
-_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void
-atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI void atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
   std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
 }
 
diff --git a/libcxx/include/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h
index e19f70104a595..61c8046fba5fa 100644
--- a/libcxx/include/__atomic/atomic_base.h
+++ b/libcxx/include/__atomic/atomic_base.h
@@ -28,11 +28,18 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 20
-#define _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE requires is_always_lock_free
+#  define _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE                                                                      \
+    [[deprecated("volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false")]]
 #else
-#define _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
+#  define _LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE
 #endif
 
+template <class _Tp, bool always_lock_free>
+constexpr bool __deprecated_if_not_awlays_lock_free = true;
+
+template <class _Tp>
+_LIBCPP_DEPRECATED_NOT_ALWAYS_LOCK_FREE constexpr bool __deprecated_if_not_awlays_lock_free<_Tp, false> = true;
+
 template <class _Tp, bool = is_integral<_Tp>::value && !is_same<_Tp, bool>::value>
 struct __atomic_base // false
 {
@@ -49,8 +56,8 @@ struct __atomic_base // false
     return static_cast<__atomic_base const volatile*>(this)->is_lock_free();
   }
   _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
+      _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, is_always_lock_free>);
     std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT
@@ -58,19 +65,21 @@ struct __atomic_base // false
     std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
+      _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, is_always_lock_free>);
     return std::__cxx_atomic_load(std::addressof(__a_), __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT
       _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
     return std::__cxx_atomic_load(std::addressof(__a_), __m);
   }
-  _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE { return load(); }
+  _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, is_always_lock_free>);
+    return load();
+  }
   _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); }
-  _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, is_always_lock_free>);
     return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
@@ -78,8 +87,8 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
+      _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, is_always_lock_free>);
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
   _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -88,8 +97,8 @@ struct __atomic_base // false
   }
   _LIBCPP_HIDE_FROM_ABI bool
   compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
+      _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, is_always_lock_free>);
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
   _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT
@@ -97,9 +106,8 @@ struct __atomic_base // false
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f);
   }
   _LIBCPP_HIDE_FROM_ABI bool
-  compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, is_always_lock_free>);
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
   _LIBCPP_HIDE_FROM_ABI bool
@@ -107,9 +115,8 @@ struct __atomic_base // false
     return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
   _LIBCPP_HIDE_FROM_ABI bool
-  compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, is_always_lock_free>);
     return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m);
   }
   _LIBCPP_HIDE_FROM_ABI bool
@@ -148,8 +155,8 @@ struct __atomic_base // false
 };
 
 #if _LIBCPP_STD_VER >= 20
-#undef _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-#define _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE requires __base::is_always_lock_free
+#  undef _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
+#  define _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE requires __base::is_always_lock_free
 #endif
 
 // atomic<Integral>
@@ -162,9 +169,8 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {}
 
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
   }
 
@@ -172,9 +178,8 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
     return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
   }
 
@@ -182,9 +187,8 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
     return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);
   }
 
@@ -192,9 +196,8 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
     return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);
   }
 
@@ -202,9 +205,8 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
     return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m);
   }
 
@@ -214,73 +216,64 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return fetch_add(_Tp(1));
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return fetch_sub(_Tp(1));
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return fetch_add(_Tp(1)) + _Tp(1);
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return fetch_sub(_Tp(1)) - _Tp(1);
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) _NOEXCEPT { return fetch_add(__op) + __op; }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return fetch_add(__op) + __op;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return fetch_sub(__op) - __op;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) _NOEXCEPT { return fetch_and(__op) & __op; }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return fetch_and(__op) & __op;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) _NOEXCEPT { return fetch_or(__op) | __op; }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return fetch_or(__op) | __op;
   }
 
   _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT
-    _LIBCPP_REQUIRE_IS_ALWAYS_LOCK_FREE
-  {
+  _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT {
+    static_assert(__deprecated_if_not_awlays_lock_free<_Tp, __base::is_always_lock_free>);
     return fetch_xor(__op) ^ __op;
   }
 };
diff --git a/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp b/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp
index 9c12125e714ea..1fe7760f2386f 100644
--- a/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp
+++ b/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp
@@ -48,36 +48,32 @@ void f() {
   arr test_value;
 
   volatile std::atomic<arr> va{};
-  // expected-error at +1 {{call to deleted member function 'operator='}}
-  va.operator=(test_value); 
-  
-  // expected-error at +1 {{no matching member function for call to 'store'}}
+
+  // expected-warning at __atomic/atomic.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  va.operator=(test_value);
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
   va.store(test_value, ord);
-  
-  // expected-error at +1 {{no matching member function for call to 'load'}}
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
   va.load(ord);
-  
-  // expected-error at +1 {{no matching member function for call to 'operator arr'}}
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
   va.operator arr();
 
-  // expected-error at +1 {{no matching member function for call to 'exchange'}}
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
   va.exchange(test_value, ord);
 
-  // expected-error at +1 {{no matching member function for call to 'compare_exchange_weak'}}
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
   va.compare_exchange_weak(test_value, test_value, ord);
 
-  // expected-error at +1 {{no matching member function for call to 'compare_exchange_weak'}}
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
   va.compare_exchange_weak(test_value, test_value, ord, ord);
 
-  // expected-error at +1 {{no matching member function for call to 'compare_exchange_strong'}}
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
   va.compare_exchange_strong(test_value, test_value, ord);
-  
-  // expected-error at +1 {{no matching member function for call to 'compare_exchange_strong'}}
-  va.compare_exchange_strong(test_value, test_value, ord, ord);
-
-  void (arr::*fptr)();
 
-  std::atomic<void (arr::*)()> vfp;
-  vfp.store(&test_value.method);
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  va.compare_exchange_strong(test_value, test_value, ord, ord);
 
 }

>From 32568cfbf5472ed91ff83b0b84dfb8f5e12f0f87 Mon Sep 17 00:00:00 2001
From: Joshua Karns <jkarns275 at gmail.com>
Date: Sun, 4 Aug 2024 03:07:21 -0400
Subject: [PATCH 5/6] Tests and warnings for tuple and variant

---
 libcxx/include/__tuple/tuple_element.h        | 10 ++++++
 libcxx/include/__tuple/tuple_size.h           | 16 ++++++++--
 libcxx/include/variant                        | 24 +++++++++++---
 ...tile_require_lock_free_in_cxx20.verify.cpp | 28 +++++++++++++++++
 ...ple_element_deprecated_in_cxx20.verify.cpp | 21 +++++++++++++
 ..._tuple_size_deprecated_in_cxx20.verify.cpp | 21 +++++++++++++
 .../volatile_deprecated.verify.cpp            | 31 +++++++++++++++++++
 7 files changed, 145 insertions(+), 6 deletions(-)
 create mode 100644 libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_element_deprecated_in_cxx20.verify.cpp
 create mode 100644 libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_size_deprecated_in_cxx20.verify.cpp
 create mode 100644 libcxx/test/libcxx/utilities/variant/variant.variant/variant.helper/volatile_deprecated.verify.cpp

diff --git a/libcxx/include/__tuple/tuple_element.h b/libcxx/include/__tuple/tuple_element.h
index 9127c47dc8f1a..eec29613d9bcb 100644
--- a/libcxx/include/__tuple/tuple_element.h
+++ b/libcxx/include/__tuple/tuple_element.h
@@ -20,6 +20,14 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+template <class _Tp, bool _cxx20 = _LIBCPP_STD_VER >= 20>
+_LIBCPP_HIDE_FROM_ABI constexpr bool __volatile_tuple_element_deprecated = true;
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX20 constexpr bool __volatile_tuple_element_deprecated<_Tp, true> = true;
+
+#define _LIBCPP_VOLATILE_TUPLE_ELEMENT_DEPRECATED_WARNING static_assert(__volatile_tuple_element_deprecated<_Tp>)
+
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_element;
 
@@ -30,11 +38,13 @@ struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const _Tp> {
 
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, volatile _Tp> {
+  _LIBCPP_VOLATILE_TUPLE_ELEMENT_DEPRECATED_WARNING;
   typedef _LIBCPP_NODEBUG volatile typename tuple_element<_Ip, _Tp>::type type;
 };
 
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const volatile _Tp> {
+  _LIBCPP_VOLATILE_TUPLE_ELEMENT_DEPRECATED_WARNING;
   typedef _LIBCPP_NODEBUG const volatile typename tuple_element<_Ip, _Tp>::type type;
 };
 
diff --git a/libcxx/include/__tuple/tuple_size.h b/libcxx/include/__tuple/tuple_size.h
index 18a17fd4d5878..2ed5fbe6227fa 100644
--- a/libcxx/include/__tuple/tuple_size.h
+++ b/libcxx/include/__tuple/tuple_size.h
@@ -22,6 +22,14 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+template <class _Tp, bool _cxx20 = _LIBCPP_STD_VER >= 20>
+_LIBCPP_HIDE_FROM_ABI constexpr bool __volatile_tuple_size_deprecated = true;
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX20 constexpr bool __volatile_tuple_size_deprecated<_Tp, true> = true;
+
+#define _LIBCPP_VOLATILE_TUPLE_SIZE_DEPRECATED_WARNING static_assert(__volatile_tuple_size_deprecated<_Tp>)
+
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_size;
 
@@ -39,12 +47,16 @@ template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp< volatile _Tp,
                                                                    __enable_if_t<!is_const<_Tp>::value>,
                                                                    integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
-    : public integral_constant<size_t, tuple_size<_Tp>::value> {};
+    : public integral_constant<size_t, tuple_size<_Tp>::value> {
+  _LIBCPP_VOLATILE_TUPLE_SIZE_DEPRECATED_WARNING;
+};
 
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS
 tuple_size<__enable_if_tuple_size_imp<const volatile _Tp, integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
-    : public integral_constant<size_t, tuple_size<_Tp>::value> {};
+    : public integral_constant<size_t, tuple_size<_Tp>::value> {
+  _LIBCPP_VOLATILE_TUPLE_SIZE_DEPRECATED_WARNING;
+};
 
 #else
 template <class _Tp>
diff --git a/libcxx/include/variant b/libcxx/include/variant
index aadc264f68c8c..beb524b01a7ae 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -305,6 +305,14 @@ __throw_bad_variant_access() {
 #  endif
 }
 
+template <class _Tp, bool _cxx20 = _LIBCPP_STD_VER >= 20>
+_LIBCPP_HIDE_FROM_ABI constexpr bool __volatile_variant_deprecated = true;
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX20 constexpr bool __volatile_variant_deprecated<_Tp, true> = true;
+
+#define _LIBCPP_VOLATILE_VARIANT_DEPRECATED_WARNING static_assert(__volatile_variant_deprecated<_Tp>)
+
 template <class... _Types>
 class _LIBCPP_TEMPLATE_VIS variant;
 
@@ -318,10 +326,14 @@ template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS variant_size<const _Tp> : variant_size<_Tp> {};
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS variant_size<volatile _Tp> : variant_size<_Tp> {};
+struct _LIBCPP_TEMPLATE_VIS variant_size<volatile _Tp> : variant_size<_Tp> {
+  _LIBCPP_VOLATILE_VARIANT_DEPRECATED_WARNING;
+};
 
 template <class _Tp>
-struct _LIBCPP_TEMPLATE_VIS variant_size<const volatile _Tp> : variant_size<_Tp> {};
+struct _LIBCPP_TEMPLATE_VIS variant_size<const volatile _Tp> : variant_size<_Tp> {
+  _LIBCPP_VOLATILE_VARIANT_DEPRECATED_WARNING;
+};
 
 template <class... _Types>
 struct _LIBCPP_TEMPLATE_VIS variant_size<variant<_Types...>> : integral_constant<size_t, sizeof...(_Types)> {};
@@ -336,10 +348,14 @@ template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const _Tp> : add_const<variant_alternative_t<_Ip, _Tp>> {};
 
 template <size_t _Ip, class _Tp>
-struct _LIBCPP_TEMPLATE_VIS  variant_alternative<_Ip, volatile _Tp> : add_volatile<variant_alternative_t<_Ip, _Tp>> {};
+struct _LIBCPP_TEMPLATE_VIS  variant_alternative<_Ip, volatile _Tp> : add_volatile<variant_alternative_t<_Ip, _Tp>> {
+  _LIBCPP_VOLATILE_VARIANT_DEPRECATED_WARNING;
+};
 
 template <size_t _Ip, class _Tp>
-struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const volatile _Tp> : add_cv<variant_alternative_t<_Ip, _Tp>> {};
+struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const volatile _Tp> : add_cv<variant_alternative_t<_Ip, _Tp>> {
+  _LIBCPP_VOLATILE_VARIANT_DEPRECATED_WARNING;
+};
 
 template <size_t _Ip, class... _Types>
 struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, variant<_Types...>> {
diff --git a/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp b/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp
index 1fe7760f2386f..113f6e8bbf040 100644
--- a/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp
+++ b/libcxx/test/libcxx/atomics/atomics.types.operations/atomic_volatile_require_lock_free_in_cxx20.verify.cpp
@@ -76,4 +76,32 @@ void f() {
   // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
   va.compare_exchange_strong(test_value, test_value, ord, ord);
 
+  const volatile std::atomic<arr> cva{};
+
+  // expected-warning at __atomic/atomic.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  cva.operator=(test_value);
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  cva.store(test_value, ord);
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  cva.load(ord);
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  cva.operator arr();
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  cva.exchange(test_value, ord);
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  cva.compare_exchange_weak(test_value, test_value, ord);
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  cva.compare_exchange_weak(test_value, test_value, ord, ord);
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  cva.compare_exchange_strong(test_value, test_value, ord);
+
+  // expected-warning at __atomic/atomic_base.h:* {{'__deprecated_if_not_awlays_lock_free<arr, false>' is deprecated: volatile atomic operations are deprecated when std::atomic<T>::is_always_lock_free is false}}
+  cva.compare_exchange_strong(test_value, test_value, ord, ord);
 }
diff --git a/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_element_deprecated_in_cxx20.verify.cpp b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_element_deprecated_in_cxx20.verify.cpp
new file mode 100644
index 0000000000000..97b30e66abe43
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_element_deprecated_in_cxx20.verify.cpp
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// UNSUPPORTED: c++03, c++11, c++17
+
+#include <tuple>
+
+[[maybe_unused]] std::tuple_element<0, std::tuple<void, void>> test;
+
+// expected-warning at __tuple/tuple_element.h:* {{'__volatile_tuple_element_deprecated<std::tuple<void, void>>' is deprecated}}
+[[maybe_unused]] std::tuple_element<0, volatile std::tuple<void, void>> vol_test;
+
+// expected-warning at __tuple/tuple_element.h:* {{'__volatile_tuple_element_deprecated<std::tuple<void, void>>' is deprecated}}
+[[maybe_unused]] std::tuple_element<0, const volatile std::tuple<void, void>> const_vol_test;
diff --git a/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_size_deprecated_in_cxx20.verify.cpp b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_size_deprecated_in_cxx20.verify.cpp
new file mode 100644
index 0000000000000..b9a9bcb8baf03
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_size_deprecated_in_cxx20.verify.cpp
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <tuple>
+
+// UNSUPPORTED: c++03, c++11, c++17
+
+#include <tuple>
+
+[[maybe_unused]] std::tuple_size<std::tuple<void, void>> test;
+
+// expected-warning at __tuple/tuple_size.h:* {{'__volatile_tuple_size_deprecated<std::tuple<void, void>>' is deprecated}}
+[[maybe_unused]] std::tuple_size<volatile std::tuple<void, void>> vol_test;
+
+// expected-warning at __tuple/tuple_size.h:* {{'__volatile_tuple_size_deprecated<std::tuple<void, void>>' is deprecated}}
+[[maybe_unused]] std::tuple_size<const volatile std::tuple<void, void>> const_vol_test;
diff --git a/libcxx/test/libcxx/utilities/variant/variant.variant/variant.helper/volatile_deprecated.verify.cpp b/libcxx/test/libcxx/utilities/variant/variant.variant/variant.helper/volatile_deprecated.verify.cpp
new file mode 100644
index 0000000000000..e054f906eec88
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/variant/variant.variant/variant.helper/volatile_deprecated.verify.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <variant>
+
+// UNSUPPORTED: c++03, c++11, c++17
+
+#include <variant>
+
+typedef std::variant<void, int> vars;
+
+[[maybe_unused]] std::variant_alternative<0, vars> alt_test;
+
+// expected-warning at variant:* {{'__volatile_variant_deprecated<std::variant<void, int>>' is deprecated}}
+[[maybe_unused]] std::variant_alternative<0, volatile vars> vol_alt_test;
+
+// expected-warning at variant:* {{'__volatile_variant_deprecated<std::variant<void, int>>' is deprecated}}
+[[maybe_unused]] std::variant_alternative<0, const volatile vars> const_vol_alt_test;
+
+[[maybe_unused]] std::variant_size<vars> size_test;
+
+// expected-warning at variant:* {{'__volatile_variant_deprecated<std::variant<void, int>>' is deprecated}}
+[[maybe_unused]] std::variant_size<volatile vars> vol_size_test;
+
+// expected-warning at variant:* {{'__volatile_variant_deprecated<std::variant<void, int>>' is deprecated}}
+[[maybe_unused]] std::variant_size<const volatile vars> const_vol_size_test;

>From bbb636b4ee3031d7a62eaa46e2d86c2df50521db Mon Sep 17 00:00:00 2001
From: Joshua Karns <jkarns275 at gmail.com>
Date: Sun, 4 Aug 2024 04:18:53 -0400
Subject: [PATCH 6/6] Update atomic synopses, move warning field to __config

---
 libcxx/include/__config                       |   8 +
 libcxx/include/__tuple/tuple_element.h        |  12 +-
 libcxx/include/__tuple/tuple_size.h           |  12 +-
 libcxx/include/atomic                         | 188 ++++++++++++------
 libcxx/include/tuple                          |  10 +-
 libcxx/include/variant                        |  20 +-
 ...ple_element_deprecated_in_cxx20.verify.cpp |   4 +-
 ..._tuple_size_deprecated_in_cxx20.verify.cpp |   4 +-
 .../volatile_deprecated.verify.cpp            |   8 +-
 9 files changed, 160 insertions(+), 106 deletions(-)

diff --git a/libcxx/include/__config b/libcxx/include/__config
index 392053a64a8dc..0b9bffe1f3a1c 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -741,6 +741,14 @@ typedef __char32_t char32_t;
 #    define _LIBCPP_DEPRECATED_WITH_CHAR8_T
 #  endif
 
+// P1831R1 deprecated many uses of volatile, but the way attributes work with template specializations require this work-around to always raise a warning.
+template <class _Tp, bool _cxx20 = _LIBCPP_STD_VER >= 20>
+_LIBCPP_HIDE_FROM_ABI constexpr bool __volatile_deprecated_since_cxx20_warning = true;
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX20 constexpr bool __volatile_deprecated_since_cxx20_warning<_Tp, true> = true;
+#  define _LIBCPP_VOLATILE_DEPRECATED_WARNING static_assert(__volatile_deprecated_since_cxx20_warning<volatile _Tp>)
+#  define _LIBCPP_CONST_VOLATILE_DEPRECATED_WARNING static_assert(__volatile_deprecated_since_cxx20_warning<const volatile _Tp>)
+
 // Macros to enter and leave a state where deprecation warnings are suppressed.
 #  if defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_COMPILER_GCC)
 #    define _LIBCPP_SUPPRESS_DEPRECATED_PUSH                                                                           \
diff --git a/libcxx/include/__tuple/tuple_element.h b/libcxx/include/__tuple/tuple_element.h
index eec29613d9bcb..fb67eeedba8ff 100644
--- a/libcxx/include/__tuple/tuple_element.h
+++ b/libcxx/include/__tuple/tuple_element.h
@@ -20,14 +20,6 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _Tp, bool _cxx20 = _LIBCPP_STD_VER >= 20>
-_LIBCPP_HIDE_FROM_ABI constexpr bool __volatile_tuple_element_deprecated = true;
-
-template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX20 constexpr bool __volatile_tuple_element_deprecated<_Tp, true> = true;
-
-#define _LIBCPP_VOLATILE_TUPLE_ELEMENT_DEPRECATED_WARNING static_assert(__volatile_tuple_element_deprecated<_Tp>)
-
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_element;
 
@@ -38,13 +30,13 @@ struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const _Tp> {
 
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, volatile _Tp> {
-  _LIBCPP_VOLATILE_TUPLE_ELEMENT_DEPRECATED_WARNING;
+  _LIBCPP_VOLATILE_DEPRECATED_WARNING;
   typedef _LIBCPP_NODEBUG volatile typename tuple_element<_Ip, _Tp>::type type;
 };
 
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const volatile _Tp> {
-  _LIBCPP_VOLATILE_TUPLE_ELEMENT_DEPRECATED_WARNING;
+  _LIBCPP_CONST_VOLATILE_DEPRECATED_WARNING;
   typedef _LIBCPP_NODEBUG const volatile typename tuple_element<_Ip, _Tp>::type type;
 };
 
diff --git a/libcxx/include/__tuple/tuple_size.h b/libcxx/include/__tuple/tuple_size.h
index 2ed5fbe6227fa..3147c8a4b5ce4 100644
--- a/libcxx/include/__tuple/tuple_size.h
+++ b/libcxx/include/__tuple/tuple_size.h
@@ -22,14 +22,6 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _Tp, bool _cxx20 = _LIBCPP_STD_VER >= 20>
-_LIBCPP_HIDE_FROM_ABI constexpr bool __volatile_tuple_size_deprecated = true;
-
-template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX20 constexpr bool __volatile_tuple_size_deprecated<_Tp, true> = true;
-
-#define _LIBCPP_VOLATILE_TUPLE_SIZE_DEPRECATED_WARNING static_assert(__volatile_tuple_size_deprecated<_Tp>)
-
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS tuple_size;
 
@@ -48,14 +40,14 @@ struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp< volatile _Tp,
                                                                    __enable_if_t<!is_const<_Tp>::value>,
                                                                    integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
     : public integral_constant<size_t, tuple_size<_Tp>::value> {
-  _LIBCPP_VOLATILE_TUPLE_SIZE_DEPRECATED_WARNING;
+  _LIBCPP_VOLATILE_DEPRECATED_WARNING;
 };
 
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS
 tuple_size<__enable_if_tuple_size_imp<const volatile _Tp, integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
     : public integral_constant<size_t, tuple_size<_Tp>::value> {
-  _LIBCPP_VOLATILE_TUPLE_SIZE_DEPRECATED_WARNING;
+  _LIBCPP_CONST_VOLATILE_DEPRECATED_WARNING;
 };
 
 #else
diff --git a/libcxx/include/atomic b/libcxx/include/atomic
index 772ac998615a9..8c9e21273fd20 100644
--- a/libcxx/include/atomic
+++ b/libcxx/include/atomic
@@ -74,30 +74,39 @@ struct atomic
     atomic& operator=(const atomic&) = delete;
     atomic& operator=(const atomic&) volatile = delete;
 
-    T load(memory_order m = memory_order_seq_cst) const volatile noexcept;
+    T load(memory_order m = memory_order_seq_cst) const volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     T load(memory_order m = memory_order_seq_cst) const noexcept;
-    operator T() const volatile noexcept;
+    operator T() const volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     operator T() const noexcept;
-    void store(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;
+    void store(T desr, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     void store(T desr, memory_order m = memory_order_seq_cst) noexcept;
-    T operator=(T) volatile noexcept;
+    T operator=(T) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     T operator=(T) noexcept;
 
-    T exchange(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;
+    T exchange(T desr, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     T exchange(T desr, memory_order m = memory_order_seq_cst) noexcept;
     bool compare_exchange_weak(T& expc, T desr,
-                               memory_order s, memory_order f) volatile noexcept;
+                               memory_order s, memory_order f) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     bool compare_exchange_weak(T& expc, T desr, memory_order s, memory_order f) noexcept;
     bool compare_exchange_strong(T& expc, T desr,
-                                 memory_order s, memory_order f) volatile noexcept;
+                                 memory_order s, memory_order f) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     bool compare_exchange_strong(T& expc, T desr,
-                                 memory_order s, memory_order f) noexcept;
+                                 memory_order s, memory_order f) noexcept
     bool compare_exchange_weak(T& expc, T desr,
-                               memory_order m = memory_order_seq_cst) volatile noexcept;
+                               memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     bool compare_exchange_weak(T& expc, T desr,
                                memory_order m = memory_order_seq_cst) noexcept;
     bool compare_exchange_strong(T& expc, T desr,
-                                memory_order m = memory_order_seq_cst) volatile noexcept;
+                                memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     bool compare_exchange_strong(T& expc, T desr,
                                  memory_order m = memory_order_seq_cst) noexcept;
 
@@ -125,63 +134,85 @@ struct atomic<integral>
     atomic& operator=(const atomic&) = delete;
     atomic& operator=(const atomic&) volatile = delete;
 
-    integral load(memory_order m = memory_order_seq_cst) const volatile noexcept;
+    integral load(memory_order m = memory_order_seq_cst) const volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral load(memory_order m = memory_order_seq_cst) const noexcept;
     operator integral() const volatile noexcept;
     operator integral() const noexcept;
-    void store(integral desr, memory_order m = memory_order_seq_cst) volatile noexcept;
+    void store(integral desr, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     void store(integral desr, memory_order m = memory_order_seq_cst) noexcept;
-    integral operator=(integral desr) volatile noexcept;
+    integral operator=(integral desr) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator=(integral desr) noexcept;
 
     integral exchange(integral desr,
-                      memory_order m = memory_order_seq_cst) volatile noexcept;
+                      memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral exchange(integral desr, memory_order m = memory_order_seq_cst) noexcept;
     bool compare_exchange_weak(integral& expc, integral desr,
-                               memory_order s, memory_order f) volatile noexcept;
+                               memory_order s, memory_order f) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     bool compare_exchange_weak(integral& expc, integral desr,
                                memory_order s, memory_order f) noexcept;
     bool compare_exchange_strong(integral& expc, integral desr,
-                                 memory_order s, memory_order f) volatile noexcept;
+                                 memory_order s, memory_order f) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     bool compare_exchange_strong(integral& expc, integral desr,
                                  memory_order s, memory_order f) noexcept;
     bool compare_exchange_weak(integral& expc, integral desr,
-                               memory_order m = memory_order_seq_cst) volatile noexcept;
+                               memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     bool compare_exchange_weak(integral& expc, integral desr,
                                memory_order m = memory_order_seq_cst) noexcept;
     bool compare_exchange_strong(integral& expc, integral desr,
-                                memory_order m = memory_order_seq_cst) volatile noexcept;
+                                memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     bool compare_exchange_strong(integral& expc, integral desr,
                                  memory_order m = memory_order_seq_cst) noexcept;
 
-    integral fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
+    integral fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral fetch_add(integral op, memory_order m = memory_order_seq_cst) noexcept;
-    integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
+    integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral fetch_sub(integral op, memory_order m = memory_order_seq_cst) noexcept;
-    integral fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
+    integral fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral fetch_and(integral op, memory_order m = memory_order_seq_cst) noexcept;
-    integral fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
+    integral fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral fetch_or(integral op, memory_order m = memory_order_seq_cst) noexcept;
-    integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile noexcept;
+    integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral fetch_xor(integral op, memory_order m = memory_order_seq_cst) noexcept;
 
-    integral operator++(int) volatile noexcept;
+    integral operator++(int) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator++(int) noexcept;
-    integral operator--(int) volatile noexcept;
+    integral operator--(int) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator--(int) noexcept;
-    integral operator++() volatile noexcept;
+    integral operator++() volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator++() noexcept;
-    integral operator--() volatile noexcept;
+    integral operator--() volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator--() noexcept;
-    integral operator+=(integral op) volatile noexcept;
+    integral operator+=(integral op) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator+=(integral op) noexcept;
-    integral operator-=(integral op) volatile noexcept;
+    integral operator-=(integral op) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator-=(integral op) noexcept;
-    integral operator&=(integral op) volatile noexcept;
+    integral operator&=(integral op) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator&=(integral op) noexcept;
-    integral operator|=(integral op) volatile noexcept;
+    integral operator|=(integral op) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator|=(integral op) noexcept;
-    integral operator^=(integral op) volatile noexcept;
+    integral operator^=(integral op) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                  // constraint since C++20
     integral operator^=(integral op) noexcept;
 
     void wait(integral, memory_order = memory_order::seq_cst) const volatile noexcept; // since C++20
@@ -209,49 +240,66 @@ struct atomic<T*>
     atomic& operator=(const atomic&) = delete;
     atomic& operator=(const atomic&) volatile = delete;
 
-    T* load(memory_order m = memory_order_seq_cst) const volatile noexcept;
+    T* load(memory_order m = memory_order_seq_cst) const volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* load(memory_order m = memory_order_seq_cst) const noexcept;
-    operator T*() const volatile noexcept;
+    operator T*() const volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     operator T*() const noexcept;
-    void store(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept;
+    void store(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     void store(T* desr, memory_order m = memory_order_seq_cst) noexcept;
-    T* operator=(T*) volatile noexcept;
+    T* operator=(T*) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* operator=(T*) noexcept;
 
-    T* exchange(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept;
+    T* exchange(T* desr, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* exchange(T* desr, memory_order m = memory_order_seq_cst) noexcept;
     bool compare_exchange_weak(T*& expc, T* desr,
-                               memory_order s, memory_order f) volatile noexcept;
+                               memory_order s, memory_order f) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     bool compare_exchange_weak(T*& expc, T* desr,
                                memory_order s, memory_order f) noexcept;
     bool compare_exchange_strong(T*& expc, T* desr,
-                                 memory_order s, memory_order f) volatile noexcept;
+                                 memory_order s, memory_order f) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     bool compare_exchange_strong(T*& expc, T* desr,
                                  memory_order s, memory_order f) noexcept;
     bool compare_exchange_weak(T*& expc, T* desr,
-                               memory_order m = memory_order_seq_cst) volatile noexcept;
+                               memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     bool compare_exchange_weak(T*& expc, T* desr,
                                memory_order m = memory_order_seq_cst) noexcept;
     bool compare_exchange_strong(T*& expc, T* desr,
-                                memory_order m = memory_order_seq_cst) volatile noexcept;
+                                memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     bool compare_exchange_strong(T*& expc, T* desr,
                                  memory_order m = memory_order_seq_cst) noexcept;
-    T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept;
+    T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* fetch_add(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept;
-    T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept;
+    T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* fetch_sub(ptrdiff_t op, memory_order m = memory_order_seq_cst) noexcept;
 
-    T* operator++(int) volatile noexcept;
+    T* operator++(int) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* operator++(int) noexcept;
-    T* operator--(int) volatile noexcept;
+    T* operator--(int) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* operator--(int) noexcept;
-    T* operator++() volatile noexcept;
+    T* operator++() volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* operator++() noexcept;
-    T* operator--() volatile noexcept;
+    T* operator--() volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* operator--() noexcept;
-    T* operator+=(ptrdiff_t op) volatile noexcept;
+    T* operator+=(ptrdiff_t op) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* operator+=(ptrdiff_t op) noexcept;
-    T* operator-=(ptrdiff_t op) volatile noexcept;
+    T* operator-=(ptrdiff_t op) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
     T* operator-=(ptrdiff_t op) noexcept;
 
     void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; // since C++20
@@ -277,48 +325,61 @@ struct atomic<floating-point-type> {  // since C++20
   atomic& operator=(const atomic&) = delete;
   atomic& operator=(const atomic&) volatile = delete;
 
-  void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept;
+  void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept;
-  floating-point-type operator=(floating-point-type) volatile noexcept;
+  floating-point-type operator=(floating-point-type) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   floating-point-type operator=(floating-point-type) noexcept;
-  floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept;
+  floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   floating-point-type load(memory_order = memory_order::seq_cst) noexcept;
-  operator floating-point-type() volatile noexcept;
+  operator floating-point-type() volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   operator floating-point-type() noexcept;
 
   floating-point-type exchange(floating-point-type,
-                               memory_order = memory_order::seq_cst) volatile noexcept;
+                               memory_order = memory_order::seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   floating-point-type exchange(floating-point-type,
                                memory_order = memory_order::seq_cst) noexcept;
   bool compare_exchange_weak(floating-point-type&, floating-point-type,
-                             memory_order, memory_order) volatile noexcept;
+                             memory_order, memory_order) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   bool compare_exchange_weak(floating-point-type&, floating-point-type,
                              memory_order, memory_order) noexcept;
   bool compare_exchange_strong(floating-point-type&, floating-point-type,
-                               memory_order, memory_order) volatile noexcept;
+                               memory_order, memory_order) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   bool compare_exchange_strong(floating-point-type&, floating-point-type,
                                memory_order, memory_order) noexcept;
   bool compare_exchange_weak(floating-point-type&, floating-point-type,
-                             memory_order = memory_order::seq_cst) volatile noexcept;
+                             memory_order = memory_order::seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   bool compare_exchange_weak(floating-point-type&, floating-point-type,
                              memory_order = memory_order::seq_cst) noexcept;
   bool compare_exchange_strong(floating-point-type&, floating-point-type,
-                               memory_order = memory_order::seq_cst) volatile noexcept;
+                               memory_order = memory_order::seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   bool compare_exchange_strong(floating-point-type&, floating-point-type,
                                memory_order = memory_order::seq_cst) noexcept;
 
   floating-point-type fetch_add(floating-point-type,
-                                memory_order = memory_order::seq_cst) volatile noexcept;
+                                memory_order = memory_order::seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   floating-point-type fetch_add(floating-point-type,
                                 memory_order = memory_order::seq_cst) noexcept;
   floating-point-type fetch_sub(floating-point-type,
-                                memory_order = memory_order::seq_cst) volatile noexcept;
+                                memory_order = memory_order::seq_cst) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   floating-point-type fetch_sub(floating-point-type,
                                 memory_order = memory_order::seq_cst) noexcept;
 
-  floating-point-type operator+=(floating-point-type) volatile noexcept;
+  floating-point-type operator+=(floating-point-type) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   floating-point-type operator+=(floating-point-type) noexcept;
-  floating-point-type operator-=(floating-point-type) volatile noexcept;
+  floating-point-type operator-=(floating-point-type) volatile noexcept
+      requires atomic<T>::is_always_lock_free;                                   // constraint since C++20
   floating-point-type operator-=(floating-point-type) noexcept;
 
   void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept; // since C++20
@@ -574,7 +635,8 @@ void atomic_signal_fence(memory_order m) noexcept;
 // deprecated
 
 template <class T>
-  void atomic_init(volatile atomic<T>* obj, atomic<T>::value_type desr) noexcept;
+  void atomic_init(volatile atomic<T>* obj, atomic<T>::value_type desr) noexcept
+    requires atomic<T>::is_always_lock_free;                                     // constraint since C++20
 
 template <class T>
   void atomic_init(atomic<T>* obj, atomic<T>::value_type desr) noexcept;
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 154f114bfb6d0..46b7b70bf6b13 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -132,7 +132,7 @@ tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>;       // since C++
 template <class Alloc, class ...T>
 tuple(allocator_arg_t, Alloc, tuple<T...>) -> tuple<T...>;          // since C++17
 
-struct ignore-type { // exposition only                             // Since C++26
+struct ignore-type { // exposition only                             // since C++26
   constexpr const ignore-type&
     operator=(const auto &) const noexcept
       { return *this; }
@@ -157,8 +157,8 @@ template <class T>
   inline constexpr size_t tuple_size_v = tuple_size<T>::value; // C++17
 
 template <class T> struct tuple_size<const T>;
-template <class T> struct tuple_size<volatile T>;       // Deprecated in C++20
-template <class T> struct tuple_size<const volatile T>; // Deprecated in C++20
+template <class T> struct tuple_size<volatile T>;       // deprecated in C++20
+template <class T> struct tuple_size<const volatile T>; // deprecated in C++20
 
 template <size_t I, class T> struct tuple_element; // undefined
 template <size_t I, class... T> struct tuple_element<I, tuple<T...>>;
@@ -166,8 +166,8 @@ template <size_t I, class T>
   using tuple_element_t = typename tuple_element <I, T>::type; // C++14
 
 template <size_t I, class T> struct tuple_element<I, const T>;
-template <size_t I, class T> struct tuple_element<I, volatile T>;       // Deprecated in C++20
-template <size_t I, class T> struct tuple_element<I, const volatile T>; // Deprecated in C++20
+template <size_t I, class T> struct tuple_element<I, volatile T>;       // deprecated in C++20
+template <size_t I, class T> struct tuple_element<I, const volatile T>; // deprecated in C++20
 
 // 20.4.1.5, element access:
 template <size_t I, class... T>
diff --git a/libcxx/include/variant b/libcxx/include/variant
index beb524b01a7ae..6da80a83f341b 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -74,9 +74,9 @@ namespace std {
 
     // [variant.visit], visitation
     template<class Self, class Visitor>
-      constexpr decltype(auto) visit(this Self&&, Visitor&&); // Since C++26
+      constexpr decltype(auto) visit(this Self&&, Visitor&&); // since C++26
     template<class R, class Self, class Visitor>
-      constexpr R visit(this Self&&, Visitor&&);              // Since C++26
+      constexpr R visit(this Self&&, Visitor&&);              // since C++26
   };
 
   // 20.7.3, variant helper classes
@@ -86,8 +86,8 @@ namespace std {
   inline constexpr size_t variant_size_v = variant_size<T>::value;
 
   template <class T> struct variant_size<const T>;
-  template <class T> struct variant_size<volatile T>;       // Deprecated in C++20
-  template <class T> struct variant_size<const volatile T>; // Deprecated in C++20
+  template <class T> struct variant_size<volatile T>;       // deprecated in C++20
+  template <class T> struct variant_size<const volatile T>; // deprecated in C++20
 
   template <class... Types>
   struct variant_size<variant<Types...>>;
@@ -98,8 +98,8 @@ namespace std {
   using variant_alternative_t = typename variant_alternative<I, T>::type;
 
   template <size_t I, class T> struct variant_alternative<I, const T>;
-  template <size_t I, class T> struct variant_alternative<I, volatile T>;       // Deprecated in C++20
-  template <size_t I, class T> struct variant_alternative<I, const volatile T>; // Deprecated in C++20
+  template <size_t I, class T> struct variant_alternative<I, volatile T>;       // deprecated in C++20
+  template <size_t I, class T> struct variant_alternative<I, const volatile T>; // deprecated in C++20
 
   template <size_t I, class... Types>
   struct variant_alternative<I, variant<Types...>>;
@@ -327,12 +327,12 @@ struct _LIBCPP_TEMPLATE_VIS variant_size<const _Tp> : variant_size<_Tp> {};
 
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS variant_size<volatile _Tp> : variant_size<_Tp> {
-  _LIBCPP_VOLATILE_VARIANT_DEPRECATED_WARNING;
+  _LIBCPP_VOLATILE_DEPRECATED_WARNING;
 };
 
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS variant_size<const volatile _Tp> : variant_size<_Tp> {
-  _LIBCPP_VOLATILE_VARIANT_DEPRECATED_WARNING;
+  _LIBCPP_CONST_VOLATILE_DEPRECATED_WARNING;
 };
 
 template <class... _Types>
@@ -349,12 +349,12 @@ struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const _Tp> : add_const<vari
 
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS  variant_alternative<_Ip, volatile _Tp> : add_volatile<variant_alternative_t<_Ip, _Tp>> {
-  _LIBCPP_VOLATILE_VARIANT_DEPRECATED_WARNING;
+  _LIBCPP_VOLATILE_DEPRECATED_WARNING;
 };
 
 template <size_t _Ip, class _Tp>
 struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, const volatile _Tp> : add_cv<variant_alternative_t<_Ip, _Tp>> {
-  _LIBCPP_VOLATILE_VARIANT_DEPRECATED_WARNING;
+  _LIBCPP_CONST_VOLATILE_DEPRECATED_WARNING;
 };
 
 template <size_t _Ip, class... _Types>
diff --git a/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_element_deprecated_in_cxx20.verify.cpp b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_element_deprecated_in_cxx20.verify.cpp
index 97b30e66abe43..43475dd6af811 100644
--- a/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_element_deprecated_in_cxx20.verify.cpp
+++ b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_element_deprecated_in_cxx20.verify.cpp
@@ -14,8 +14,8 @@
 
 [[maybe_unused]] std::tuple_element<0, std::tuple<void, void>> test;
 
-// expected-warning at __tuple/tuple_element.h:* {{'__volatile_tuple_element_deprecated<std::tuple<void, void>>' is deprecated}}
+// expected-warning at __tuple/tuple_element.h:* {{'__volatile_deprecated_since_cxx20_warning<volatile std::tuple<void, void>>' is deprecated}}
 [[maybe_unused]] std::tuple_element<0, volatile std::tuple<void, void>> vol_test;
 
-// expected-warning at __tuple/tuple_element.h:* {{'__volatile_tuple_element_deprecated<std::tuple<void, void>>' is deprecated}}
+// expected-warning at __tuple/tuple_element.h:* {{'__volatile_deprecated_since_cxx20_warning<const volatile std::tuple<void, void>>' is deprecated}}
 [[maybe_unused]] std::tuple_element<0, const volatile std::tuple<void, void>> const_vol_test;
diff --git a/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_size_deprecated_in_cxx20.verify.cpp b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_size_deprecated_in_cxx20.verify.cpp
index b9a9bcb8baf03..0d562aba68f66 100644
--- a/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_size_deprecated_in_cxx20.verify.cpp
+++ b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.helper/volatile_tuple_size_deprecated_in_cxx20.verify.cpp
@@ -14,8 +14,8 @@
 
 [[maybe_unused]] std::tuple_size<std::tuple<void, void>> test;
 
-// expected-warning at __tuple/tuple_size.h:* {{'__volatile_tuple_size_deprecated<std::tuple<void, void>>' is deprecated}}
+// expected-warning at __tuple/tuple_size.h:* {{'__volatile_deprecated_since_cxx20_warning<volatile std::tuple<void, void>>' is deprecated}}
 [[maybe_unused]] std::tuple_size<volatile std::tuple<void, void>> vol_test;
 
-// expected-warning at __tuple/tuple_size.h:* {{'__volatile_tuple_size_deprecated<std::tuple<void, void>>' is deprecated}}
+// expected-warning at __tuple/tuple_size.h:* {{'__volatile_deprecated_since_cxx20_warning<const volatile std::tuple<void, void>>' is deprecated}}
 [[maybe_unused]] std::tuple_size<const volatile std::tuple<void, void>> const_vol_test;
diff --git a/libcxx/test/libcxx/utilities/variant/variant.variant/variant.helper/volatile_deprecated.verify.cpp b/libcxx/test/libcxx/utilities/variant/variant.variant/variant.helper/volatile_deprecated.verify.cpp
index e054f906eec88..29c27c92d36ff 100644
--- a/libcxx/test/libcxx/utilities/variant/variant.variant/variant.helper/volatile_deprecated.verify.cpp
+++ b/libcxx/test/libcxx/utilities/variant/variant.variant/variant.helper/volatile_deprecated.verify.cpp
@@ -16,16 +16,16 @@ typedef std::variant<void, int> vars;
 
 [[maybe_unused]] std::variant_alternative<0, vars> alt_test;
 
-// expected-warning at variant:* {{'__volatile_variant_deprecated<std::variant<void, int>>' is deprecated}}
+// expected-warning at variant:* {{'__volatile_deprecated_since_cxx20_warning<volatile std::variant<void, int>>' is deprecated}}
 [[maybe_unused]] std::variant_alternative<0, volatile vars> vol_alt_test;
 
-// expected-warning at variant:* {{'__volatile_variant_deprecated<std::variant<void, int>>' is deprecated}}
+// expected-warning at variant:* {{'__volatile_deprecated_since_cxx20_warning<const volatile std::variant<void, int>>' is deprecated}}
 [[maybe_unused]] std::variant_alternative<0, const volatile vars> const_vol_alt_test;
 
 [[maybe_unused]] std::variant_size<vars> size_test;
 
-// expected-warning at variant:* {{'__volatile_variant_deprecated<std::variant<void, int>>' is deprecated}}
+// expected-warning at variant:* {{'__volatile_deprecated_since_cxx20_warning<volatile std::variant<void, int>>' is deprecated}}
 [[maybe_unused]] std::variant_size<volatile vars> vol_size_test;
 
-// expected-warning at variant:* {{'__volatile_variant_deprecated<std::variant<void, int>>' is deprecated}}
+// expected-warning at variant:* {{'__volatile_deprecated_since_cxx20_warning<const volatile std::variant<void, int>>' is deprecated}}
 [[maybe_unused]] std::variant_size<const volatile vars> const_vol_size_test;



More information about the libcxx-commits mailing list