[libcxx-commits] [libcxx] fc4bff0 - Update atomic feature macros, synopsis, signatures to match C++20. Improve test coverage for non-lock-free atomics.

Olivier Giroux via libcxx-commits libcxx-commits at lists.llvm.org
Wed Sep 9 10:00:28 PDT 2020


Author: Olivier Giroux
Date: 2020-09-09T10:00:09-07:00
New Revision: fc4bff0cd37fa84ee74e6dff7170b643df3ffa42

URL: https://github.com/llvm/llvm-project/commit/fc4bff0cd37fa84ee74e6dff7170b643df3ffa42
DIFF: https://github.com/llvm/llvm-project/commit/fc4bff0cd37fa84ee74e6dff7170b643df3ffa42.diff

LOG: Update atomic feature macros, synopsis, signatures to match C++20. Improve test coverage for non-lock-free atomics.

Added: 
    libcxx/test/std/atomics/atomics.flag/atomic_flag_test.pass.cpp
    libcxx/test/std/atomics/atomics.flag/atomic_flag_test_explicit.pass.cpp

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/include/atomic
    libcxx/include/version
    libcxx/test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h
    libcxx/test/std/atomics/types.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/execution.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
    libcxx/test/support/cmpxchg_loop.h
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index f5c6e5b8251a..61773381c15f 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -170,8 +170,20 @@ Status
     -------------------------------------------------------------------
     ``__cpp_lib_array_constexpr``                     ``201811L``      
     ------------------------------------------------- -----------------
+    ``__cpp_lib_atomic_flag_test``                    ``201907L``      
+    ------------------------------------------------- -----------------
+    ``__cpp_lib_atomic_float``                        *unimplemented*  
+    ------------------------------------------------- -----------------
+    ``__cpp_lib_atomic_lock_free_type_aliases``       ``201907L``      
+    ------------------------------------------------- -----------------
     ``__cpp_lib_atomic_ref``                          *unimplemented*  
     ------------------------------------------------- -----------------
+    ``__cpp_lib_atomic_shared_ptr``                   *unimplemented*  
+    ------------------------------------------------- -----------------
+    ``__cpp_lib_atomic_value_initialization``         *unimplemented*  
+    ------------------------------------------------- -----------------
+    ``__cpp_lib_atomic_wait``                         ``201907L``      
+    ------------------------------------------------- -----------------
     ``__cpp_lib_bind_front``                          *unimplemented*  
     ------------------------------------------------- -----------------
     ``__cpp_lib_bit_cast``                            *unimplemented*  

