[libcxx-commits] [libcxx] 9965f3d - [libc++] Improve diagnostic when violating `std::atomic` trivially copyable mandates (#131754)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Apr 7 12:25:49 PDT 2025


Author: Damien L-G
Date: 2025-04-07T15:25:45-04:00
New Revision: 9965f3d337bba09fbf2497a78123957fdaee0ffa

URL: https://github.com/llvm/llvm-project/commit/9965f3d337bba09fbf2497a78123957fdaee0ffa
DIFF: https://github.com/llvm/llvm-project/commit/9965f3d337bba09fbf2497a78123957fdaee0ffa.diff

LOG: [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`)

Added: 
    

Modified: 
    libcxx/include/__atomic/atomic.h
    libcxx/include/__atomic/support.h
    libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.verify.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index c65f9afe4f390..eead49dde6192 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 4b555ab483ca0..99d0f6aa543ca 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 0955707cdcf38..452e65d569230 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}}
 }


        


More information about the libcxx-commits mailing list