diff --git a/libcxx/include/atomic b/libcxx/include/atomic --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -2171,7 +2171,8 @@ _LIBCPP_INLINE_VISIBILITY typename enable_if < - is_integral<_Tp>::value && !is_same<_Tp, bool>::value && !is_const<_Tp>::value, + (is_integral<_Tp>::value && !is_same<_Tp, bool>::value && !is_const<_Tp>::value) || + (is_pointer<_Tp>::value && is_object::type>::value && !is_const<_Tp>::value), _Tp >::type atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT @@ -2183,7 +2184,8 @@ _LIBCPP_INLINE_VISIBILITY typename enable_if < - is_integral<_Tp>::value && !is_same<_Tp, bool>::value && !is_const<_Tp>::value, + (is_integral<_Tp>::value && !is_same<_Tp, bool>::value && !is_const<_Tp>::value) || + (is_pointer<_Tp>::value && is_object::type>::value && !is_const<_Tp>::value), _Tp >::type atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT @@ -2191,6 +2193,7 @@ return __o->fetch_add(__op); } +#ifdef DO_WE_WANT_TO_KEEP_THIS_COMPILER_EXTENSION template _LIBCPP_INLINE_VISIBILITY _Tp* @@ -2206,6 +2209,7 @@ { return __o->fetch_add(__op); } +#endif // atomic_fetch_add_explicit diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.pass.cpp @@ -11,21 +11,13 @@ // -// template -// Integral -// atomic_fetch_add(volatile atomic* obj, Integral op); -// -// template -// Integral -// atomic_fetch_add(atomic* obj, Integral op); -// // template // T* -// atomic_fetch_add(volatile atomic* obj, ptrdiff_t op); +// atomic_fetch_add(volatile atomic* obj, typename atomic::difference_type) noexcept; // // template // T* -// atomic_fetch_add(atomic* obj, ptrdiff_t op); +// atomic_fetch_add(atomic* obj, typename atomic::difference_type) noexcept; #include #include @@ -63,12 +55,22 @@ A t; std::atomic_init(&t, T(1*sizeof(X))); assert(std::atomic_fetch_add(&t, 2) == T(1*sizeof(X))); -#ifdef _LIBCPP_VERSION // libc++ is nonconforming + /* + * This doesn't compile with MSVC or GCC, but works with current Clang. + * Do we want to keep this? + */ std::atomic_fetch_add(&t, 0); -#else + assert(t == T(3*sizeof(X))); + } + { + typedef std::atomic A; + typedef typename std::remove_pointer::type X; + A t; + std::atomic_init(&t, T(1*sizeof(X))); + assert(std::atomic_fetch_add(&t, 2) == T(1*sizeof(X))); std::atomic_fetch_add(&t, 0); -#endif // _LIBCPP_VERSION assert(t == T(3*sizeof(X))); + ASSERT_NOEXCEPT(std::atomic_fetch_add(&t, 0)); } { typedef std::atomic A; @@ -76,12 +78,9 @@ volatile A t; std::atomic_init(&t, T(1*sizeof(X))); assert(std::atomic_fetch_add(&t, 2) == T(1*sizeof(X))); -#ifdef _LIBCPP_VERSION // libc++ is nonconforming - std::atomic_fetch_add(&t, 0); -#else std::atomic_fetch_add(&t, 0); -#endif // _LIBCPP_VERSION assert(t == T(3*sizeof(X))); + ASSERT_NOEXCEPT(std::atomic_fetch_add(&t, 0)); } }