Skip to content

Commit 232e8b5

Browse files
[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.
1 parent 6b98f82 commit 232e8b5

4 files changed

Lines changed: 76 additions & 43 deletions

File tree

libcxx/docs/Status/Cxx26Issues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
"`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>`__",""
109109
"`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>`__",""
110110
"`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)","","","`#118367 <https://github.com/llvm/llvm-project/issues/118367>`__",""
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>`__",""
112112
"`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>`__",""
113113
"","","","","","",""
114114
"`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>`__",""

libcxx/include/__atomic/atomic.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <__cstddef/ptrdiff_t.h>
2323
#include <__memory/addressof.h>
2424
#include <__type_traits/enable_if.h>
25+
#include <__type_traits/is_constructible.h>
2526
#include <__type_traits/is_floating_point.h>
2627
#include <__type_traits/is_function.h>
2728
#include <__type_traits/is_integral.h>
@@ -258,7 +259,9 @@ struct atomic : public __atomic_base<typename __check_atomic_mandates<_Tp>::type
258259
using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>;
259260

260261
#if _LIBCPP_STD_VER >= 20
261-
_LIBCPP_HIDE_FROM_ABI atomic() = default;
262+
_LIBCPP_HIDE_FROM_ABI atomic()
263+
requires is_default_constructible_v<_Tp>
264+
= default;
262265
#else
263266
_LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;
264267
#endif

libcxx/test/std/atomics/atomics.types.generic/constexpr_noexcept.compile.pass.cpp

Lines changed: 0 additions & 41 deletions
This file was deleted.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// <atomic>
10+
11+
// atomic() noexcept = default; // until C++20
12+
// constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>); // since C++20
13+
14+
// Constraints: is_default_constructible_v<T> is true. (since C++20)
15+
16+
#include <atomic>
17+
#include <type_traits>
18+
19+
#include "test_macros.h"
20+
21+
template <typename T>
22+
void test() {
23+
#if TEST_STD_VER >= 11
24+
constexpr T a{};
25+
(void)a;
26+
# if TEST_STD_VER >= 20
27+
[[maybe_unused]] constexpr T b;
28+
# endif
29+
#else
30+
T a;
31+
(void)a;
32+
#endif
33+
static_assert(std::is_nothrow_constructible<T>::value, "");
34+
ASSERT_NOEXCEPT(T{});
35+
}
36+
37+
struct throwing {
38+
throwing() {}
39+
};
40+
41+
struct trivial {
42+
int a;
43+
};
44+
45+
struct not_default_constructible {
46+
explicit not_default_constructible(int) {}
47+
};
48+
49+
int main(int, char**) {
50+
test<std::atomic<bool> >();
51+
test<std::atomic<int> >();
52+
test<std::atomic<int*> >();
53+
test<std::atomic<trivial> >();
54+
test<std::atomic_flag>();
55+
56+
#if TEST_STD_VER >= 20
57+
static_assert(!std::is_nothrow_constructible_v<std::atomic<throwing>>);
58+
ASSERT_NOT_NOEXCEPT(std::atomic<throwing>{});
59+
60+
static_assert(!std::is_default_constructible_v<std::atomic<not_default_constructible>>);
61+
#else
62+
static_assert(std::is_nothrow_constructible<std::atomic<throwing> >::value, "");
63+
64+
ASSERT_NOEXCEPT(std::atomic<throwing>{});
65+
# ifndef TEST_COMPILER_GCC
66+
static_assert(std::is_default_constructible<std::atomic<not_default_constructible> >::value, "");
67+
# endif
68+
#endif
69+
70+
return 0;
71+
}

0 commit comments

Comments
 (0)