[libcxx-commits] [libcxx] [libc++] LWG4169: `std::atomic<T>`'s default constructor should be constrained (PR #131950)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Mon Oct 27 19:40:47 PDT 2025


https://github.com/frederick-vs-ja updated https://github.com/llvm/llvm-project/pull/131950

>From 1a270b47a999bc2827ee683fbcad726c0587603c Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Wed, 19 Mar 2025 11:58:53 +0800
Subject: [PATCH] [libc++] LWG4169 constrain `std::atomic<T>`'s default
 constructor

Drive-by: Rename `constexpr_noexcept.compile.pass.cpp` to
`default_constructor.compile.pass.cpp` as test coverage is added to it,
and run it in all modes.
---
 libcxx/docs/Status/Cxx2cIssues.csv            |  2 +-
 libcxx/include/__atomic/atomic.h              |  5 +-
 .../constexpr_noexcept.compile.pass.cpp       | 41 ------------
 .../default_constructor.compile.pass.cpp      | 64 +++++++++++++++++++
 4 files changed, 69 insertions(+), 43 deletions(-)
 delete mode 100644 libcxx/test/std/atomics/atomics.types.generic/constexpr_noexcept.compile.pass.cpp
 create mode 100644 libcxx/test/std/atomics/atomics.types.generic/default_constructor.compile.pass.cpp

diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 859c49af17ec9..10f11feb891af 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -108,7 +108,7 @@
 "`LWG4154 <https://wg21.link/LWG4154>`__","The Mandates for ``std::packaged_task``'s constructor from a callable entity should consider decaying","2024-11 (Wrocław)","","","`#118364 <https://github.com/llvm/llvm-project/issues/118364>`__",""
 "`LWG4157 <https://wg21.link/LWG4157>`__","The resolution of LWG3465 was damaged by P2167R3","2024-11 (Wrocław)","|Complete|","20","`#118365 <https://github.com/llvm/llvm-project/issues/118365>`__",""
 "`LWG4164 <https://wg21.link/LWG4164>`__","Missing guarantees for ``forward_list`` modifiers","2024-11 (Wrocław)","|Complete|","21","`#118366 <https://github.com/llvm/llvm-project/issues/118366>`__",""
-"`LWG4169 <https://wg21.link/LWG4169>`__","``std::atomic<T>``'s default constructor should be constrained","2024-11 (Wrocław)","","","`#118367 <https://github.com/llvm/llvm-project/issues/118367>`__",""
+"`LWG4169 <https://wg21.link/LWG4169>`__","``std::atomic<T>``'s default constructor should be constrained","2024-11 (Wrocław)","|Complete|","22","`#118367 <https://github.com/llvm/llvm-project/issues/118367>`__",""
 "`LWG4170 <https://wg21.link/LWG4170>`__","``contiguous_iterator`` should require ``to_address(I{})``","2024-11 (Wrocław)","","","`#118368 <https://github.com/llvm/llvm-project/issues/118368>`__",""
 "","","","","","",""
 "`LWG3578 <https://wg21.link/LWG3578>`__","Iterator SCARYness in the context of associative container merging","2025-02 (Hagenberg)","","","`#127859 <https://github.com/llvm/llvm-project/issues/127859>`__",""
diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index 44835820bb06c..fd408833ba7a9 100644
--- a/libcxx/include/__atomic/atomic.h
+++ b/libcxx/include/__atomic/atomic.h
@@ -19,6 +19,7 @@
 #include <__cstddef/ptrdiff_t.h>
 #include <__memory/addressof.h>
 #include <__type_traits/enable_if.h>
+#include <__type_traits/is_constructible.h>
 #include <__type_traits/is_floating_point.h>
 #include <__type_traits/is_function.h>
 #include <__type_traits/is_integral.h>
@@ -237,7 +238,9 @@ struct atomic : public __atomic_base<typename __check_atomic_mandates<_Tp>::type
   using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>;
 
 #if _LIBCPP_STD_VER >= 20
-  _LIBCPP_HIDE_FROM_ABI atomic() = default;
+  _LIBCPP_HIDE_FROM_ABI atomic()
+    requires is_default_constructible_v<_Tp>
+  = default;
 #else
   _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;
 #endif
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
deleted file mode 100644
index fca52a998eace..0000000000000
--- a/libcxx/test/std/atomics/atomics.types.generic/constexpr_noexcept.compile.pass.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-#include <atomic>
-#include <type_traits>
-
-#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/default_constructor.compile.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/default_constructor.compile.pass.cpp
new file mode 100644
index 0000000000000..e1a3eb183bf27
--- /dev/null
+++ b/libcxx/test/std/atomics/atomics.types.generic/default_constructor.compile.pass.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Test the properties of std::atomic's default constructor.
+
+#include <atomic>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <typename T>
+void test() {
+#if TEST_STD_VER >= 11
+  constexpr T a{};
+  (void)a;
+#  if TEST_STD_VER >= 20
+  [[maybe_unused]] constexpr T b;
+#  endif
+#else
+  T a;
+  (void)a;
+#endif
+  static_assert(std::is_nothrow_constructible<T>::value, "");
+  ASSERT_NOEXCEPT(T{});
+}
+
+struct throwing {
+  throwing() {}
+};
+
+struct trivial {
+  int a;
+};
+
+struct not_default_constructible {
+  explicit not_default_constructible(int) {}
+};
+
+void test() {
+  test<std::atomic<bool> >();
+  test<std::atomic<int> >();
+  test<std::atomic<int*> >();
+  test<std::atomic<trivial> >();
+  test<std::atomic_flag>();
+
+#if TEST_STD_VER >= 20
+  static_assert(!std::is_nothrow_constructible_v<std::atomic<throwing>>);
+  ASSERT_NOT_NOEXCEPT(std::atomic<throwing>{});
+
+  static_assert(!std::is_default_constructible_v<std::atomic<not_default_constructible>>);
+#else
+  static_assert(std::is_nothrow_constructible<std::atomic<throwing> >::value, "");
+
+  ASSERT_NOEXCEPT(std::atomic<throwing>{});
+#  ifndef TEST_COMPILER_GCC
+  static_assert(std::is_default_constructible<std::atomic<not_default_constructible> >::value, "");
+#  endif
+#endif
+}



More information about the libcxx-commits mailing list