Skip to content

[libc++] Improve diagnostic when violating std::atomic trivially copyable mandates #131754

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 7, 2025
Merged
9 changes: 8 additions & 1 deletion libcxx/include/__atomic/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions libcxx/include/__atomic/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
}