diff  --git a/libcxx/include/atomic b/libcxx/include/atomic
index 9c2898653788..be81f6491edf 100644
--- a/libcxx/include/atomic
+++ b/libcxx/include/atomic
@@ -16,9 +16,12 @@
 namespace std
 {
 
-// feature test macro
+// feature test macro [version.syn]
 
-#define __cpp_lib_atomic_is_always_lock_free // as specified by SG10
+#define __cpp_lib_atomic_is_always_lock_free
+#define __cpp_lib_atomic_flag_test
+#define __cpp_lib_atomic_lock_free_type_aliases
+#define __cpp_lib_atomic_wait
 
  // order and consistency
 
@@ -108,6 +111,7 @@ template <>
 struct atomic<integral>
 {
     using value_type = integral;
+    using 
diff erence_type = value_type;
 
     static constexpr bool is_always_lock_free;
     bool is_lock_free() const volatile noexcept;
@@ -190,6 +194,7 @@ template <class T>
 struct atomic<T*>
 {
     using value_type = T*;
+    using 
diff erence_type = ptr
diff _t;
 
     static constexpr bool is_always_lock_free;
     bool is_lock_free() const volatile noexcept;
@@ -1245,10 +1250,10 @@ template <typename _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool __cxx_atomic_compare_exchange_strong(volatile __cxx_atomic_lock_impl<_Tp>* __a,
                                           _Tp* __expected, _Tp __value, memory_order, memory_order) {
-  __a->__lock();
   _Tp __temp;
+  __a->__lock();
   __cxx_atomic_assign_volatile(__temp, __a->__a_value);
-  bool __ret = __temp == *__expected;
+  bool __ret = (memcmp(&__temp, __expected, sizeof(_Tp)) == 0);
   if(__ret)
     __cxx_atomic_assign_volatile(__a->__a_value, __value);
   else
@@ -1261,11 +1266,11 @@ _LIBCPP_INLINE_VISIBILITY
 bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_lock_impl<_Tp>* __a,
                                           _Tp* __expected, _Tp __value, memory_order, memory_order) {
   __a->__lock();
-  bool __ret = __a->__a_value == *__expected;
+  bool __ret = (memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0);
   if(__ret)
-    __a->__a_value = __value;
+    memcpy(&__a->__a_value, &__value, sizeof(_Tp));
   else
-    *__expected = __a->__a_value;
+    memcpy(__expected, &__a->__a_value, sizeof(_Tp));
   __a->__unlock();
   return __ret;
 }
@@ -1274,10 +1279,10 @@ template <typename _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool __cxx_atomic_compare_exchange_weak(volatile __cxx_atomic_lock_impl<_Tp>* __a,
                                         _Tp* __expected, _Tp __value, memory_order, memory_order) {
-  __a->__lock();
   _Tp __temp;
+  __a->__lock();
   __cxx_atomic_assign_volatile(__temp, __a->__a_value);
-  bool __ret = __temp == *__expected;
+  bool __ret = (memcmp(&__temp, __expected, sizeof(_Tp)) == 0);
   if(__ret)
     __cxx_atomic_assign_volatile(__a->__a_value, __value);
   else
@@ -1290,11 +1295,11 @@ _LIBCPP_INLINE_VISIBILITY
 bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_lock_impl<_Tp>* __a,
                                         _Tp* __expected, _Tp __value, memory_order, memory_order) {
   __a->__lock();
-  bool __ret = __a->__a_value == *__expected;
+  bool __ret = (memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0);
   if(__ret)
-    __a->__a_value = __value;
+    memcpy(&__a->__a_value, &__value, sizeof(_Tp));
   else
-    *__expected = __a->__a_value;
+    memcpy(__expected, &__a->__a_value, sizeof(_Tp));
   __a->__unlock();
   return __ret;
 }
@@ -1775,6 +1780,7 @@ struct atomic
 {
     typedef __atomic_base<_Tp> __base;
     typedef _Tp value_type;
+    typedef value_type 
diff erence_type;
     _LIBCPP_INLINE_VISIBILITY
     atomic() _NOEXCEPT _LIBCPP_DEFAULT
     _LIBCPP_INLINE_VISIBILITY
@@ -1796,6 +1802,7 @@ struct atomic<_Tp*>
 {
     typedef __atomic_base<_Tp*> __base;
     typedef _Tp* value_type;
+    typedef ptr
diff _t 
diff erence_type;
     _LIBCPP_INLINE_VISIBILITY
     atomic() _NOEXCEPT _LIBCPP_DEFAULT
     _LIBCPP_INLINE_VISIBILITY
@@ -1872,7 +1879,7 @@ atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 void
-atomic_init(volatile atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
+atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     __cxx_atomic_init(&__o->__a_, __d);
 }
@@ -1880,7 +1887,7 @@ atomic_init(volatile atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 void
-atomic_init(atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
+atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     __cxx_atomic_init(&__o->__a_, __d);
 }
@@ -1890,7 +1897,7 @@ atomic_init(atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 void
-atomic_store(volatile atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
+atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     __o->store(__d);
 }
@@ -1898,7 +1905,7 @@ atomic_store(volatile atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 void
-atomic_store(atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
+atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     __o->store(__d);
 }
@@ -1908,7 +1915,7 @@ atomic_store(atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 void
-atomic_store_explicit(volatile atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOEXCEPT
+atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
   _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m)
 {
     __o->store(__d, __m);
@@ -1917,7 +1924,7 @@ atomic_store_explicit(volatile atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOE
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 void
-atomic_store_explicit(atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOEXCEPT
+atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
   _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m)
 {
     __o->store(__d, __m);
@@ -1966,7 +1973,7 @@ atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 _Tp
-atomic_exchange(volatile atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
+atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     return __o->exchange(__d);
 }
@@ -1974,7 +1981,7 @@ atomic_exchange(volatile atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 _Tp
-atomic_exchange(atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
+atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     return __o->exchange(__d);
 }
@@ -1984,7 +1991,7 @@ atomic_exchange(atomic<_Tp>* __o, _Tp __d) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 _Tp
-atomic_exchange_explicit(volatile atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOEXCEPT
+atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
 {
     return __o->exchange(__d, __m);
 }
@@ -1992,7 +1999,7 @@ atomic_exchange_explicit(volatile atomic<_Tp>* __o, _Tp __d, memory_order __m) _
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 _Tp
-atomic_exchange_explicit(atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOEXCEPT
+atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
 {
     return __o->exchange(__d, __m);
 }
@@ -2002,7 +2009,7 @@ atomic_exchange_explicit(atomic<_Tp>* __o, _Tp __d, memory_order __m) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool
-atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
+atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     return __o->compare_exchange_weak(*__e, __d);
 }
@@ -2010,7 +2017,7 @@ atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEX
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool
-atomic_compare_exchange_weak(atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
+atomic_compare_exchange_weak(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     return __o->compare_exchange_weak(*__e, __d);
 }
@@ -2020,7 +2027,7 @@ atomic_compare_exchange_weak(atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool
-atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
+atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     return __o->compare_exchange_strong(*__e, __d);
 }
@@ -2028,7 +2035,7 @@ atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NO
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool
-atomic_compare_exchange_strong(atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
+atomic_compare_exchange_strong(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
 {
     return __o->compare_exchange_strong(*__e, __d);
 }
@@ -2038,8 +2045,8 @@ atomic_compare_exchange_strong(atomic<_Tp>* __o, _Tp* __e, _Tp __d) _NOEXCEPT
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool
-atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, _Tp* __e,
-                                      _Tp __d,
+atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e,
+                                      typename atomic<_Tp>::value_type __d,
                                       memory_order __s, memory_order __f) _NOEXCEPT
   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
 {
@@ -2049,7 +2056,7 @@ atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, _Tp* __e,
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool
-atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, _Tp* __e, _Tp __d,
+atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d,
                                       memory_order __s, memory_order __f) _NOEXCEPT
   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
 {
@@ -2062,7 +2069,7 @@ template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool
 atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o,
-                                        _Tp* __e, _Tp __d,
+                                        typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d,
                                         memory_order __s, memory_order __f) _NOEXCEPT
   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
 {
@@ -2072,8 +2079,8 @@ atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o,
 template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 bool
-atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, _Tp* __e,
-                                        _Tp __d,
+atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e,
+                                        typename atomic<_Tp>::value_type __d,
                                         memory_order __s, memory_order __f) _NOEXCEPT
   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
 {
@@ -2156,10 +2163,10 @@ template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
-    is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
+    is_pointer<_Tp>::value || (is_integral<_Tp>::value && !is_same<_Tp, bool>::value),
     _Tp
 >::type
-atomic_fetch_add(volatile atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
+atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::
diff erence_type __op) _NOEXCEPT
 {
     return __o->fetch_add(__op);
 }
@@ -2168,26 +2175,10 @@ template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
-    is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
+    is_pointer<_Tp>::value || (is_integral<_Tp>::value && !is_same<_Tp, bool>::value),
     _Tp
 >::type
-atomic_fetch_add(atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
-{
-    return __o->fetch_add(__op);
-}
-
-template <class _Tp>
-_LIBCPP_INLINE_VISIBILITY
-_Tp*
-atomic_fetch_add(volatile atomic<_Tp*>* __o, ptr
diff _t __op) _NOEXCEPT
-{
-    return __o->fetch_add(__op);
-}
-
-template <class _Tp>
-_LIBCPP_INLINE_VISIBILITY
-_Tp*
-atomic_fetch_add(atomic<_Tp*>* __o, ptr
diff _t __op) _NOEXCEPT
+atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::
diff erence_type __op) _NOEXCEPT
 {
     return __o->fetch_add(__op);
 }
@@ -2198,10 +2189,10 @@ template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
-    is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
+    is_pointer<_Tp>::value || (is_integral<_Tp>::value && !is_same<_Tp, bool>::value),
     _Tp
 >::type
-atomic_fetch_add_explicit(volatile atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
+atomic_fetch_add_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::
diff erence_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_add(__op, __m);
 }
@@ -2210,27 +2201,10 @@ template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
-    is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
+    is_pointer<_Tp>::value || (is_integral<_Tp>::value && !is_same<_Tp, bool>::value),
     _Tp
 >::type
-atomic_fetch_add_explicit(atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
-{
-    return __o->fetch_add(__op, __m);
-}
-
-template <class _Tp>
-_LIBCPP_INLINE_VISIBILITY
-_Tp*
-atomic_fetch_add_explicit(volatile atomic<_Tp*>* __o, ptr
diff _t __op,
-                          memory_order __m) _NOEXCEPT
-{
-    return __o->fetch_add(__op, __m);
-}
-
-template <class _Tp>
-_LIBCPP_INLINE_VISIBILITY
-_Tp*
-atomic_fetch_add_explicit(atomic<_Tp*>* __o, ptr
diff _t __op, memory_order __m) _NOEXCEPT
+atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::
diff erence_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_add(__op, __m);
 }
@@ -2241,10 +2215,10 @@ template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
-    is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
+    is_pointer<_Tp>::value || (is_integral<_Tp>::value && !is_same<_Tp, bool>::value),
     _Tp
 >::type
-atomic_fetch_sub(volatile atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
+atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::
diff erence_type __op) _NOEXCEPT
 {
     return __o->fetch_sub(__op);
 }
@@ -2253,26 +2227,10 @@ template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
-    is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
+    is_pointer<_Tp>::value || (is_integral<_Tp>::value && !is_same<_Tp, bool>::value),
     _Tp
 >::type
-atomic_fetch_sub(atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
-{
-    return __o->fetch_sub(__op);
-}
-
-template <class _Tp>
-_LIBCPP_INLINE_VISIBILITY
-_Tp*
-atomic_fetch_sub(volatile atomic<_Tp*>* __o, ptr
diff _t __op) _NOEXCEPT
-{
-    return __o->fetch_sub(__op);
-}
-
-template <class _Tp>
-_LIBCPP_INLINE_VISIBILITY
-_Tp*
-atomic_fetch_sub(atomic<_Tp*>* __o, ptr
diff _t __op) _NOEXCEPT
+atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::
diff erence_type __op) _NOEXCEPT
 {
     return __o->fetch_sub(__op);
 }
@@ -2283,10 +2241,10 @@ template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
-    is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
+    is_pointer<_Tp>::value || (is_integral<_Tp>::value && !is_same<_Tp, bool>::value),
     _Tp
 >::type
-atomic_fetch_sub_explicit(volatile atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
+atomic_fetch_sub_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::
diff erence_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_sub(__op, __m);
 }
@@ -2295,27 +2253,10 @@ template <class _Tp>
 _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
-    is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
+    is_pointer<_Tp>::value || (is_integral<_Tp>::value && !is_same<_Tp, bool>::value),
     _Tp
 >::type
-atomic_fetch_sub_explicit(atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
-{
-    return __o->fetch_sub(__op, __m);
-}
-
-template <class _Tp>
-_LIBCPP_INLINE_VISIBILITY
-_Tp*
-atomic_fetch_sub_explicit(volatile atomic<_Tp*>* __o, ptr
diff _t __op,
-                          memory_order __m) _NOEXCEPT
-{
-    return __o->fetch_sub(__op, __m);
-}
-
-template <class _Tp>
-_LIBCPP_INLINE_VISIBILITY
-_Tp*
-atomic_fetch_sub_explicit(atomic<_Tp*>* __o, ptr
diff _t __op, memory_order __m) _NOEXCEPT
+atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::
diff erence_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_sub(__op, __m);
 }
@@ -2329,7 +2270,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_and(volatile atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
+atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
 {
     return __o->fetch_and(__op);
 }
@@ -2341,7 +2282,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_and(atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
+atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
 {
     return __o->fetch_and(__op);
 }
@@ -2355,7 +2296,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_and_explicit(volatile atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
+atomic_fetch_and_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_and(__op, __m);
 }
@@ -2367,7 +2308,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_and_explicit(atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
+atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_and(__op, __m);
 }
@@ -2381,7 +2322,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_or(volatile atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
+atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
 {
     return __o->fetch_or(__op);
 }
@@ -2393,7 +2334,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_or(atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
+atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
 {
     return __o->fetch_or(__op);
 }
@@ -2407,7 +2348,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
+atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_or(__op, __m);
 }
@@ -2419,7 +2360,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_or_explicit(atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
+atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_or(__op, __m);
 }
@@ -2433,7 +2374,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_xor(volatile atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
+atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
 {
     return __o->fetch_xor(__op);
 }
@@ -2445,7 +2386,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_xor(atomic<_Tp>* __o, _Tp __op) _NOEXCEPT
+atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
 {
     return __o->fetch_xor(__op);
 }
@@ -2459,7 +2400,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_xor_explicit(volatile atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
+atomic_fetch_xor_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_xor(__op, __m);
 }
@@ -2471,7 +2412,7 @@ typename enable_if
     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
     _Tp
 >::type
-atomic_fetch_xor_explicit(atomic<_Tp>* __o, _Tp __op, memory_order __m) _NOEXCEPT
+atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
 {
     return __o->fetch_xor(__op, __m);
 }

diff  --git a/libcxx/include/version b/libcxx/include/version
index dc53be3937c4..d18da3d14690 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -24,8 +24,14 @@ __cpp_lib_apply                                         201603L <tuple>
 __cpp_lib_array_constexpr                               201811L <iterator> <array>
                                                         201603L // C++17
 __cpp_lib_as_const                                      201510L <utility>
+__cpp_lib_atomic_flag_test                              201907L <atomic>
+__cpp_lib_atomic_float                                  201711L <atomic>
 __cpp_lib_atomic_is_always_lock_free                    201603L <atomic>
+__cpp_lib_atomic_lock_free_type_aliases                 201907L <atomic>
 __cpp_lib_atomic_ref                                    201806L <atomic>
+__cpp_lib_atomic_shared_ptr                             201711L <atomic>
+__cpp_lib_atomic_value_initialization                   201911L <atomic> <memory>
+__cpp_lib_atomic_wait                                   201907L <atomic>
 __cpp_lib_bind_front                                    201811L <functional>
 __cpp_lib_bit_cast                                      201806L <bit>
 __cpp_lib_bool_constant                                 201505L <type_traits>
@@ -218,8 +224,26 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # undef  __cpp_lib_array_constexpr
 # define __cpp_lib_array_constexpr                      201811L
 # if !defined(_LIBCPP_HAS_NO_THREADS)
+#   define __cpp_lib_atomic_flag_test                   201907L
+# endif
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+// #   define __cpp_lib_atomic_float                       201711L
+# endif
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+#   define __cpp_lib_atomic_lock_free_type_aliases      201907L
+# endif
+# if !defined(_LIBCPP_HAS_NO_THREADS)
 // #   define __cpp_lib_atomic_ref                         201806L
 # endif
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+// #   define __cpp_lib_atomic_shared_ptr                  201711L
+# endif
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+// #   define __cpp_lib_atomic_value_initialization        201911L
+# endif
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+#   define __cpp_lib_atomic_wait                        201907L
+# endif
 // # define __cpp_lib_bind_front                           201811L
 // # define __cpp_lib_bit_cast                             201806L
 # if !defined(_LIBCPP_NO_HAS_CHAR8_T)

diff  --git a/libcxx/test/std/atomics/atomics.flag/atomic_flag_test.pass.cpp b/libcxx/test/std/atomics/atomics.flag/atomic_flag_test.pass.cpp
new file mode 100644
index 000000000000..22e4b66d45c5
--- /dev/null
+++ b/libcxx/test/std/atomics/atomics.flag/atomic_flag_test.pass.cpp
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: libcpp-has-no-threads
+
+// <atomic>
+
+// struct atomic_flag
+
+// bool atomic_flag_test_and_set(volatile atomic_flag*);
+// bool atomic_flag_test_and_set(atomic_flag*);
+
+#include <atomic>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main(int, char**)
+{
+    {
+        std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_and_set(&f) == 0);
+        assert(f.test_and_set() == 1);
+    }
+    {
+        volatile std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_and_set(&f) == 0);
+        assert(f.test_and_set() == 1);
+    }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/atomics/atomics.flag/atomic_flag_test_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.flag/atomic_flag_test_explicit.pass.cpp
new file mode 100644
index 000000000000..45ac737b5984
--- /dev/null
+++ b/libcxx/test/std/atomics/atomics.flag/atomic_flag_test_explicit.pass.cpp
@@ -0,0 +1,111 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: libcpp-has-no-threads
+
+// <atomic>
+
+// struct atomic_flag
+
+// bool atomic_flag_test_explicit(volatile atomic_flag*, memory_order);
+// bool atomic_flag_test_explicit(atomic_flag*, memory_order);
+
+#include <atomic>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main(int, char**)
+{
+    {
+        std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_relaxed) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_relaxed) == 1);
+    }
+    {
+        std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_consume) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_consume) == 1);
+    }
+    {
+        std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_acquire) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_acquire) == 1);
+    }
+    {
+        std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_release) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_release) == 1);
+    }
+    {
+        std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_acq_rel) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_acq_rel) == 1);
+    }
+    {
+        std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_seq_cst) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_seq_cst) == 1);
+    }
+    {
+        volatile std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_relaxed) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_relaxed) == 1);
+    }
+    {
+        volatile std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_consume) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_consume) == 1);
+    }
+    {
+        volatile std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_acquire) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_acquire) == 1);
+    }
+    {
+        volatile std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_release) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_release) == 1);
+    }
+    {
+        volatile std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_acq_rel) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_acq_rel) == 1);
+    }
+    {
+        volatile std::atomic_flag f;
+        f.clear();
+        assert(atomic_flag_test_explicit(&f, std::memory_order_seq_cst) == 0);
+        assert(f.test_and_set() == 0);
+        assert(atomic_flag_test_explicit(&f, std::memory_order_seq_cst) == 1);
+    }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp b/libcxx/test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp
index 34a068918286..8dd8c345592b 100644
--- a/libcxx/test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.lockfree/isalwayslockfree.pass.cpp
@@ -134,6 +134,11 @@ void run()
     checkLongLongTypes();
     static_assert(std::atomic<void*>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE), "");
     static_assert(std::atomic<std::nullptr_t>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE), "");
