Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++] constexpr atomic and atomic_ref #98765

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

hanickadot
Copy link
Contributor

This is implementation of constexpr atomic<T> and atomic_ref<T>. This PR depends on #98756

It's missing library tests (language PR contains tests) which will be added.

I'm not sure how is the proper way to make the constexpr support conditional, for now it's allowed in c++26 mode only.

@hanickadot hanickadot requested a review from a team as a code owner July 13, 2024 19:30
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jul 13, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jul 13, 2024

@llvm/pr-subscribers-libcxx

Author: Hana Dusíková (hanickadot)

Changes

This is implementation of constexpr atomic&lt;T&gt; and atomic_ref&lt;T&gt;. This PR depends on #98756

It's missing library tests (language PR contains tests) which will be added.

I'm not sure how is the proper way to make the constexpr support conditional, for now it's allowed in c++26 mode only.


Patch is 79.49 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/98765.diff

7 Files Affected:

  • (modified) libcxx/include/__atomic/atomic.h (+52-43)
  • (modified) libcxx/include/__atomic/atomic_base.h (+46-30)
  • (modified) libcxx/include/__atomic/atomic_flag.h (+37-23)
  • (modified) libcxx/include/__atomic/atomic_ref.h (+214-100)
  • (modified) libcxx/include/__atomic/cxx_atomic_impl.h (+42-35)
  • (modified) libcxx/include/__config (+6)
  • (modified) libcxx/include/version (+3)
diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index bd3f659c22df0..4a72f61d019fc 100644
--- a/libcxx/include/__atomic/atomic.h
+++ b/libcxx/include/__atomic/atomic.h
@@ -67,7 +67,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
   using value_type      = _Tp*;
   using difference_type = ptrdiff_t;
 
-  _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 atomic() _NOEXCEPT = default;
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
 
@@ -75,7 +75,7 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
     __base::store(__d);
     return __d;
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator=(_Tp* __d) _NOEXCEPT {
     __base::store(__d);
     return __d;
   }
@@ -86,7 +86,8 @@ 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_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp*
+  fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
     // __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);
@@ -98,24 +99,25 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
     return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp*
+  fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
     // __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);
   }
 
   _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 _LIBCPP_CONSTEXPR_SINCE_CXX26 _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) _NOEXCEPT { return fetch_sub(1); }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _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++() _NOEXCEPT { return fetch_add(1) + 1; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _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--() _NOEXCEPT { return fetch_sub(1) - 1; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _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+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _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) _NOEXCEPT { return fetch_sub(__op) - __op; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
 
   atomic& operator=(const atomic&)          = delete;
   atomic& operator=(const atomic&) volatile = delete;
@@ -151,7 +153,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
   }
 
   template <class _This, class _Operation, class _BuiltinOp>
-  _LIBCPP_HIDE_FROM_ABI static _Tp
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Tp
   __rmw_op(_This&& __self, _Tp __operand, memory_order __m, _Operation __operation, _BuiltinOp __builtin_op) {
     if constexpr (__has_rmw_builtin()) {
       return __builtin_op(std::addressof(std::forward<_This>(__self).__a_), __operand, __m);
@@ -174,7 +176,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
   }
 
   template <class _This>
-  _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_add(_This&& __self, _Tp __operand, memory_order __m) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Tp __fetch_add(_This&& __self, _Tp __operand, memory_order __m) {
     auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {
       return std::__cxx_atomic_fetch_add(__a, __builtin_operand, __order);
     };
@@ -182,7 +184,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
   }
 
   template <class _This>
-  _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_sub(_This&& __self, _Tp __operand, memory_order __m) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static _Tp __fetch_sub(_This&& __self, _Tp __operand, memory_order __m) {
     auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {
       return std::__cxx_atomic_fetch_sub(__a, __builtin_operand, __order);
     };
@@ -207,7 +209,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
     __base::store(__d);
     return __d;
   }
-  _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) noexcept {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator=(_Tp __d) noexcept {
     __base::store(__d);
     return __d;
   }
@@ -218,7 +220,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
     return __fetch_add(*this, __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
     return __fetch_add(*this, __op, __m);
   }
 
@@ -228,7 +230,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
     return __fetch_sub(*this, __op, __m);
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
     return __fetch_sub(*this, __op, __m);
   }
 
@@ -238,7 +240,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
     return fetch_add(__op) + __op;
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) noexcept { return fetch_add(__op) + __op; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _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
@@ -246,7 +248,7 @@ struct atomic<_Tp> : __atomic_base<_Tp> {
     return fetch_sub(__op) - __op;
   }
 
-  _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) noexcept { return fetch_sub(__op) - __op; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp operator-=(_Tp __op) noexcept { return fetch_sub(__op) - __op; }
 };
 
 #endif // _LIBCPP_STD_VER >= 20
