diff --git a/libcxx/docs/Cxx2aStatus.rst b/libcxx/docs/Cxx2aStatus.rst --- a/libcxx/docs/Cxx2aStatus.rst +++ b/libcxx/docs/Cxx2aStatus.rst @@ -42,8 +42,8 @@ .. [#note-P0600] P0600: The missing bits in P0600 are in |sect|\ [mem.res.class], |sect|\ [mem.poly.allocator.class], and |sect|\ [container.node.overview]. .. [#note-P0966] P0966: It was previously erroneously marked as complete in version 8.0. See `bug 45368 `__. - .. [#note-P0619] P0619: Only sections D.8, D.9, and D.10 are implemented. Sections D.4, D.7, D.11, D.12, and D.14 remain undone. + .. [#note-P0883] P0883: shared_ptr and floating-point changes weren't applied as they themselves aren't implemented yet. .. _issues-status-cxx2a: diff --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv --- a/libcxx/docs/Cxx2aStatusPaperStatus.csv +++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv @@ -133,7 +133,7 @@ "`P1661 `__","LWG","Remove dedicated precalculated hash lookup interface","Cologne","|Nothing To Do|","" "`P1754 `__","LWG","Rename concepts to standard_case for C++20, while we still can","Cologne","|In Progress|","" "","","","","","" -"`P0883 `__","LWG","Fixing Atomic Initialization","Belfast","* *","" +"`P0883 `__","LWG","Fixing Atomic Initialization","Belfast","|Complete| [#note-P0883]","13.0" "`P1391 `__","LWG","Range constructor for std::string_view","Belfast","* *","" "`P1394 `__","LWG","Range constructor for std::span","Belfast","* *","" "`P1456 `__","LWG","Move-only views","Belfast","* *","" diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -182,7 +182,7 @@ ------------------------------------------------- ----------------- ``__cpp_lib_atomic_shared_ptr`` *unimplemented* ------------------------------------------------- ----------------- - ``__cpp_lib_atomic_value_initialization`` *unimplemented* + ``__cpp_lib_atomic_value_initialization`` ``201911L`` ------------------------------------------------- ----------------- ``__cpp_lib_atomic_wait`` ``201907L`` ------------------------------------------------- ----------------- diff --git a/libcxx/include/atomic b/libcxx/include/atomic --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -67,7 +67,8 @@ bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; - atomic() noexcept = default; + atomic() noexcept = default; // until C++20 + constexpr atomic() noexcept(is_nothrow_default_constructible_v); // since C++20 constexpr atomic(T desr) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; @@ -201,7 +202,8 @@ bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; - atomic() noexcept = default; + atomic() noexcept = default; // until C++20 + constexpr atomic() noexcept; // since C++20 constexpr atomic(T* desr) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; @@ -509,7 +511,8 @@ typedef struct atomic_flag { - atomic_flag() noexcept = default; + atomic_flag() noexcept = default; // until C++20 + constexpr atomic_flag() noexcept; // since C++20 atomic_flag(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) = delete; atomic_flag& operator=(const atomic_flag&) volatile = delete; @@ -1680,8 +1683,13 @@ _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() _NOEXCEPT {__cxx_atomic_notify_all(&__a_);} +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY constexpr + __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {} +#else _LIBCPP_INLINE_VISIBILITY __atomic_base() _NOEXCEPT _LIBCPP_DEFAULT +#endif _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {} @@ -1707,8 +1715,10 @@ : public __atomic_base<_Tp, false> { typedef __atomic_base<_Tp, false> __base; - _LIBCPP_INLINE_VISIBILITY + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 __atomic_base() _NOEXCEPT _LIBCPP_DEFAULT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} @@ -1790,8 +1800,15 @@ typedef __atomic_base<_Tp> __base; typedef _Tp value_type; typedef value_type difference_type; + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + atomic() = default; +#else _LIBCPP_INLINE_VISIBILITY atomic() _NOEXCEPT _LIBCPP_DEFAULT +#endif + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {} @@ -1815,8 +1832,10 @@ typedef __atomic_base<_Tp*> __base; typedef _Tp* value_type; typedef ptrdiff_t difference_type; + _LIBCPP_INLINE_VISIBILITY atomic() _NOEXCEPT _LIBCPP_DEFAULT + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {} @@ -1892,7 +1911,7 @@ // atomic_init template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY void atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { @@ -1900,7 +1919,7 @@ } template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY void atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT { @@ -2541,8 +2560,13 @@ void notify_all() _NOEXCEPT {__cxx_atomic_notify_all(&__a_);} +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY constexpr + atomic_flag() _NOEXCEPT : __a_(false) {} +#else _LIBCPP_INLINE_VISIBILITY atomic_flag() _NOEXCEPT _LIBCPP_DEFAULT +#endif _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -283,7 +283,7 @@ // # define __cpp_lib_atomic_shared_ptr 201711L # endif # if !defined(_LIBCPP_HAS_NO_THREADS) -// # define __cpp_lib_atomic_value_initialization 201911L +# define __cpp_lib_atomic_value_initialization 201911L # endif # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) # define __cpp_lib_atomic_wait 201907L diff --git a/libcxx/test/libcxx/atomics/atomics.align/align.pass.pass.cpp b/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp rename from libcxx/test/libcxx/atomics/atomics.align/align.pass.pass.cpp rename to libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp --- a/libcxx/test/libcxx/atomics/atomics.align/align.pass.pass.cpp +++ b/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp @@ -8,6 +8,13 @@ // // UNSUPPORTED: libcpp-has-no-threads, c++03 // REQUIRES: is-lockfree-runtime-function +// ADDITIONAL_COMPILE_FLAGS: -Wno-psabi +// ... since C++20 std::__atomic_base initializes, so we get a warning about an +// ABI change for vector variants since the constructor code for that is +// different if one were to compile with architecture-specific vector +// extensions enabled. +// This however isn't ABI breaking as it was impossible for any code to trigger +// this without using libc++ internals. // GCC currently fails because it needs -fabi-version=6 to fix mangling of // std::atomic when used with __attribute__((vector(X))). diff --git a/libcxx/test/std/atomics/atomics.types.generic/address.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/address.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.generic/address.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.generic/address.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // // UNSUPPORTED: libcpp-has-no-threads -// ... test case crashes clang. // @@ -82,13 +81,9 @@ { typedef typename std::remove_pointer::type X; A obj(T(0)); + assert(obj == T(0)); bool b0 = obj.is_lock_free(); ((void)b0); // mark as unused - assert(obj == T(0)); - std::atomic_init(&obj, T(1)); - assert(obj == T(1)); - std::atomic_init(&obj, T(2)); - assert(obj == T(2)); obj.store(T(0)); assert(obj == T(0)); obj.store(T(1), std::memory_order_release); diff --git a/libcxx/test/std/atomics/atomics.types.generic/bool.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/bool.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.generic/bool.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.generic/bool.pass.cpp @@ -63,10 +63,6 @@ { volatile std::atomic obj(true); assert(obj == true); - std::atomic_init(&obj, false); - assert(obj == false); - std::atomic_init(&obj, true); - assert(obj == true); bool b0 = obj.is_lock_free(); (void)b0; // to placate scan-build obj.store(false); @@ -118,10 +114,6 @@ { std::atomic obj(true); assert(obj == true); - std::atomic_init(&obj, false); - assert(obj == false); - std::atomic_init(&obj, true); - assert(obj == true); bool b0 = obj.is_lock_free(); (void)b0; // to placate scan-build obj.store(false); @@ -173,10 +165,6 @@ { std::atomic_bool obj(true); assert(obj == true); - std::atomic_init(&obj, false); - assert(obj == false); - std::atomic_init(&obj, true); - assert(obj == true); bool b0 = obj.is_lock_free(); (void)b0; // to placate scan-build obj.store(false); diff --git a/libcxx/test/std/atomics/atomics.types.generic/constexpr_noexcept.compile.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/constexpr_noexcept.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.types.generic/constexpr_noexcept.compile.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-has-no-threads + +#include + +#include "test_macros.h" + +template +constexpr bool test() { + [[maybe_unused]] constexpr T a; + static_assert(std::is_nothrow_constructible_v); + ASSERT_NOEXCEPT(T{}); + return true; +} + +struct throwing { + throwing() {} +}; + +struct trivial { + int a; +}; + +void test() { + static_assert(test>()); + static_assert(test>()); + static_assert(test>()); + static_assert(test>()); + static_assert(test()); + + static_assert(!std::is_nothrow_constructible_v>); + ASSERT_NOT_NOEXCEPT(std::atomic{}); +} diff --git a/libcxx/test/std/atomics/atomics.types.generic/integral.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/integral.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.generic/integral.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.generic/integral.pass.cpp @@ -99,10 +99,6 @@ { A obj(T(0)); assert(obj == T(0)); - std::atomic_init(&obj, T(1)); - assert(obj == T(1)); - std::atomic_init(&obj, T(2)); - assert(obj == T(2)); bool b0 = obj.is_lock_free(); ((void)b0); // mark as unused obj.store(T(0)); diff --git a/libcxx/test/std/atomics/atomics.types.generic/throw.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/throw.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.types.generic/throw.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-has-no-threads +// UNSUPPORTED: no-exceptions + +// + +#include +#include + +struct throwing { + throwing() { throw 42; } +}; + +int main(int, char**) { + try { + [[maybe_unused]] std::atomic a; + assert(false); + } catch (int x) { + assert(x == 42); + } + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp @@ -32,9 +32,8 @@ void operator()() const { { typedef std::atomic A; - A a; T t(T(1)); - std::atomic_init(&a, t); + A a(t); assert(std::atomic_compare_exchange_strong(&a, &t, T(2)) == true); assert(a == T(2)); assert(t == T(1)); @@ -44,9 +43,8 @@ } { typedef std::atomic A; - volatile A a; T t(T(1)); - std::atomic_init(&a, t); + volatile A a(t); assert(std::atomic_compare_exchange_strong(&a, &t, T(2)) == true); assert(a == T(2)); assert(t == T(1)); diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp @@ -35,9 +35,8 @@ void operator()() const { { typedef std::atomic A; - A a; T t(T(1)); - std::atomic_init(&a, t); + A a(t); assert(std::atomic_compare_exchange_strong_explicit(&a, &t, T(2), std::memory_order_seq_cst, std::memory_order_seq_cst) == true); assert(a == T(2)); @@ -49,9 +48,8 @@ } { typedef std::atomic A; - volatile A a; T t(T(1)); - std::atomic_init(&a, t); + volatile A a(t); assert(std::atomic_compare_exchange_strong_explicit(&a, &t, T(2), std::memory_order_seq_cst, std::memory_order_seq_cst) == true); assert(a == T(2)); diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp @@ -33,9 +33,8 @@ void operator()() const { { typedef std::atomic A; - A a; T t(T(1)); - std::atomic_init(&a, t); + A a(t); assert(c_cmpxchg_weak_loop(&a, &t, T(2)) == true); assert(a == T(2)); assert(t == T(1)); @@ -45,9 +44,8 @@ } { typedef std::atomic A; - volatile A a; T t(T(1)); - std::atomic_init(&a, t); + volatile A a(t); assert(c_cmpxchg_weak_loop(&a, &t, T(2)) == true); assert(a == T(2)); assert(t == T(1)); diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp @@ -37,9 +37,8 @@ void operator()() const { { typedef std::atomic A; - A a; T t(T(1)); - std::atomic_init(&a, t); + A a(t); assert(c_cmpxchg_weak_loop(&a, &t, T(2), std::memory_order_seq_cst, std::memory_order_seq_cst) == true); assert(a == T(2)); @@ -51,9 +50,8 @@ } { typedef std::atomic A; - volatile A a; T t(T(1)); - std::atomic_init(&a, t); + volatile A a(t); assert(c_cmpxchg_weak_loop(&a, &t, T(2), std::memory_order_seq_cst, std::memory_order_seq_cst) == true); assert(a == T(2)); diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp @@ -31,12 +31,10 @@ struct TestFn { void operator()() const { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_exchange(&t, T(2)) == T(1)); assert(t == T(2)); - volatile A vt; - std::atomic_init(&vt, T(3)); + volatile A vt(T(3)); assert(std::atomic_exchange(&vt, T(4)) == T(3)); assert(vt == T(4)); } diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp @@ -31,13 +31,11 @@ struct TestFn { void operator()() const { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_exchange_explicit(&t, T(2), std::memory_order_seq_cst) == T(1)); assert(t == T(2)); - volatile A vt; - std::atomic_init(&vt, T(3)); + volatile A vt(T(3)); assert(std::atomic_exchange_explicit(&vt, T(4), std::memory_order_seq_cst) == T(3)); assert(vt == T(4)); 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 @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // // UNSUPPORTED: libcpp-has-no-threads -// ... test crashes clang // @@ -39,15 +38,13 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_fetch_add(&t, T(2)) == T(1)); assert(t == T(3)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(1)); + volatile A t(T(1)); assert(std::atomic_fetch_add(&t, T(2)) == T(1)); assert(t == T(3)); } @@ -60,8 +57,7 @@ { typedef std::atomic A; typedef typename std::remove_pointer::type X; - A t; - std::atomic_init(&t, T(1*sizeof(X))); + A 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); @@ -73,8 +69,7 @@ { typedef std::atomic A; typedef typename std::remove_pointer::type X; - volatile A t; - std::atomic_init(&t, T(1*sizeof(X))); + volatile A 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); diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // // UNSUPPORTED: libcpp-has-no-threads -// ... test crashes clang // @@ -39,16 +38,14 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_fetch_add_explicit(&t, T(2), std::memory_order_seq_cst) == T(1)); assert(t == T(3)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(1)); + volatile A t(T(1)); assert(std::atomic_fetch_add_explicit(&t, T(2), std::memory_order_seq_cst) == T(1)); assert(t == T(3)); @@ -63,8 +60,7 @@ { typedef std::atomic A; typedef typename std::remove_pointer::type X; - A t; - std::atomic_init(&t, T(1*sizeof(X))); + A t(T(1 * sizeof(X))); assert(std::atomic_fetch_add_explicit(&t, 2, std::memory_order_seq_cst) == T(1*sizeof(X))); #ifdef _LIBCPP_VERSION // libc++ is not conforming @@ -77,8 +73,7 @@ { typedef std::atomic A; typedef typename std::remove_pointer::type X; - volatile A t; - std::atomic_init(&t, T(1*sizeof(X))); + volatile A t(T(1 * sizeof(X))); assert(std::atomic_fetch_add_explicit(&t, 2, std::memory_order_seq_cst) == T(1*sizeof(X))); #ifdef _LIBCPP_VERSION // libc++ is not conforming diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and.pass.cpp @@ -30,15 +30,13 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_fetch_and(&t, T(2)) == T(1)); assert(t == T(0)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(3)); + volatile A t(T(3)); assert(std::atomic_fetch_and(&t, T(2)) == T(3)); assert(t == T(2)); } diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and_explicit.pass.cpp @@ -30,16 +30,14 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_fetch_and_explicit(&t, T(2), std::memory_order_seq_cst) == T(1)); assert(t == T(0)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(3)); + volatile A t(T(3)); assert(std::atomic_fetch_and_explicit(&t, T(2), std::memory_order_seq_cst) == T(3)); assert(t == T(2)); diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or.pass.cpp @@ -30,15 +30,13 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_fetch_or(&t, T(2)) == T(1)); assert(t == T(3)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(3)); + volatile A t(T(3)); assert(std::atomic_fetch_or(&t, T(2)) == T(3)); assert(t == T(3)); } diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or_explicit.pass.cpp @@ -30,16 +30,14 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_fetch_or_explicit(&t, T(2), std::memory_order_seq_cst) == T(1)); assert(t == T(3)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(3)); + volatile A t(T(3)); assert(std::atomic_fetch_or_explicit(&t, T(2), std::memory_order_seq_cst) == T(3)); assert(t == T(3)); diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // // UNSUPPORTED: libcpp-has-no-threads -// ... test crashes clang // @@ -39,15 +38,13 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(3)); + A t(T(3)); assert(std::atomic_fetch_sub(&t, T(2)) == T(3)); assert(t == T(1)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(3)); + volatile A t(T(3)); assert(std::atomic_fetch_sub(&t, T(2)) == T(3)); assert(t == T(1)); } @@ -60,8 +57,7 @@ { typedef std::atomic A; typedef typename std::remove_pointer::type X; - A t; - std::atomic_init(&t, T(3*sizeof(X))); + A t(T(3 * sizeof(X))); assert(std::atomic_fetch_sub(&t, 2) == T(3*sizeof(X))); #ifdef _LIBCPP_VERSION // libc++ is nonconforming std::atomic_fetch_sub(&t, 0); @@ -73,8 +69,7 @@ { typedef std::atomic A; typedef typename std::remove_pointer::type X; - volatile A t; - std::atomic_init(&t, T(3*sizeof(X))); + volatile A t(T(3 * sizeof(X))); assert(std::atomic_fetch_sub(&t, 2) == T(3*sizeof(X))); #ifdef _LIBCPP_VERSION // libc++ is nonconforming std::atomic_fetch_sub(&t, 0); diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // // UNSUPPORTED: libcpp-has-no-threads -// ... test crashes clang // @@ -40,16 +39,14 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(3)); + A t(T(3)); assert(std::atomic_fetch_sub_explicit(&t, T(2), std::memory_order_seq_cst) == T(3)); assert(t == T(1)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(3)); + volatile A t(T(3)); assert(std::atomic_fetch_sub_explicit(&t, T(2), std::memory_order_seq_cst) == T(3)); assert(t == T(1)); @@ -63,8 +60,7 @@ { typedef std::atomic A; typedef typename std::remove_pointer::type X; - A t; - std::atomic_init(&t, T(3*sizeof(X))); + A t(T(3 * sizeof(X))); assert(std::atomic_fetch_sub_explicit(&t, 2, std::memory_order_seq_cst) == T(3*sizeof(X))); #ifdef _LIBCPP_VERSION // libc++ is nonconforming @@ -77,8 +73,7 @@ { typedef std::atomic A; typedef typename std::remove_pointer::type X; - volatile A t; - std::atomic_init(&t, T(3*sizeof(X))); + volatile A t(T(3 * sizeof(X))); assert(std::atomic_fetch_sub_explicit(&t, 2, std::memory_order_seq_cst) == T(3*sizeof(X))); #ifdef _LIBCPP_VERSION // libc++ is nonconforming diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor.pass.cpp @@ -30,15 +30,13 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_fetch_xor(&t, T(2)) == T(1)); assert(t == T(3)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(3)); + volatile A t(T(3)); assert(std::atomic_fetch_xor(&t, T(2)) == T(3)); assert(t == T(1)); } diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor_explicit.pass.cpp @@ -30,16 +30,14 @@ void operator()() const { { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_fetch_xor_explicit(&t, T(2), std::memory_order_seq_cst) == T(1)); assert(t == T(3)); } { typedef std::atomic A; - volatile A t; - std::atomic_init(&t, T(3)); + volatile A t(T(3)); assert(std::atomic_fetch_xor_explicit(&t, T(2), std::memory_order_seq_cst) == T(3)); assert(t == T(1)); diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp @@ -9,6 +9,7 @@ // UNSUPPORTED: libcpp-has-no-threads // XFAIL: !non-lockfree-atomics // ... assertion fails line 36 +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp @@ -31,11 +31,9 @@ struct TestFn { void operator()() const { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_load(&t) == T(1)); - volatile A vt; - std::atomic_init(&vt, T(2)); + volatile A vt(T(2)); assert(std::atomic_load(&vt) == T(2)); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp @@ -31,11 +31,9 @@ struct TestFn { void operator()() const { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_load_explicit(&t, std::memory_order_seq_cst) == T(1)); - volatile A vt; - std::atomic_init(&vt, T(2)); + volatile A vt(T(2)); assert(std::atomic_load_explicit(&vt, std::memory_order_seq_cst) == T(2)); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp @@ -36,8 +36,7 @@ void operator()() const { typedef std::atomic A; - A t; - std::atomic_init(&t, T(1)); + A t(T(1)); assert(std::atomic_load(&t) == T(1)); std::atomic_wait(&t, T(0)); std::thread t1 = support::make_test_thread([&](){ @@ -47,8 +46,7 @@ std::atomic_wait(&t, T(1)); t1.join(); - volatile A vt; - std::atomic_init(&vt, T(2)); + volatile A vt(T(2)); assert(std::atomic_load(&vt) == T(2)); std::atomic_wait(&vt, T(1)); std::thread t2 = support::make_test_thread([&](){ diff --git a/libcxx/test/std/depr/depr.atomics/depr.atomics.nonmembers/atomic_init.depr_in_cxx20.verify.cpp b/libcxx/test/std/depr/depr.atomics/depr.atomics.nonmembers/atomic_init.depr_in_cxx20.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/depr/depr.atomics/depr.atomics.nonmembers/atomic_init.depr_in_cxx20.verify.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-has-no-threads + +// +// +// atomic_init + +#include + +void test() { + std::atomic a; + std::atomic_init(&a, 1); // expected-warning {{'atomic_init' is deprecated}} + + volatile std::atomic b; + std::atomic_init(&b, 1); // expected-warning {{'atomic_init' is deprecated}} +} 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 --- 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 @@ -235,16 +235,16 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if !defined(_LIBCPP_HAS_NO_THREADS) # ifndef __cpp_lib_atomic_value_initialization # error "__cpp_lib_atomic_value_initialization should be defined in c++20" # endif # if __cpp_lib_atomic_value_initialization != 201911L # error "__cpp_lib_atomic_value_initialization should have the value 201911L in c++20" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_atomic_value_initialization -# error "__cpp_lib_atomic_value_initialization should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_atomic_value_initialization should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" # endif # endif @@ -354,16 +354,16 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if !defined(_LIBCPP_HAS_NO_THREADS) # ifndef __cpp_lib_atomic_value_initialization # error "__cpp_lib_atomic_value_initialization should be defined in c++2b" # endif # if __cpp_lib_atomic_value_initialization != 201911L # error "__cpp_lib_atomic_value_initialization should have the value 201911L in c++2b" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_atomic_value_initialization -# error "__cpp_lib_atomic_value_initialization should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_atomic_value_initialization should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" # endif # endif 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 --- 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 @@ -307,16 +307,16 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if !defined(_LIBCPP_HAS_NO_THREADS) # ifndef __cpp_lib_atomic_value_initialization # error "__cpp_lib_atomic_value_initialization should be defined in c++20" # endif # if __cpp_lib_atomic_value_initialization != 201911L # error "__cpp_lib_atomic_value_initialization should have the value 201911L in c++20" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_atomic_value_initialization -# error "__cpp_lib_atomic_value_initialization should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_atomic_value_initialization should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" # endif # endif @@ -457,16 +457,16 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if !defined(_LIBCPP_HAS_NO_THREADS) # ifndef __cpp_lib_atomic_value_initialization # error "__cpp_lib_atomic_value_initialization should be defined in c++2b" # endif # if __cpp_lib_atomic_value_initialization != 201911L # error "__cpp_lib_atomic_value_initialization should have the value 201911L in c++2b" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_atomic_value_initialization -# error "__cpp_lib_atomic_value_initialization should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_atomic_value_initialization should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" # endif # 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 --- 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 @@ -2242,16 +2242,16 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if !defined(_LIBCPP_HAS_NO_THREADS) # ifndef __cpp_lib_atomic_value_initialization # error "__cpp_lib_atomic_value_initialization should be defined in c++20" # endif # if __cpp_lib_atomic_value_initialization != 201911L # error "__cpp_lib_atomic_value_initialization should have the value 201911L in c++20" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_atomic_value_initialization -# error "__cpp_lib_atomic_value_initialization should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_atomic_value_initialization should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" # endif # endif @@ -3423,16 +3423,16 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if !defined(_LIBCPP_HAS_NO_THREADS) # ifndef __cpp_lib_atomic_value_initialization # error "__cpp_lib_atomic_value_initialization should be defined in c++2b" # endif # if __cpp_lib_atomic_value_initialization != 201911L # error "__cpp_lib_atomic_value_initialization should have the value 201911L in c++2b" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_atomic_value_initialization -# error "__cpp_lib_atomic_value_initialization should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_atomic_value_initialization should not be defined when !defined(_LIBCPP_HAS_NO_THREADS) is not defined!" # endif # endif diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -138,7 +138,6 @@ "headers": ["atomic", "memory"], "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)", "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)", - "unimplemented": True, }, { "name": "__cpp_lib_atomic_wait", "values": { "c++20": 201907 },