[libcxx-commits] [libcxx] 56aac56 - [libcxx] Implement P0883R2 ("Fixing Atomic Initialization")

Raul Tambre via libcxx-commits libcxx-commits at lists.llvm.org
Sun Jun 20 07:37:48 PDT 2021


Author: Raul Tambre
Date: 2021-06-20T17:37:42+03:00
New Revision: 56aac567acfd696f54163e33d8df02dc2ad3a72e

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

LOG: [libcxx] Implement P0883R2 ("Fixing Atomic Initialization")

Reviewed By: Quuxplusone

Differential Revision: https://reviews.llvm.org/D103769

Added: 
    libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp
    libcxx/test/std/atomics/atomics.types.generic/constexpr_noexcept.compile.pass.cpp
    libcxx/test/std/atomics/atomics.types.generic/throw.pass.cpp
    libcxx/test/std/depr/depr.atomics/depr.atomics.nonmembers/atomic_init.depr_in_cxx20.verify.cpp

Modified: 
    libcxx/docs/Cxx2aStatus.rst
    libcxx/docs/Cxx2aStatusPaperStatus.csv
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/include/atomic
    libcxx/include/version
    libcxx/test/std/atomics/atomics.types.generic/address.pass.cpp
    libcxx/test/std/atomics/atomics.types.generic/bool.pass.cpp
    libcxx/test/std/atomics/atomics.types.generic/integral.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and_explicit.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or_explicit.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor_explicit.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp
    libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.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/memory.version.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    libcxx/test/libcxx/atomics/atomics.align/align.pass.pass.cpp


################################################################################
diff  --git a/libcxx/docs/Cxx2aStatus.rst b/libcxx/docs/Cxx2aStatus.rst
index c96198bd36851..8bbf7d80c3aa4 100644
--- a/libcxx/docs/Cxx2aStatus.rst
+++ b/libcxx/docs/Cxx2aStatus.rst
@@ -42,8 +42,8 @@ Paper Status
 
    .. [#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 <https://llvm.org/PR45368>`__.
-
    .. [#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
index 3666d89cfda08..90695107ad813 100644
--- a/libcxx/docs/Cxx2aStatusPaperStatus.csv
+++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv
@@ -133,7 +133,7 @@
 "`P1661 <https://wg21.link/P1661>`__","LWG","Remove dedicated precalculated hash lookup interface","Cologne","|Nothing To Do|",""
 "`P1754 <https://wg21.link/P1754>`__","LWG","Rename concepts to standard_case for C++20, while we still can","Cologne","|In Progress|",""
 "","","","","",""
-"`P0883 <https://wg21.link/P0883>`__","LWG","Fixing Atomic Initialization","Belfast","* *",""
+"`P0883 <https://wg21.link/P0883>`__","LWG","Fixing Atomic Initialization","Belfast","|Complete| [#note-P0883]","13.0"
 "`P1391 <https://wg21.link/P1391>`__","LWG","Range constructor for std::string_view","Belfast","* *",""
 "`P1394 <https://wg21.link/P1394>`__","LWG","Range constructor for std::span","Belfast","* *",""
 "`P1456 <https://wg21.link/P1456>`__","LWG","Move-only views","Belfast","* *",""

diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index ff5197f514c15..c2690e72eea04 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -182,7 +182,7 @@ Status
     ------------------------------------------------- -----------------
     ``__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
index 90bed4f947661..0f6aee83ce824 100644
--- a/libcxx/include/atomic
+++ b/libcxx/include/atomic
@@ -67,7 +67,8 @@ struct atomic
     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<T>); // since C++20
     constexpr atomic(T desr) noexcept;
     atomic(const atomic&) = delete;
     atomic& operator=(const atomic&) = delete;
@@ -201,7 +202,8 @@ struct atomic<T*>
     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 atomic<uintmax_t> atomic_uintmax_t;
 
 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 @@ struct __atomic_base  // false
     _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 @@ struct __atomic_base<_Tp, true>
     : 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 @@ struct atomic
     typedef __atomic_base<_Tp> __base;
     typedef _Tp value_type;
     typedef value_type 
diff erence_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 @@ 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
     _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
 
@@ -1892,7 +1911,7 @@ atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT
 // atomic_init
 
 template <class _Tp>
-_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 @@ atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NO
 }
 
 template <class _Tp>
-_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 @@ typedef struct atomic_flag
     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
index 3d1554b5c4d77..a0ec730a8ea10 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -283,7 +283,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 // #   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
similarity index 90%
rename from libcxx/test/libcxx/atomics/atomics.align/align.pass.pass.cpp
rename to libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp
index 96a34e22069c8..279fc090244f0 100644
--- 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
+// 
diff erent 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
index 598889736ab91..0bcaa19d38f39 100644
--- 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.
 
 // <atomic>
 
