Skip to content

Commit 9965f3d

Browse files
authored
[libc++] Improve diagnostic when violating std::atomic trivially copyable mandates (#131754)
When attempting to instantiate `std::atomic` with a non trivially copyable type, one gets errors from instantiating internals before the actual static assertion that check the template parameter type requirements. The `verify` test for it had a `// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error` directive to work around this issue. The changes I propose enable us to drop that directive. As I understand it, the `verify` test was misplaced so I moved it to `test/{std -> libcxx}/atomics`. (I ran into this while working on #121414 in which we would add another static assertion in `__check_atomic_mandates`)
1 parent 27c099b commit 9965f3d

File tree

3 files changed

+14
-13
lines changed

3 files changed

+14
-13
lines changed

libcxx/include/__atomic/atomic.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <__type_traits/is_integral.h>
2424
#include <__type_traits/is_nothrow_constructible.h>
2525
#include <__type_traits/is_same.h>
26+
#include <__type_traits/is_trivially_copyable.h>
2627
#include <__type_traits/remove_const.h>
2728
#include <__type_traits/remove_pointer.h>
2829
#include <__type_traits/remove_volatile.h>
@@ -230,8 +231,14 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > {
230231
}
231232
};
232233

234+
template <typename _Tp>
235+
struct __check_atomic_mandates {
236+
using type _LIBCPP_NODEBUG = _Tp;
237+
static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type");
238+
};
239+
233240
template <class _Tp>
234-
struct atomic : public __atomic_base<_Tp> {
241+
struct atomic : public __atomic_base<typename __check_atomic_mandates<_Tp>::type> {
235242
using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>;
236243

237244
#if _LIBCPP_STD_VER >= 20

libcxx/include/__atomic/support.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#define _LIBCPP___ATOMIC_SUPPORT_H
1111

1212
#include <__config>
13-
#include <__type_traits/is_trivially_copyable.h>
1413

1514
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1615
# pragma GCC system_header
@@ -113,8 +112,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
113112

114113
template <typename _Tp, typename _Base = __cxx_atomic_base_impl<_Tp> >
115114
struct __cxx_atomic_impl : public _Base {
116-
static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type");
117-
118115
_LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default;
119116
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {}
120117
};

libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.verify.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,23 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
10+
911
// <atomic>
1012

1113
// template <class T>
1214
// struct atomic;
1315

14-
// This test checks that we static_assert inside std::atomic<T> when T
15-
// is not trivially copyable, however Clang will sometimes emit additional
16-
// errors while trying to instantiate the rest of std::atomic<T>.
17-
// We silence those to make the test more robust.
18-
// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error
19-
2016
#include <atomic>
2117

2218
struct NotTriviallyCopyable {
23-
explicit NotTriviallyCopyable(int i) : i_(i) { }
24-
NotTriviallyCopyable(const NotTriviallyCopyable &rhs) : i_(rhs.i_) { }
19+
explicit NotTriviallyCopyable(int i) : i_(i) {}
20+
NotTriviallyCopyable(const NotTriviallyCopyable& rhs) : i_(rhs.i_) {}
2521
int i_;
2622
};
2723

2824
void f() {
2925
NotTriviallyCopyable x(42);
30-
std::atomic<NotTriviallyCopyable> a(x); // expected-error@*:* {{std::atomic<T> requires that 'T' be a trivially copyable type}}
26+
std::atomic<NotTriviallyCopyable> a(
27+
x); // expected-error@*:* {{std::atomic<T> requires that 'T' be a trivially copyable type}}
3128
}

0 commit comments

Comments
 (0)