+
+#if TEST_STD_VER >= 20
+    static_assert(std::atomic<std::atomic_signed_lock_free>::is_always_lock_free, "");
+    static_assert(std::atomic<std::atomic_unsigned_lock_free>::is_always_lock_free, "");
+#endif
 }
 
 int main(int, char**) { run(); return 0; }

diff  --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h
index 65676339c742..1cb3a3d11114 100644
--- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h
+++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_helpers.h
@@ -23,6 +23,37 @@ struct UserAtomicType
     { return x.i == y.i; }
 };
 
+struct WeirdUserAtomicType
+{
+    char i, j, k; /* the 3 chars of doom */
+
+    explicit WeirdUserAtomicType(int d = 0) TEST_NOEXCEPT : i(d) {}
+
+    friend bool operator==(const WeirdUserAtomicType& x, const WeirdUserAtomicType& y)
+    { return x.i == y.i; }
+};
+
+struct PaddedUserAtomicType
+{
+    char i; int j; /* probably lock-free? */
+
+    explicit PaddedUserAtomicType(int d = 0) TEST_NOEXCEPT : i(d) {}
+
+    friend bool operator==(const PaddedUserAtomicType& x, const PaddedUserAtomicType& y)
+    { return x.i == y.i; }
+};
+
+struct LargeUserAtomicType
+{
+    int i, j[127]; /* decidedly not lock-free */
+
+    LargeUserAtomicType(int d = 0) TEST_NOEXCEPT : i(d)
+    {}
+
+    friend bool operator==(const LargeUserAtomicType& x, const LargeUserAtomicType& y)
+    { return x.i == y.i; }
+};
+
 template < template <class TestArg> class TestFunctor >
 struct TestEachIntegralType {
     void operator()() const {
@@ -58,8 +89,19 @@ struct TestEachAtomicType {
     void operator()() const {
         TestEachIntegralType<TestFunctor>()();
         TestFunctor<UserAtomicType>()();
+        TestFunctor<PaddedUserAtomicType>()();
+#ifndef __APPLE__
+        /*
+            These aren't going to be lock-free,
+            so some libatomic.a is necessary.
+        */
+        TestFunctor<WeirdUserAtomicType>()();
+        TestFunctor<LargeUserAtomicType>()();
+#endif
         TestFunctor<int*>()();
         TestFunctor<const int*>()();
+        TestFunctor<float>()();
+        TestFunctor<double>()();
     }
 };
 

diff  --git a/libcxx/test/std/atomics/types.pass.cpp b/libcxx/test/std/atomics/types.pass.cpp
index f891f90e116b..5740b758035e 100644
--- a/libcxx/test/std/atomics/types.pass.cpp
+++ b/libcxx/test/std/atomics/types.pass.cpp
@@ -30,15 +30,43 @@
 
 #include "test_macros.h"
 
+template <class A, bool Integral>
+struct test_atomic
+{
+    test_atomic()
+    {
+        A a; (void)a;
+#if TEST_STD_VER >= 17
+    static_assert((std::is_same_v<typename A::value_type, decltype(a.load())>), "");
+#endif
+    }
+};
+
 template <class A>
-void
-test_atomic()
+struct test_atomic<A, true>
 {
-    A a; (void)a;
+    test_atomic()
+    {
+        A a; (void)a;
 #if TEST_STD_VER >= 17
-    static_assert((std::is_same<typename A::value_type, decltype(a.load())>::value), "");
+    static_assert((std::is_same_v<typename A::value_type, decltype(a.load())>), "");
+    static_assert((std::is_same_v<typename A::value_type, typename A::
diff erence_type>), "");
 #endif
-}
+    }
+};
+
+template <class A>
+struct test_atomic<A*, false>
+{
+    test_atomic()
+    {
+        A a; (void)a;
+#if TEST_STD_VER >= 17
+    static_assert((std::is_same_v<typename A::value_type, decltype(a.load())>), "");
+    static_assert((std::is_same_v<typename A::
diff erence_type, ptr
diff _t>), "");
+#endif
+    }
+};
 
 template <class T>
 void
@@ -46,15 +74,30 @@ test()
 {
     using A = std::atomic<T>;
 #if TEST_STD_VER >= 17
-    static_assert((std::is_same<typename A::value_type, T>::value), "");
+    static_assert((std::is_same_v<typename A::value_type, T>), "");
 #endif
-    test_atomic<A>();
+    test_atomic<A, std::is_integral<T>::value && !std::is_same<T, bool>::value>();
 }
 
 struct TriviallyCopyable {
     int i_;
 };
 
+struct WeirdTriviallyCopyable
+{
+    char i, j, k; /* the 3 chars of doom */
+};
+
+struct PaddedTriviallyCopyable
+{
+    char i; int j; /* probably lock-free? */
+};
+
+struct LargeTriviallyCopyable
+{
+    int i, j[127]; /* decidedly not lock-free */
+};
+
 int main(int, char**)
 {
     test<bool>               ();
@@ -111,13 +154,23 @@ int main(int, char**)
     test<uintmax_t> ();
 
     test<TriviallyCopyable>();
+    test<PaddedTriviallyCopyable>();
+#ifndef __APPLE__
+    /*
+        These aren't going to be lock-free,
+        so some libatomic.a is necessary.
+    */
+    test<WeirdTriviallyCopyable>();
+    test<LargeTriviallyCopyable>();
+#endif
+
     test<std::thread::id>();
     test<std::chrono::nanoseconds>();
     test<float>();
 
 #if TEST_STD_VER >= 20
-    test_atomic<std::atomic_signed_lock_free>();
-    test_atomic<std::atomic_unsigned_lock_free>();
+    test<std::atomic_signed_lock_free>();
+    test<std::atomic_unsigned_lock_free>();
 /*
     test<std::shared_ptr<int>>();
 */

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp
index d8f6f548cd23..d4c63edb5b8a 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp
@@ -15,10 +15,16 @@
 
 // Test the feature test macros defined by <atomic>
 
-/*  Constant                                Value
-    __cpp_lib_atomic_is_always_lock_free    201603L [C++17]
-    __cpp_lib_atomic_ref                    201806L [C++2a]
-    __cpp_lib_char8_t                       201811L [C++2a]
+/*  Constant                                   Value
+    __cpp_lib_atomic_flag_test                 201907L [C++2a]
+    __cpp_lib_atomic_float                     201711L [C++2a]
+    __cpp_lib_atomic_is_always_lock_free       201603L [C++17]
+    __cpp_lib_atomic_lock_free_type_aliases    201907L [C++2a]
+    __cpp_lib_atomic_ref                       201806L [C++2a]
+    __cpp_lib_atomic_shared_ptr                201711L [C++2a]
+    __cpp_lib_atomic_value_initialization      201911L [C++2a]
+    __cpp_lib_atomic_wait                      201907L [C++2a]
+    __cpp_lib_char8_t                          201811L [C++2a]
 */
 
 #include <atomic>
@@ -26,34 +32,90 @@
 
 #if TEST_STD_VER < 14
 
+# ifdef __cpp_lib_atomic_flag_test
+#   error "__cpp_lib_atomic_flag_test should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_float
+#   error "__cpp_lib_atomic_float should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_is_always_lock_free
 #   error "__cpp_lib_atomic_is_always_lock_free should not be defined before c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_lock_free_type_aliases
+#   error "__cpp_lib_atomic_lock_free_type_aliases should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_ref
 #   error "__cpp_lib_atomic_ref should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_atomic_shared_ptr
+#   error "__cpp_lib_atomic_shared_ptr should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_value_initialization
+#   error "__cpp_lib_atomic_value_initialization should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_wait
+#   error "__cpp_lib_atomic_wait should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_char8_t
 #   error "__cpp_lib_char8_t should not be defined before c++2a"
 # endif
 
 #elif TEST_STD_VER == 14
 
+# ifdef __cpp_lib_atomic_flag_test
+#   error "__cpp_lib_atomic_flag_test should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_float
+#   error "__cpp_lib_atomic_float should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_is_always_lock_free
 #   error "__cpp_lib_atomic_is_always_lock_free should not be defined before c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_lock_free_type_aliases
+#   error "__cpp_lib_atomic_lock_free_type_aliases should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_ref
 #   error "__cpp_lib_atomic_ref should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_atomic_shared_ptr
+#   error "__cpp_lib_atomic_shared_ptr should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_value_initialization
+#   error "__cpp_lib_atomic_value_initialization should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_wait
+#   error "__cpp_lib_atomic_wait should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_char8_t
 #   error "__cpp_lib_char8_t should not be defined before c++2a"
 # endif
 
 #elif TEST_STD_VER == 17
 
+# ifdef __cpp_lib_atomic_flag_test
+#   error "__cpp_lib_atomic_flag_test should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_float
+#   error "__cpp_lib_atomic_float should not be defined before c++2a"
+# endif
+
 # if !defined(_LIBCPP_HAS_NO_THREADS)
 #   ifndef __cpp_lib_atomic_is_always_lock_free
 #     error "__cpp_lib_atomic_is_always_lock_free should be defined in c++17"
@@ -67,16 +129,58 @@
 #   endif
 # endif
 
+# ifdef __cpp_lib_atomic_lock_free_type_aliases
+#   error "__cpp_lib_atomic_lock_free_type_aliases should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_ref
 #   error "__cpp_lib_atomic_ref should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_atomic_shared_ptr
+#   error "__cpp_lib_atomic_shared_ptr should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_value_initialization
+#   error "__cpp_lib_atomic_value_initialization should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_wait
+#   error "__cpp_lib_atomic_wait should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_char8_t
 #   error "__cpp_lib_char8_t should not be defined before c++2a"
 # endif
 
 #elif TEST_STD_VER > 17
 
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+#   ifndef __cpp_lib_atomic_flag_test
+#     error "__cpp_lib_atomic_flag_test should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_flag_test != 201907L
+#     error "__cpp_lib_atomic_flag_test should have the value 201907L in c++2a"
+#   endif
+# else
+#   ifdef __cpp_lib_atomic_flag_test
+#     error "__cpp_lib_atomic_flag_test should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!"
+#   endif
+# endif
+
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_atomic_float
+#     error "__cpp_lib_atomic_float should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_float != 201711L
+#     error "__cpp_lib_atomic_float should have the value 201711L in c++2a"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_atomic_float
+#     error "__cpp_lib_atomic_float should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
 # if !defined(_LIBCPP_HAS_NO_THREADS)
 #   ifndef __cpp_lib_atomic_is_always_lock_free
 #     error "__cpp_lib_atomic_is_always_lock_free should be defined in c++2a"
@@ -90,6 +194,19 @@
 #   endif
 # endif
 
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+#   ifndef __cpp_lib_atomic_lock_free_type_aliases
+#     error "__cpp_lib_atomic_lock_free_type_aliases should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_lock_free_type_aliases != 201907L
+#     error "__cpp_lib_atomic_lock_free_type_aliases should have the value 201907L in c++2a"
+#   endif
+# else
+#   ifdef __cpp_lib_atomic_lock_free_type_aliases
+#     error "__cpp_lib_atomic_lock_free_type_aliases should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!"
+#   endif
+# endif
+
 # if !defined(_LIBCPP_VERSION)
 #   ifndef __cpp_lib_atomic_ref
 #     error "__cpp_lib_atomic_ref should be defined in c++2a"
@@ -103,6 +220,45 @@
 #   endif
 # endif
 
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_atomic_shared_ptr
+#     error "__cpp_lib_atomic_shared_ptr should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_shared_ptr != 201711L
+#     error "__cpp_lib_atomic_shared_ptr should have the value 201711L in c++2a"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_atomic_shared_ptr
+#     error "__cpp_lib_atomic_shared_ptr should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_atomic_value_initialization
+#     error "__cpp_lib_atomic_value_initialization should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_value_initialization != 201911L
+#     error "__cpp_lib_atomic_value_initialization should have the value 201911L in c++2a"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_atomic_value_initialization
+#     error "__cpp_lib_atomic_value_initialization should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+#   ifndef __cpp_lib_atomic_wait
+#     error "__cpp_lib_atomic_wait should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_wait != 201907L
+#     error "__cpp_lib_atomic_wait should have the value 201907L in c++2a"
+#   endif
+# else
+#   ifdef __cpp_lib_atomic_wait
+#     error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!"
+#   endif
+# endif
+
 # if defined(__cpp_char8_t)
 #   ifndef __cpp_lib_char8_t
 #     error "__cpp_lib_char8_t should be defined in c++2a"

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp
index 16febf8d3e24..9ec2157d974c 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp
@@ -1,4 +1,3 @@
-
 //===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -7,29 +6,53 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// <concepts> feature macros
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <concepts>
 
-/*  Constant                                    Value
-    __cpp_lib_concepts                          201806L
+// Test the feature test macros defined by <concepts>
 
+/*  Constant              Value
+    __cpp_lib_concepts    201806L [C++2a]
 */
 
-// XFAIL
-// #include <concepts>
-#include <cassert>
+#include <concepts>
 #include "test_macros.h"
 
-int main(int, char**)
-{
-//  ensure that the macros that are supposed to be defined in <concepts> are defined.
+#if TEST_STD_VER < 14
 
-/*
-#if !defined(__cpp_lib_fooby)
-# error "__cpp_lib_fooby is not defined"
-#elif __cpp_lib_fooby < 201606L
-# error "__cpp_lib_fooby has an invalid value"
-#endif
-*/
+# ifdef __cpp_lib_concepts
+#   error "__cpp_lib_concepts should not be defined before c++2a"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_concepts
+#   error "__cpp_lib_concepts should not be defined before c++2a"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_concepts
+#   error "__cpp_lib_concepts should not be defined before c++2a"
+# endif
+
+#elif TEST_STD_VER > 17
+
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_concepts
+#     error "__cpp_lib_concepts should be defined in c++2a"
+#   endif
+#   if __cpp_lib_concepts != 201806L
+#     error "__cpp_lib_concepts should have the value 201806L in c++2a"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_concepts
+#     error "__cpp_lib_concepts should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
+#endif // TEST_STD_VER > 17
 
-  return 0;
-}
+int main(int, char**) { return 0; }

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/execution.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/execution.version.pass.cpp
index b05f41bb1731..1244efa4aeba 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/execution.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/execution.version.pass.cpp
@@ -1,4 +1,3 @@
-
 //===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -7,29 +6,62 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// <execution> feature macros
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <execution>
 
-/*  Constant                                    Value
-    __cpp_lib_execution                         201603L
+// Test the feature test macros defined by <execution>
 
+/*  Constant               Value
+    __cpp_lib_execution    201603L [C++17]
 */
 
-// XFAIL
-// #include <execution>
-#include <cassert>
+#include <execution>
 #include "test_macros.h"
 
-int main(int, char**)
-{
-//  ensure that the macros that are supposed to be defined in <execution> are defined.
+#if TEST_STD_VER < 14
 
-/*
-#if !defined(__cpp_lib_fooby)
-# error "__cpp_lib_fooby is not defined"
-#elif __cpp_lib_fooby < 201606L
-# error "__cpp_lib_fooby has an invalid value"
-#endif
-*/
+# ifdef __cpp_lib_execution
+#   error "__cpp_lib_execution should not be defined before c++17"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_execution
+#   error "__cpp_lib_execution should not be defined before c++17"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_execution
+#     error "__cpp_lib_execution should be defined in c++17"
+#   endif
+#   if __cpp_lib_execution != 201603L
+#     error "__cpp_lib_execution should have the value 201603L in c++17"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_execution
+#     error "__cpp_lib_execution should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
+#elif TEST_STD_VER > 17
+
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_execution
+#     error "__cpp_lib_execution should be defined in c++2a"
+#   endif
+#   if __cpp_lib_execution != 201603L
+#     error "__cpp_lib_execution should have the value 201603L in c++2a"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_execution
+#     error "__cpp_lib_execution should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
+#endif // TEST_STD_VER > 17
 
-  return 0;
-}
+int main(int, char**) { return 0; }

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.pass.cpp
index 6c845d71febd..0117fd83a60c 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.pass.cpp
@@ -16,6 +16,7 @@
 /*  Constant                                      Value
     __cpp_lib_addressof_constexpr                 201603L [C++17]
     __cpp_lib_allocator_traits_is_always_equal    201411L [C++17]
+    __cpp_lib_atomic_value_initialization         201911L [C++2a]
     __cpp_lib_enable_shared_from_this             201603L [C++17]
     __cpp_lib_make_unique                         201304L [C++14]
     __cpp_lib_ranges                              201811L [C++2a]
@@ -37,6 +38,10 @@
 #   error "__cpp_lib_allocator_traits_is_always_equal should not be defined before c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_value_initialization
+#   error "__cpp_lib_atomic_value_initialization should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_enable_shared_from_this
 #   error "__cpp_lib_enable_shared_from_this should not be defined before c++17"
 # endif
@@ -71,6 +76,10 @@
 #   error "__cpp_lib_allocator_traits_is_always_equal should not be defined before c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_value_initialization
+#   error "__cpp_lib_atomic_value_initialization should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_enable_shared_from_this
 #   error "__cpp_lib_enable_shared_from_this should not be defined before c++17"
 # endif
@@ -120,6 +129,10 @@
 #   error "__cpp_lib_allocator_traits_is_always_equal should have the value 201411L in c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_value_initialization
+#   error "__cpp_lib_atomic_value_initialization should not be defined before c++2a"
+# endif
+
 # ifndef __cpp_lib_enable_shared_from_this
 #   error "__cpp_lib_enable_shared_from_this should be defined in c++17"
 # endif
@@ -187,6 +200,19 @@
 #   error "__cpp_lib_allocator_traits_is_always_equal should have the value 201411L in c++2a"
 # endif
 
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_atomic_value_initialization
+#     error "__cpp_lib_atomic_value_initialization should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_value_initialization != 201911L
+#     error "__cpp_lib_atomic_value_initialization should have the value 201911L in c++2a"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_atomic_value_initialization
+#     error "__cpp_lib_atomic_value_initialization should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
 # ifndef __cpp_lib_enable_shared_from_this
 #   error "__cpp_lib_enable_shared_from_this should be defined in c++2a"
 # endif

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
index afbee586df3c..46b2e1f21d18 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
@@ -21,8 +21,14 @@
     __cpp_lib_array_constexpr                      201603L [C++17]
                                                    201811L [C++2a]
     __cpp_lib_as_const                             201510L [C++17]
+    __cpp_lib_atomic_flag_test                     201907L [C++2a]
+    __cpp_lib_atomic_float                         201711L [C++2a]
     __cpp_lib_atomic_is_always_lock_free           201603L [C++17]
+    __cpp_lib_atomic_lock_free_type_aliases        201907L [C++2a]
     __cpp_lib_atomic_ref                           201806L [C++2a]
+    __cpp_lib_atomic_shared_ptr                    201711L [C++2a]
+    __cpp_lib_atomic_value_initialization          201911L [C++2a]
+    __cpp_lib_atomic_wait                          201907L [C++2a]
     __cpp_lib_bind_front                           201811L [C++2a]
     __cpp_lib_bit_cast                             201806L [C++2a]
     __cpp_lib_bool_constant                        201505L [C++17]
@@ -135,14 +141,38 @@
 #   error "__cpp_lib_as_const should not be defined before c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_flag_test
+#   error "__cpp_lib_atomic_flag_test should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_float
+#   error "__cpp_lib_atomic_float should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_is_always_lock_free
 #   error "__cpp_lib_atomic_is_always_lock_free should not be defined before c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_lock_free_type_aliases
+#   error "__cpp_lib_atomic_lock_free_type_aliases should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_ref
 #   error "__cpp_lib_atomic_ref should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_atomic_shared_ptr
+#   error "__cpp_lib_atomic_shared_ptr should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_value_initialization
+#   error "__cpp_lib_atomic_value_initialization should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_wait
+#   error "__cpp_lib_atomic_wait should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_bind_front
 #   error "__cpp_lib_bind_front should not be defined before c++2a"
 # endif
@@ -489,14 +519,38 @@
 #   error "__cpp_lib_as_const should not be defined before c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_flag_test
+#   error "__cpp_lib_atomic_flag_test should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_float
+#   error "__cpp_lib_atomic_float should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_is_always_lock_free
 #   error "__cpp_lib_atomic_is_always_lock_free should not be defined before c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_lock_free_type_aliases
+#   error "__cpp_lib_atomic_lock_free_type_aliases should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_ref
 #   error "__cpp_lib_atomic_ref should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_atomic_shared_ptr
+#   error "__cpp_lib_atomic_shared_ptr should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_value_initialization
+#   error "__cpp_lib_atomic_value_initialization should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_wait
+#   error "__cpp_lib_atomic_wait should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_bind_front
 #   error "__cpp_lib_bind_front should not be defined before c++2a"
 # endif
@@ -933,6 +987,14 @@
 #   error "__cpp_lib_as_const should have the value 201510L in c++17"
 # endif
 
+# ifdef __cpp_lib_atomic_flag_test
+#   error "__cpp_lib_atomic_flag_test should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_float
+#   error "__cpp_lib_atomic_float should not be defined before c++2a"
+# endif
+
 # if !defined(_LIBCPP_HAS_NO_THREADS)
 #   ifndef __cpp_lib_atomic_is_always_lock_free
 #     error "__cpp_lib_atomic_is_always_lock_free should be defined in c++17"
@@ -946,10 +1008,26 @@
 #   endif
 # endif
 
+# ifdef __cpp_lib_atomic_lock_free_type_aliases
+#   error "__cpp_lib_atomic_lock_free_type_aliases should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_atomic_ref
 #   error "__cpp_lib_atomic_ref should not be defined before c++2a"
 # endif
 
+# ifdef __cpp_lib_atomic_shared_ptr
+#   error "__cpp_lib_atomic_shared_ptr should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_value_initialization
+#   error "__cpp_lib_atomic_value_initialization should not be defined before c++2a"
+# endif
+
+# ifdef __cpp_lib_atomic_wait
+#   error "__cpp_lib_atomic_wait should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_bind_front
 #   error "__cpp_lib_bind_front should not be defined before c++2a"
 # endif
@@ -1575,6 +1653,32 @@
 #   error "__cpp_lib_as_const should have the value 201510L in c++2a"
 # endif
 
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+#   ifndef __cpp_lib_atomic_flag_test
+#     error "__cpp_lib_atomic_flag_test should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_flag_test != 201907L
+#     error "__cpp_lib_atomic_flag_test should have the value 201907L in c++2a"
+#   endif
+# else
+#   ifdef __cpp_lib_atomic_flag_test
+#     error "__cpp_lib_atomic_flag_test should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!"
+#   endif
+# endif
+
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_atomic_float
+#     error "__cpp_lib_atomic_float should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_float != 201711L
+#     error "__cpp_lib_atomic_float should have the value 201711L in c++2a"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_atomic_float
+#     error "__cpp_lib_atomic_float should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
 # if !defined(_LIBCPP_HAS_NO_THREADS)
 #   ifndef __cpp_lib_atomic_is_always_lock_free
 #     error "__cpp_lib_atomic_is_always_lock_free should be defined in c++2a"
@@ -1588,6 +1692,19 @@
 #   endif
 # endif
 
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+#   ifndef __cpp_lib_atomic_lock_free_type_aliases
+#     error "__cpp_lib_atomic_lock_free_type_aliases should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_lock_free_type_aliases != 201907L
+#     error "__cpp_lib_atomic_lock_free_type_aliases should have the value 201907L in c++2a"
+#   endif
+# else
+#   ifdef __cpp_lib_atomic_lock_free_type_aliases
+#     error "__cpp_lib_atomic_lock_free_type_aliases should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!"
+#   endif
+# endif
+
 # if !defined(_LIBCPP_VERSION)
 #   ifndef __cpp_lib_atomic_ref
 #     error "__cpp_lib_atomic_ref should be defined in c++2a"
@@ -1601,6 +1718,45 @@
 #   endif
 # endif
 
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_atomic_shared_ptr
+#     error "__cpp_lib_atomic_shared_ptr should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_shared_ptr != 201711L
+#     error "__cpp_lib_atomic_shared_ptr should have the value 201711L in c++2a"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_atomic_shared_ptr
+#     error "__cpp_lib_atomic_shared_ptr should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_atomic_value_initialization
+#     error "__cpp_lib_atomic_value_initialization should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_value_initialization != 201911L
+#     error "__cpp_lib_atomic_value_initialization should have the value 201911L in c++2a"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_atomic_value_initialization
+#     error "__cpp_lib_atomic_value_initialization should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
+# if !defined(_LIBCPP_HAS_NO_THREADS)
+#   ifndef __cpp_lib_atomic_wait
+#     error "__cpp_lib_atomic_wait should be defined in c++2a"
+#   endif
+#   if __cpp_lib_atomic_wait != 201907L
+#     error "__cpp_lib_atomic_wait should have the value 201907L in c++2a"
+#   endif
+# else
+#   ifdef __cpp_lib_atomic_wait
+#     error "__cpp_lib_atomic_wait should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!"
+#   endif
+# endif
+
 # if !defined(_LIBCPP_VERSION)
 #   ifndef __cpp_lib_bind_front
 #     error "__cpp_lib_bind_front should be defined in c++2a"

diff  --git a/libcxx/test/support/cmpxchg_loop.h b/libcxx/test/support/cmpxchg_loop.h
index 50bd00a30bdb..e34160609813 100644
--- a/libcxx/test/support/cmpxchg_loop.h
+++ b/libcxx/test/support/cmpxchg_loop.h
@@ -8,8 +8,8 @@
 
 #include <atomic>
 
-template <class A, class T>
-bool cmpxchg_weak_loop(A& atomic, T& expected, T desired) {
+template <class A>
+bool cmpxchg_weak_loop(A& atomic, typename A::value_type& expected, typename A::value_type desired) {
   for (int i = 0; i < 10; i++) {
     if (atomic.compare_exchange_weak(expected, desired) == true) {
       return true;
@@ -19,8 +19,8 @@ bool cmpxchg_weak_loop(A& atomic, T& expected, T desired) {
   return false;
 }
 
-template <class A, class T>
-bool cmpxchg_weak_loop(A& atomic, T& expected, T desired,
+template <class A>
+bool cmpxchg_weak_loop(A& atomic, typename A::value_type& expected, typename A::value_type desired,
                        std::memory_order success,
                        std::memory_order failure) {
   for (int i = 0; i < 10; i++) {
@@ -33,8 +33,8 @@ bool cmpxchg_weak_loop(A& atomic, T& expected, T desired,
   return false;
 }
 
-template <class A, class T>
-bool c_cmpxchg_weak_loop(A* atomic, T* expected, T desired) {
+template <class A>
+bool c_cmpxchg_weak_loop(A* atomic, typename A::value_type* expected, typename A::value_type desired) {
   for (int i = 0; i < 10; i++) {
     if (std::atomic_compare_exchange_weak(atomic, expected, desired) == true) {
       return true;
@@ -44,8 +44,8 @@ bool c_cmpxchg_weak_loop(A* atomic, T* expected, T desired) {
   return false;
 }
 
-template <class A, class T>
-bool c_cmpxchg_weak_loop(A* atomic, T* expected, T desired,
+template <class A>
+bool c_cmpxchg_weak_loop(A* atomic, typename A::value_type* expected, typename A::value_type desired,
                          std::memory_order success,
                          std::memory_order failure) {
   for (int i = 0; i < 10; i++) {

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 6ad1a1856989..211702e9982c 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -613,6 +613,57 @@ def add_version_header(tc):
    },
    "headers": ["utility"],
    },
+  {"name": "__cpp_lib_atomic_flag_test",
+   "values": {
+     "c++2a": int(201907),
+   },
+   "headers": ["atomic"],
+   "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   },
+  {"name": "__cpp_lib_atomic_lock_free_type_aliases",
+   "values": {
+     "c++2a": int(201907),
+   },
+   "headers": ["atomic"],
+   "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   },
+  {"name": "__cpp_lib_atomic_wait",
+   "values": {
+     "c++2a": int(201907),
+   },
+   "headers": ["atomic"],
+   "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   },
+  {"name": "__cpp_lib_atomic_float",
+   "values": {
+     "c++2a": int(201711),
+   },
+   "headers": ["atomic"],
+   "unimplemented": True,
+   "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   },
+  {"name": "__cpp_lib_atomic_shared_ptr",
+   "values": {
+     "c++2a": int(201711),
+   },
+   "headers": ["atomic"],
+   "unimplemented": True,
+   "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   },
+  {"name": "__cpp_lib_atomic_value_initialization",
+   "values": {
+     "c++2a": int(201911),
+   },
+   "headers": ["atomic", "memory"],
+   "unimplemented": True,
+   "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
+   },
 ]], key=lambda tc: tc["name"])
 
 def get_std_dialects():


        


More information about the libcxx-commits mailing list