diff --git a/libcxx/include/atomic b/libcxx/include/atomic --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -1440,7 +1440,7 @@ #endif //_LIBCPP_ATOMIC_ONLY_USE_BUILTINS struct __cxx_atomic_impl : public _Base { static_assert(is_trivially_copyable<_Tp>::value, - "std::atomic requires that 'Tp' be a trivially copyable type"); + "std::atomic requires that 'T' be a trivially copyable type"); _LIBCPP_INLINE_VISIBILITY __cxx_atomic_impl() _NOEXCEPT _LIBCPP_DEFAULT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp value) _NOEXCEPT diff --git a/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.compile.fail.cpp b/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.compile.fail.cpp deleted file mode 100644 --- a/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.compile.fail.cpp +++ /dev/null @@ -1,71 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// template -// struct atomic -// { -// bool is_lock_free() const volatile noexcept; -// bool is_lock_free() const noexcept; -// void store(T desr, memory_order m = memory_order_seq_cst) volatile noexcept; -// void store(T desr, memory_order m = memory_order_seq_cst) noexcept; -// T load(memory_order m = memory_order_seq_cst) const volatile noexcept; -// T load(memory_order m = memory_order_seq_cst) const noexcept; -// operator T() const volatile noexcept; -// operator T() const noexcept; -// T exchange(T desr, memory_order m = memory_order_seq_cst) volatile noexcept; -// T exchange(T desr, memory_order m = memory_order_seq_cst) noexcept; -// bool compare_exchange_weak(T& expc, T desr, -// memory_order s, memory_order f) volatile noexcept; -// bool compare_exchange_weak(T& expc, T desr, memory_order s, memory_order f) noexcept; -// bool compare_exchange_strong(T& expc, T desr, -// memory_order s, memory_order f) volatile noexcept; -// bool compare_exchange_strong(T& expc, T desr, -// memory_order s, memory_order f) noexcept; -// bool compare_exchange_weak(T& expc, T desr, -// memory_order m = memory_order_seq_cst) volatile noexcept; -// bool compare_exchange_weak(T& expc, T desr, -// memory_order m = memory_order_seq_cst) noexcept; -// bool compare_exchange_strong(T& expc, T desr, -// memory_order m = memory_order_seq_cst) volatile noexcept; -// bool compare_exchange_strong(T& expc, T desr, -// memory_order m = memory_order_seq_cst) noexcept; -// -// atomic() noexcept = default; -// constexpr atomic(T desr) noexcept; -// atomic(const atomic&) = delete; -// atomic& operator=(const atomic&) = delete; -// atomic& operator=(const atomic&) volatile = delete; -// T operator=(T) volatile noexcept; -// T operator=(T) noexcept; -// }; - -#include -#include -#include -#include // for thread_id -#include // for nanoseconds - -struct NotTriviallyCopyable { - NotTriviallyCopyable ( int i ) : i_(i) {} - NotTriviallyCopyable ( const NotTriviallyCopyable &rhs) : i_(rhs.i_) {} - int i_; -}; - -template -void test ( T t ) { - std::atomic t0(t); -} - -int main(int, char**) -{ - test(NotTriviallyCopyable(42)); - - return 0; -} diff --git a/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.pass.cpp @@ -11,42 +11,9 @@ // // template -// struct atomic -// { -// bool is_lock_free() const volatile noexcept; -// bool is_lock_free() const noexcept; -// void store(T desr, memory_order m = memory_order_seq_cst) volatile noexcept; -// void store(T desr, memory_order m = memory_order_seq_cst) noexcept; -// T load(memory_order m = memory_order_seq_cst) const volatile noexcept; -// T load(memory_order m = memory_order_seq_cst) const noexcept; -// operator T() const volatile noexcept; -// operator T() const noexcept; -// T exchange(T desr, memory_order m = memory_order_seq_cst) volatile noexcept; -// T exchange(T desr, memory_order m = memory_order_seq_cst) noexcept; -// bool compare_exchange_weak(T& expc, T desr, -// memory_order s, memory_order f) volatile noexcept; -// bool compare_exchange_weak(T& expc, T desr, memory_order s, memory_order f) noexcept; -// bool compare_exchange_strong(T& expc, T desr, -// memory_order s, memory_order f) volatile noexcept; -// bool compare_exchange_strong(T& expc, T desr, -// memory_order s, memory_order f) noexcept; -// bool compare_exchange_weak(T& expc, T desr, -// memory_order m = memory_order_seq_cst) volatile noexcept; -// bool compare_exchange_weak(T& expc, T desr, -// memory_order m = memory_order_seq_cst) noexcept; -// bool compare_exchange_strong(T& expc, T desr, -// memory_order m = memory_order_seq_cst) volatile noexcept; -// bool compare_exchange_strong(T& expc, T desr, -// memory_order m = memory_order_seq_cst) noexcept; -// -// atomic() noexcept = default; -// constexpr atomic(T desr) noexcept; -// atomic(const atomic&) = delete; -// atomic& operator=(const atomic&) = delete; -// atomic& operator=(const atomic&) volatile = delete; -// T operator=(T) volatile noexcept; -// T operator=(T) noexcept; -// }; +// struct atomic; + +// Make sure atomic can be instantiated. #include #include @@ -54,23 +21,20 @@ #include // for thread_id #include // for nanoseconds -#include "test_macros.h" - struct TriviallyCopyable { - TriviallyCopyable ( int i ) : i_(i) {} - int i_; - }; + explicit TriviallyCopyable(int i) : i_(i) { } + int i_; +}; template -void test ( T t ) { - std::atomic t0(t); - } +void test(T t) { + std::atomic t0(t); +} -int main(int, char**) -{ - test(TriviallyCopyable(42)); - test(std::this_thread::get_id()); - test(std::chrono::nanoseconds(2)); +int main(int, char**) { + test(TriviallyCopyable(42)); + test(std::this_thread::get_id()); + test(std::chrono::nanoseconds(2)); return 0; } 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 new file mode 100644 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.verify.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: libcpp-has-no-threads + +// + +// template +// struct atomic; + +// This test checks that we static_assert inside std::atomic when T +// is not trivially copyable, however Clang will sometimes emit additional +// errors while trying to instantiate the rest of std::atomic. +// We silence those to make the test more robust. +// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error + +#include + +struct NotTriviallyCopyable { + explicit NotTriviallyCopyable(int i) : i_(i) { } + NotTriviallyCopyable(const NotTriviallyCopyable &rhs) : i_(rhs.i_) { } + int i_; +}; + +void f() { + NotTriviallyCopyable x(42); + std::atomic a(x); // expected-error@atomic:* {{std::atomic requires that 'T' be a trivially copyable type}} +}