diff options
author | Damien L-G <dalg24@gmail.com> | 2025-04-07 15:25:45 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-07 15:25:45 -0400 |
commit | 9965f3d337bba09fbf2497a78123957fdaee0ffa (patch) | |
tree | 7beb233e57f6a1366a42455c166fd3e2f529bc94 | |
parent | 27c099bc84d1432752b3828f1ba95de24db76c5e (diff) | |
download | llvm-9965f3d337bba09fbf2497a78123957fdaee0ffa.zip llvm-9965f3d337bba09fbf2497a78123957fdaee0ffa.tar.gz llvm-9965f3d337bba09fbf2497a78123957fdaee0ffa.tar.bz2 |
[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`)
-rw-r--r-- | libcxx/include/__atomic/atomic.h | 9 | ||||
-rw-r--r-- | libcxx/include/__atomic/support.h | 3 | ||||
-rw-r--r-- | libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.verify.cpp | 15 |
3 files changed, 14 insertions, 13 deletions
diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h index c65f9af..eead49d 100644 --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -23,6 +23,7 @@ #include <__type_traits/is_integral.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_same.h> +#include <__type_traits/is_trivially_copyable.h> #include <__type_traits/remove_const.h> #include <__type_traits/remove_pointer.h> #include <__type_traits/remove_volatile.h> @@ -230,8 +231,14 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > { } }; +template <typename _Tp> +struct __check_atomic_mandates { + using type _LIBCPP_NODEBUG = _Tp; + static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type"); +}; + template <class _Tp> -struct atomic : public __atomic_base<_Tp> { +struct atomic : public __atomic_base<typename __check_atomic_mandates<_Tp>::type> { using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>; #if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__atomic/support.h b/libcxx/include/__atomic/support.h index 4b555ab..99d0f6a 100644 --- a/libcxx/include/__atomic/support.h +++ b/libcxx/include/__atomic/support.h @@ -10,7 +10,6 @@ #define _LIBCPP___ATOMIC_SUPPORT_H #include <__config> -#include <__type_traits/is_trivially_copyable.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -113,8 +112,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <typename _Tp, typename _Base = __cxx_atomic_base_impl<_Tp> > struct __cxx_atomic_impl : public _Base { - static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type"); - _LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {} }; diff --git a/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.verify.cpp b/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.verify.cpp index 0955707..452e65d 100644 --- a/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.verify.cpp +++ b/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.verify.cpp @@ -6,26 +6,23 @@ // //===----------------------------------------------------------------------===// +// XFAIL: FROZEN-CXX03-HEADERS-FIXME + // <atomic> // template <class T> // struct atomic; -// This test checks that we static_assert inside std::atomic<T> when T -// is not trivially copyable, however Clang will sometimes emit additional -// errors while trying to instantiate the rest of std::atomic<T>. -// We silence those to make the test more robust. -// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error - #include <atomic> struct NotTriviallyCopyable { - explicit NotTriviallyCopyable(int i) : i_(i) { } - NotTriviallyCopyable(const NotTriviallyCopyable &rhs) : i_(rhs.i_) { } + explicit NotTriviallyCopyable(int i) : i_(i) {} + NotTriviallyCopyable(const NotTriviallyCopyable& rhs) : i_(rhs.i_) {} int i_; }; void f() { NotTriviallyCopyable x(42); - std::atomic<NotTriviallyCopyable> a(x); // expected-error@*:* {{std::atomic<T> requires that 'T' be a trivially copyable type}} + std::atomic<NotTriviallyCopyable> a( + x); // expected-error@*:* {{std::atomic<T> requires that 'T' be a trivially copyable type}} } |