@@ -82,13 +81,9 @@ do_test()
 {
     typedef typename std::remove_pointer<T>::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
index 154d0bfe67d56..4e1428ddadef7 100644
--- 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 @@ int main(int, char**)
     {
         volatile 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);
@@ -118,10 +114,6 @@ int main(int, char**)
     {
         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);
@@ -173,10 +165,6 @@ int main(int, char**)
     {
         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
index 0000000000000..8546541150e75
--- /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 <atomic>
+
+#include "test_macros.h"
+
+template <typename T>
+constexpr bool test() {
+  [[maybe_unused]] constexpr T a;
+  static_assert(std::is_nothrow_constructible_v<T>);
+  ASSERT_NOEXCEPT(T{});
+  return true;
+}
+
+struct throwing {
+  throwing() {}
+};
+
+struct trivial {
+  int a;
+};
+
+void test() {
+  static_assert(test<std::atomic<bool>>());
+  static_assert(test<std::atomic<int>>());
+  static_assert(test<std::atomic<int*>>());
+  static_assert(test<std::atomic<trivial>>());
+  static_assert(test<std::atomic_flag>());
+
+  static_assert(!std::is_nothrow_constructible_v<std::atomic<throwing>>);
+  ASSERT_NOT_NOEXCEPT(std::atomic<throwing>{});
+}

diff  --git a/libcxx/test/std/atomics/atomics.types.generic/integral.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/integral.pass.cpp
index 4405503626187..a4a480ffd0914 100644
--- 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 @@ do_test()
 {
     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
index 0000000000000..8fd7d4f33d47f
--- /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
+
+// <atomic>
+
+#include <atomic>
+#include <cassert>
+
+struct throwing {
+  throwing() { throw 42; }
+};
+
+int main(int, char**) {
+  try {
+    [[maybe_unused]] std::atomic<throwing> 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
index 90075751c89aa..1bb1c915ca514 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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 @@ struct TestFn {
     }
     {
         typedef std::atomic<T> 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
index c998a26649170..db3bad9172b26 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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 @@ struct TestFn {
     }
     {
         typedef std::atomic<T> 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
index da1a976dabeb6..0e4c5502cd900 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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 @@ struct TestFn {
     }
     {
         typedef std::atomic<T> 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
index 1f88e155fb2e6..ab0e50a7e19eb 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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 @@ struct TestFn {
     }
     {
         typedef std::atomic<T> 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
index 04e90d18e50e4..afad574ecc610 100644
--- 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 @@ template <class T>
 struct TestFn {
   void operator()() const {
     typedef std::atomic<T> 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
index 00182921258b8..b63a79482da81 100644
--- 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 @@ template <class T>
 struct TestFn {
   void operator()() const {
     typedef std::atomic<T> 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
index b840930c12583..f48892b1e9733 100644
--- 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
 
 // <atomic>
 
@@ -39,15 +38,13 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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 @@ void testp()
     {
         typedef std::atomic<T> A;
         typedef typename std::remove_pointer<T>::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<X>(&t, 0);
@@ -73,8 +69,7 @@ void testp()
     {
         typedef std::atomic<T> A;
         typedef typename std::remove_pointer<T>::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<X>(&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
index 2effd4c128a19..ca41e7bc08917 100644
--- 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
 
 // <atomic>
 
@@ -39,16 +38,14 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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 @@ testp()
     {
         typedef std::atomic<T> A;
         typedef typename std::remove_pointer<T>::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 @@ testp()
     {
         typedef std::atomic<T> A;
         typedef typename std::remove_pointer<T>::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
index aad3209e4fab8..6ea213285c509 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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
index cbcc2231d0fca..361afd5c18249 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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
index f86624a977cae..78bf4e0a3ef34 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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
index 12686835aa285..4effcb5b0cacd 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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
index dd867b8bb7667..d065c46d79198 100644
--- 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
 
 // <atomic>
 
@@ -39,15 +38,13 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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 @@ void testp()
     {
         typedef std::atomic<T> A;
         typedef typename std::remove_pointer<T>::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<X>(&t, 0);
@@ -73,8 +69,7 @@ void testp()
     {
         typedef std::atomic<T> A;
         typedef typename std::remove_pointer<T>::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<X>(&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
index 1499de1606beb..62fc4b9a12d5d 100644
--- 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
 
 // <atomic>
 
@@ -40,16 +39,14 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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 @@ void testp()
     {
         typedef std::atomic<T> A;
         typedef typename std::remove_pointer<T>::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 @@ void testp()
     {
         typedef std::atomic<T> A;
         typedef typename std::remove_pointer<T>::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
index 4979e0106ff8d..874eabf2e1ee8 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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
index 639cc230f8249..f8f3e6ddb3d6f 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     {
         typedef std::atomic<T> 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<T> 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
index 60a1248d661e8..1de165d537ccd 100644
--- 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
 
 // <atomic>
 

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
index 49d217388dead..d9e672e1a9d20 100644
--- 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 @@ template <class T>
 struct TestFn {
   void operator()() const {
     typedef std::atomic<T> 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
index 20ee32c0bb0c9..61a7929881fc3 100644
--- 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 @@ template <class T>
 struct TestFn {
   void operator()() const {
     typedef std::atomic<T> 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
index ce7b023f8d0a3..a54988dd73312 100644
--- 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 @@ struct TestFn {
   void operator()() const {
     typedef std::atomic<T> 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 @@ struct TestFn {
     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
index 0000000000000..4cb680ef67fbd
--- /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>
+//
+// atomic_init
+
+#include <atomic>
+
+void test() {
+  std::atomic<int> a;
+  std::atomic_init(&a, 1); // expected-warning {{'atomic_init<int>' is deprecated}}
+
+  volatile std::atomic<int> b;
+  std::atomic_init(&b, 1); // expected-warning {{'atomic_init<int>' 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
index c8a837115adef..23af3aeac21e7 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
@@ -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
index b54a1f47bc2f3..8f085e0cdec06 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
@@ -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
index 64db73f68877a..f2125064bfa40 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
@@ -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
index 76ac93ec10237..78b124e7c21e7 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -138,7 +138,6 @@ def add_version_header(tc):
     "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 },


        


More information about the libcxx-commits mailing list