@@ -272,7 +274,7 @@ atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NO
 }
 
 template <class _Tp>
-_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CONSTEXPR_SINCE_CXX26 _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);
 }
@@ -285,7 +287,8 @@ _LIBCPP_HIDE_FROM_ABI void atomic_store(volatile atomic<_Tp>* __o, typename atom
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI void atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
+atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
   __o->store(__d);
 }
 
@@ -299,7 +302,7 @@ atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_typ
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
 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);
@@ -313,7 +316,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT {
   return __o->load();
 }
 
@@ -326,7 +329,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const volatile atomic<_Tp>* __o,
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
     _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
   return __o->load(__m);
 }
@@ -339,7 +342,8 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(volatile atomic<_Tp>* __o, typename at
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
+atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
   return __o->exchange(__d);
 }
 
@@ -352,7 +356,7 @@ atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _Tp
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
 atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {
   return __o->exchange(__d, __m);
 }
@@ -366,7 +370,7 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool 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);
 }
@@ -380,7 +384,7 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool 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);
 }
@@ -398,7 +402,7 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool atomic_compare_exchange_weak_explicit(
     atomic<_Tp>* __o,
     typename atomic<_Tp>::value_type* __e,
     typename atomic<_Tp>::value_type __d,
@@ -420,7 +424,7 @@ _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool atomic_compare_exchange_strong_explicit(
     atomic<_Tp>* __o,
     typename atomic<_Tp>::value_type* __e,
     typename atomic<_Tp>::value_type __d,
@@ -438,7 +442,7 @@ atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __
 }
 
 template <class _Tp>
-_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
 atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {
   return __o->wait(__v);
 }
@@ -453,7 +457,7 @@ atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::valu
 }
 
 template <class _Tp>
-_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
 atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT
     _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
   return __o->wait(__v, __m);
@@ -467,7 +471,7 @@ atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT {
   __o->notify_one();
 }
 template <class _Tp>
-_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
 atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT {
   __o->notify_one();
 }
@@ -480,7 +484,7 @@ atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT {
   __o->notify_all();
 }
 template <class _Tp>
-_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
+_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
 atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT {
   __o->notify_all();
 }
@@ -494,7 +498,8 @@ atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_typ
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
+atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
   return __o->fetch_add(__op);
 }
 
@@ -507,7 +512,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add_explicit(
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _Tp
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
 atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
   return __o->fetch_add(__op, __m);
 }
@@ -521,7 +526,8 @@ atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_typ
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
+atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
   return __o->fetch_sub(__op);
 }
 
@@ -534,7 +540,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub_explicit(
 }
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _Tp
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
 atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
   return __o->fetch_sub(__op, __m);
 }
@@ -547,7 +553,8 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(volatile atomic<_Tp>* __o, typename a
 }
 
 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
+atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
   return __o->fetch_and(__op);
 }
 
@@ -560,7 +567,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and_explicit(
 }
 
 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _Tp
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
 atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
   return __o->fetch_and(__op, __m);
 }
@@ -573,7 +580,8 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(volatile atomic<_Tp>* __o, typename at
 }
 
 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
+atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
   return __o->fetch_or(__op);
 }
 
@@ -586,7 +594,7 @@ atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_
 }
 
 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _Tp
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
 atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
   return __o->fetch_or(__op, __m);
 }
@@ -599,7 +607,8 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(volatile atomic<_Tp>* __o, typename a
 }
 
 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
+atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
   return __o->fetch_xor(__op);
 }
 
