[libcxx-commits] [PATCH] D103983: [libc++][rfc] Improve atomic_fetch_(add|sub).*.

Mark de Wever via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jul 12 13:03:08 PDT 2021


Mordante marked an inline comment as done.
Mordante added a comment.

Thanks for the review!



================
Comment at: libcxx/include/atomic:1851
     _LIBCPP_INLINE_VISIBILITY
-    _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst)
-                                                                        volatile _NOEXCEPT
+    typename enable_if<is_same<_Tp, _Up>::value && is_object<_Up>::value, _Up*>::type
+    fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
----------------
Quuxplusone wrote:
> Mordante wrote:
> > I'm not too happy with this way to constrain the function. I'm open to better suggestions.
> I recommend:
> ```
> _LIBCPP_INLINE_VISIBILITY
> _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT
>     {return __cxx_atomic_fetch_add(&this->__a_, __op, __m);}
> ```
> This follows the Standard's specification exactly, and also is simple (no weird metaprogramming involved). Also, this is what libstdc++ does. (MSVC essentially handles this via a partial specialization: they `conditional_t` between `_Atomic_pointer` and `_Atomic_storage` depending on whether the pointer is an object pointer type. But we don't need to do that, the standard doesn't do that, and libstdc++ doesn't do that. Let's Keep It Simple.)
> 
> If you want to explicitly nod to the "Mandates:" in http://eel.is/c++draft/atomics.types.pointer#5 , then I recommend
> ```
> _LIBCPP_INLINE_VISIBILITY
> _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
>     static_assert(is_object<typename remove_pointer<_Tp>::type>::value, "Must be an object pointer type");
>     return __cxx_atomic_fetch_add(&this->__a_, __op, __m);
> }
> ```
I'll have a look at the other two implementations. However we need to do something else we do arithmetic on a function pointer. Or do you mean that Clang should protect us against that behavior? When I don't disable the function pointer here it allows function pointers.


================
Comment at: libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.verify.cpp:26
+    volatile std::atomic<void*> obj;
+    // expected-error at atomic:* {{no matching member function for call to 'fetch_sub'}}
+    std::atomic_fetch_sub_explicit(&obj, 0, std::memory_order_relaxed);
----------------
Quuxplusone wrote:
> .verify.cpp tests are run only on libc++? This test wouldn't pass against libstdc++, for example, because libstdc++ doesn't SFINAE away `fetch_sub` in these cases. (There'd still be an error; it'd just be a //different// error, because subtracting from a `void*` is ill-formed.)
Correct these tests are only executed with Clang and libc++. So here it's valid to validate against Clang specific diagnostics.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103983/new/

https://reviews.llvm.org/D103983



More information about the libcxx-commits mailing list