Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions libcxx/include/__atomic/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct __atomic_base // false
{
mutable __cxx_atomic_impl<_Tp> __a_;

using value_type = _Tp;

#if _LIBCPP_STD_VER >= 17
static constexpr bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value;
#endif
Expand Down Expand Up @@ -145,6 +147,8 @@ template <class _Tp>
struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
using __base _LIBCPP_NODEBUG = __atomic_base<_Tp, false>;

using difference_type = __base::value_type;

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __atomic_base() _NOEXCEPT = default;

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {}
Expand Down Expand Up @@ -229,8 +233,6 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > {
template <class _Tp>
struct atomic : public __atomic_base<_Tp> {
using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>;
using value_type = _Tp;
using difference_type = value_type;

#if _LIBCPP_STD_VER >= 20
_LIBCPP_HIDE_FROM_ABI atomic() = default;
Expand Down Expand Up @@ -258,8 +260,8 @@ struct atomic : public __atomic_base<_Tp> {
template <class _Tp>
struct atomic<_Tp*> : public __atomic_base<_Tp*> {
using __base _LIBCPP_NODEBUG = __atomic_base<_Tp*>;
using value_type = _Tp*;
using difference_type = ptrdiff_t;

using difference_type = ptrdiff_t;

_LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ struct S {
void member_function_pointer() {
{
volatile std::atomic<void (S::*)(int)> fun;
// expected-error@*:* {{no member named 'fetch_add' in}}
// expected-error@*:* {{no matching function for call to 'atomic_fetch_add'}}
std::atomic_fetch_add(&fun, 0);
}
{
std::atomic<void (S::*)(int)> fun;
// expected-error@*:* {{no member named 'fetch_add' in}}
// expected-error@*:* {{no matching function for call to 'atomic_fetch_add'}}
std::atomic_fetch_add(&fun, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ struct S {
void member_function_pointer() {
{
volatile std::atomic<void (S::*)(int)> fun;
// expected-error@*:* {{no member named 'fetch_add' in}}
// expected-error@*:* {{no matching function for call to 'atomic_fetch_add_explicit'}}
std::atomic_fetch_add_explicit(&fun, 0, std::memory_order_relaxed);
}
{
std::atomic<void (S::*)(int)> fun;
// expected-error@*:* {{no member named 'fetch_add' in}}
// expected-error@*:* {{no matching function for call to 'atomic_fetch_add_explicit'}}
std::atomic_fetch_add_explicit(&fun, 0, std::memory_order_relaxed);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ struct S {
void member_function_pointer() {
{
volatile std::atomic<void (S::*)(int)> fun;
// expected-error@*:* {{no member named 'fetch_sub' in}}
// expected-error@*:* {{no matching function for call to 'atomic_fetch_sub'}}
std::atomic_fetch_sub(&fun, 0);
}
{
std::atomic<void (S::*)(int)> fun;
// expected-error@*:* {{no member named 'fetch_sub' in}}
// expected-error@*:* {{no matching function for call to 'atomic_fetch_sub'}}
std::atomic_fetch_sub(&fun, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ struct S {
void member_function_pointer() {
{
volatile std::atomic<void (S::*)(int)> fun;
// expected-error@*:* {{no member named 'fetch_sub' in}}
// expected-error@*:* {{no matching function for call to 'atomic_fetch_sub_explicit'}}
std::atomic_fetch_sub_explicit(&fun, 0, std::memory_order_relaxed);
}
{
std::atomic<void (S::*)(int)> fun;
// expected-error@*:* {{no member named 'fetch_sub' in}}
// expected-error@*:* {{no matching function for call to 'atomic_fetch_sub_explicit'}}
std::atomic_fetch_sub_explicit(&fun, 0, std::memory_order_relaxed);
}
}
223 changes: 118 additions & 105 deletions libcxx/test/std/atomics/types.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,163 +29,176 @@
# include <thread>
#endif

template <class A, bool Integral>
struct test_atomic
{
test_atomic()
{
A a; (void)a;
// detect existence of the difference_type member type
template <class...>
using myvoid_t = void;
template <typename T, typename = void>
struct has_difference_type : std::false_type {};
template <typename T>
struct has_difference_type<T, myvoid_t<typename T::difference_type> > : std::true_type {};

template <class A, bool IntegralOrFloating, bool Pointer>
struct test_atomic {
test_atomic() {
static_assert(!IntegralOrFloating || !Pointer, "");
A a;
(void)a;
#if TEST_STD_VER >= 17
static_assert((std::is_same_v<typename A::value_type, decltype(a.load())>), "");
static_assert(!has_difference_type<A>::value, "");
#endif
}
}
};

template <class A>
struct test_atomic<A, true>
{
test_atomic()
{
A a; (void)a;
struct test_atomic<A, true, false> {
test_atomic() {
A a;
(void)a;
#if TEST_STD_VER >= 17
static_assert((std::is_same_v<typename A::value_type, decltype(a.load())>), "");
static_assert((std::is_same_v<typename A::value_type, typename A::difference_type>), "");
#endif
}
}
};

template <class A>
struct test_atomic<A*, false>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would never occur since we were instantiating with A = std::atomic<T>

{
test_atomic()
{
A a; (void)a;
struct test_atomic<A, false, true> {
test_atomic() {
A a;
(void)a;
#if TEST_STD_VER >= 17
static_assert((std::is_same_v<typename A::value_type, decltype(a.load())>), "");
static_assert((std::is_same_v<typename A::difference_type, std::ptrdiff_t>), "");
#endif
}
}
};

template <class T>
void
test()
{
using A = std::atomic<T>;
void test() {
using A = std::atomic<T>;
#if TEST_STD_VER >= 17
static_assert((std::is_same_v<typename A::value_type, T>), "");
static_assert((std::is_same_v<typename A::value_type, T>), "");
#endif
test_atomic<A, std::is_integral<T>::value && !std::is_same<T, bool>::value>();
enum {
IntegralOrFloating =
(std::is_integral<T>::value && !std::is_same<T, bool>::value) || std::is_floating_point<T>::value
};
enum { Pointer = std::is_pointer<T>::value };
test_atomic<A, IntegralOrFloating, Pointer>();
}

struct TriviallyCopyable {
int i_;
int i_;
};

struct WeirdTriviallyCopyable
{
char i, j, k; /* the 3 chars of doom */
struct WeirdTriviallyCopyable {
char i, j, k; /* the 3 chars of doom */
};

struct PaddedTriviallyCopyable
{
char i; int j; /* probably lock-free? */
struct PaddedTriviallyCopyable {
char i;
int j; /* probably lock-free? */
};

struct LargeTriviallyCopyable
{
int i, j[127]; /* decidedly not lock-free */
struct LargeTriviallyCopyable {
int i, j[127]; /* decidedly not lock-free */
};

int main(int, char**)
{
test<bool> ();
test<char> ();
test<signed char> ();
test<unsigned char> ();
test<short> ();
test<unsigned short> ();
test<int> ();
test<unsigned int> ();
test<long> ();
test<unsigned long> ();
test<long long> ();
test<unsigned long long> ();
int main(int, char**) {
test<bool>();
test<char>();
test<signed char>();
test<unsigned char>();
test<short>();
test<unsigned short>();
test<int>();
test<unsigned int>();
test<long>();
test<unsigned long>();
test<long long>();
test<unsigned long long>();
#if TEST_STD_VER > 17 && defined(__cpp_char8_t)
test<char8_t> ();
test<char8_t>();
#endif
test<char16_t> ();
test<char32_t> ();
test<char16_t>();
test<char32_t>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t> ();
test<wchar_t>();
#endif

test<std::int_least8_t> ();
test<std::uint_least8_t> ();
test<std::int_least16_t> ();
test<std::uint_least16_t> ();
test<std::int_least32_t> ();
test<std::uint_least32_t> ();
test<std::int_least64_t> ();
test<std::uint_least64_t> ();

test<std::int_fast8_t> ();
test<std::uint_fast8_t> ();
test<std::int_fast16_t> ();
test<std::uint_fast16_t> ();
test<std::int_fast32_t> ();
test<std::uint_fast32_t> ();
test<std::int_fast64_t> ();
test<std::uint_fast64_t> ();

test< std::int8_t> ();
test<std::uint8_t> ();
test< std::int16_t> ();
test<std::uint16_t> ();
test< std::int32_t> ();
test<std::uint32_t> ();
test< std::int64_t> ();
test<std::uint64_t> ();

test<std::intptr_t> ();
test<std::uintptr_t> ();
test<std::size_t> ();
test<std::ptrdiff_t> ();
test<std::intmax_t> ();
test<std::uintmax_t> ();

test<std::uintmax_t> ();
test<std::uintmax_t> ();

test<TriviallyCopyable>();
test<PaddedTriviallyCopyable>();
test<std::int_least8_t>();
test<std::uint_least8_t>();
test<std::int_least16_t>();
test<std::uint_least16_t>();
test<std::int_least32_t>();
test<std::uint_least32_t>();
test<std::int_least64_t>();
test<std::uint_least64_t>();

test<std::int_fast8_t>();
test<std::uint_fast8_t>();
test<std::int_fast16_t>();
test<std::uint_fast16_t>();
test<std::int_fast32_t>();
test<std::uint_fast32_t>();
test<std::int_fast64_t>();
test<std::uint_fast64_t>();

test< std::int8_t>();
test<std::uint8_t>();
test< std::int16_t>();
test<std::uint16_t>();
test< std::int32_t>();
test<std::uint32_t>();
test< std::int64_t>();
test<std::uint64_t>();

test<std::intptr_t>();
test<std::uintptr_t>();
test<std::size_t>();
test<std::ptrdiff_t>();
test<std::intmax_t>();
test<std::uintmax_t>();

test<std::uintmax_t>();
test<std::uintmax_t>();

test<void (*)(int)>();
test<void*>();
test<const void*>();
test<int*>();
test<const int*>();

test<TriviallyCopyable>();
test<PaddedTriviallyCopyable>();
#ifndef __APPLE__ // Apple doesn't ship libatomic
/*
/*
These aren't going to be lock-free,
so some libatomic.a is necessary.
*/
test<WeirdTriviallyCopyable>();
test<LargeTriviallyCopyable>();
test<WeirdTriviallyCopyable>();
test<LargeTriviallyCopyable>();
#endif

#ifndef TEST_HAS_NO_THREADS
test<std::thread::id>();
test<std::thread::id>();
#endif
test<std::chrono::nanoseconds>();
test<float>();
test<std::chrono::nanoseconds>();
test<float>();

#if TEST_STD_VER >= 20
test<std::atomic_signed_lock_free::value_type>();
static_assert(std::is_signed_v<std::atomic_signed_lock_free::value_type>);
static_assert(std::is_integral_v<std::atomic_signed_lock_free::value_type>);
test<std::atomic_signed_lock_free::value_type>();
static_assert(std::is_signed_v<std::atomic_signed_lock_free::value_type>);
static_assert(std::is_integral_v<std::atomic_signed_lock_free::value_type>);

test<std::atomic_unsigned_lock_free::value_type>();
static_assert(std::is_unsigned_v<std::atomic_unsigned_lock_free::value_type>);
static_assert(std::is_integral_v<std::atomic_unsigned_lock_free::value_type>);
test<std::atomic_unsigned_lock_free::value_type>();
static_assert(std::is_unsigned_v<std::atomic_unsigned_lock_free::value_type>);
static_assert(std::is_integral_v<std::atomic_unsigned_lock_free::value_type>);
/*
test<std::shared_ptr<int>>();
*/
#endif

return 0;
return 0;
}
Loading