@@ -612,7 +621,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor_explicit(
 }
 
 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _Tp
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp
 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/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h
index 7e26434c9c3a0..22e898f736674 100644
--- a/libcxx/include/__atomic/atomic_base.h
+++ b/libcxx/include/__atomic/atomic_base.h
@@ -40,13 +40,13 @@ struct __atomic_base // false
     return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>));
   }
   _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const _NOEXCEPT {
-    return static_cast<__atomic_base const volatile*>(this)->is_lock_free();
+    return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>));
   }
   _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
       _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
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT
       _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
     std::__cxx_atomic_store(std::addressof(__a_), __d, __m);
   }
@@ -54,16 +54,16 @@ struct __atomic_base // false
       _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
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _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 { return load(); }
-  _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 operator _Tp() const _NOEXCEPT { return load(); }
   _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
     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 {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
     return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m);
   }
   _LIBCPP_HIDE_FROM_ABI bool
@@ -71,7 +71,8 @@ struct __atomic_base // false
       _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 compa...
[truncated]

Copy link

github-actions bot commented Jul 13, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@philnik777 philnik777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation itself looks pretty good to me. Everything seems fairly straight-forward.

I'm not sure how is the proper way to make the constexpr support conditional, for now it's allowed in c++26 mode only.

I'm not sure what you mean here with "how to make the constexpr support conditional". Allowing it only for C++26 seems like the right thing to do to me.

libcxx/include/__atomic/atomic_base.h Outdated Show resolved Hide resolved
libcxx/include/__atomic/atomic_base.h Outdated Show resolved Hide resolved
libcxx/include/__atomic/atomic_ref.h Outdated Show resolved Hide resolved
libcxx/include/version Outdated Show resolved Hide resolved
@hanickadot
Copy link
Contributor Author

I'm not sure what you mean here with "how to make the constexpr support conditional". Allowing it only for C++26 seems like the right thing to do to me.

I mean this will work with clang with apropriate change, but libc++ is working with other compilers, so the support should be enabled conditionally constexpr conditionally so user won't get scary error about insides of atomic<T> if they will try to use it on compiler without atomic builtins support.

@philnik777
Copy link
Contributor

I'm not sure what you mean here with "how to make the constexpr support conditional". Allowing it only for C++26 seems like the right thing to do to me.

I mean this will work with clang with apropriate change, but libc++ is working with other compilers, so the support should be enabled conditionally constexpr conditionally so user won't get scary error about insides of atomic<T> if they will try to use it on compiler without atomic builtins support.

Ah, OK. Are there actually any errors generated? We're in a template, so that might not actually be a problem. If there are diagnostics I think we want something like

#if __has_constexpr_builtin(whatever)
#  define _LIBCPP_ATOMIC_CONSTEXPR _LIBCPP_CONSTEXPR_SINCE_CXX26
#else
#  define _LIBCPP_ATOMIC_CONSTEXPR
#endif

and then just use _LIBCPP_ATOMIC_CONSTEXPR throughout instead of _LIBCPP_CONSTEXPR_SINCE_CXX26.

@hanickadot
Copy link
Contributor Author

I'm not sure what you mean here with "how to make the constexpr support conditional". Allowing it only for C++26 seems like the right thing to do to me.

I mean this will work with clang with apropriate change, but libc++ is working with other compilers, so the support should be enabled conditionally constexpr conditionally so user won't get scary error about insides of atomic<T> if they will try to use it on compiler without atomic builtins support.

Ah, OK. Are there actually any errors generated? We're in a template, so that might not actually be a problem. If there are diagnostics I think we want something like

#if __has_constexpr_builtin(whatever)
#  define _LIBCPP_ATOMIC_CONSTEXPR _LIBCPP_CONSTEXPR_SINCE_CXX26
#else
#  define _LIBCPP_ATOMIC_CONSTEXPR
#endif

and then just use _LIBCPP_ATOMIC_CONSTEXPR throughout instead of _LIBCPP_CONSTEXPR_SINCE_CXX26.

Where do you recommend to put it?

@philnik777
Copy link
Contributor

probably in cxx_atomic_impl.h

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants