[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`)
This commit is contained in:
parent
27c099bc84
commit
9965f3d337
@ -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
|
||||
|
||||
@ -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) {}
|
||||
};
|
||||
|
||||
@ -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}}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user