[libc++] Implement LWG4169: std::atomic<T>'s default constructor should be constrained (#131950)

Drive-by: Rename `constexpr_noexcept.compile.pass.cpp` to
`ctor.default.pass.cpp` as test coverage is added to it, and compile and
run it in all modes.
This commit is contained in:
A. Jiang 2026-08-01 17:20:05 +08:00 committed by GitHub
parent 6b98f82fe9
commit 232e8b5f45
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 76 additions and 43 deletions

View file

@ -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|","24","`#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>`__",""

1 Issue # Issue Name Meeting Status First released version GitHub issue Notes
108 `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>`__
109 `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>`__
110 `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>`__
111 `LWG4169 <https://wg21.link/LWG4169>`__ ``std::atomic<T>``'s default constructor should be constrained 2024-11 (Wrocław) |Complete| 24 `#118367 <https://github.com/llvm/llvm-project/issues/118367>`__
112 `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>`__
113
114 `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>`__

View file

@ -22,6 +22,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>
@ -258,7 +259,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

View file

@ -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>{});
}

View file

@ -0,0 +1,71 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <atomic>
// atomic() noexcept = default; // until C++20
// constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>); // since C++20
// Constraints: is_default_constructible_v<T> is true. (since C++20)
#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) {}
};
int main(int, char**) {
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
return 0;
}