xref: /llvm-project/libcxx/test/std/atomics/atomics.ref/fetch_or.pass.cpp (revision 09e3a360581dc36d0820d3fb6da9bd7cfed87b5d)
142ba740aSDamien L-G //
242ba740aSDamien L-G // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
342ba740aSDamien L-G // See https://llvm.org/LICENSE.txt for license information.
442ba740aSDamien L-G // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
542ba740aSDamien L-G //
642ba740aSDamien L-G //===----------------------------------------------------------------------===//
742ba740aSDamien L-G 
842ba740aSDamien L-G // UNSUPPORTED: c++03, c++11, c++14, c++17
942ba740aSDamien L-G // XFAIL: !has-64-bit-atomics
1042ba740aSDamien L-G 
1142ba740aSDamien L-G // integral-type fetch_or(integral-type, memory_order = memory_order::seq_cst) const noexcept;
1242ba740aSDamien L-G 
1342ba740aSDamien L-G #include <atomic>
1442ba740aSDamien L-G #include <cassert>
15*09e3a360SLouis Dionne #include <concepts>
1642ba740aSDamien L-G #include <type_traits>
17*09e3a360SLouis Dionne #include <utility>
1842ba740aSDamien L-G 
1942ba740aSDamien L-G #include "atomic_helpers.h"
2042ba740aSDamien L-G #include "test_macros.h"
2142ba740aSDamien L-G 
2242ba740aSDamien L-G template <typename T>
2342ba740aSDamien L-G concept has_fetch_or = requires {
2442ba740aSDamien L-G   std::declval<T const>().fetch_or(std::declval<T>());
2542ba740aSDamien L-G   std::declval<T const>().fetch_or(std::declval<T>(), std::declval<std::memory_order>());
2642ba740aSDamien L-G };
2742ba740aSDamien L-G 
2842ba740aSDamien L-G template <typename T>
2942ba740aSDamien L-G struct TestDoesNotHaveFetchOr {
3042ba740aSDamien L-G   void operator()() const { static_assert(!has_fetch_or<std::atomic_ref<T>>); }
3142ba740aSDamien L-G };
3242ba740aSDamien L-G 
3342ba740aSDamien L-G template <typename T>
3442ba740aSDamien L-G struct TestFetchOr {
3542ba740aSDamien L-G   void operator()() const {
3642ba740aSDamien L-G     static_assert(std::is_integral_v<T>);
3742ba740aSDamien L-G 
3842ba740aSDamien L-G     T x(T(1));
3942ba740aSDamien L-G     std::atomic_ref<T> const a(x);
4042ba740aSDamien L-G 
4142ba740aSDamien L-G     {
4242ba740aSDamien L-G       std::same_as<T> decltype(auto) y = a.fetch_or(T(2));
4342ba740aSDamien L-G       assert(y == T(1));
4442ba740aSDamien L-G       assert(x == T(3));
4542ba740aSDamien L-G       ASSERT_NOEXCEPT(a.fetch_or(T(0)));
4642ba740aSDamien L-G     }
4742ba740aSDamien L-G 
4842ba740aSDamien L-G     {
4942ba740aSDamien L-G       std::same_as<T> decltype(auto) y = a.fetch_or(T(2), std::memory_order_relaxed);
5042ba740aSDamien L-G       assert(y == T(3));
5142ba740aSDamien L-G       assert(x == T(3));
5242ba740aSDamien L-G       ASSERT_NOEXCEPT(a.fetch_or(T(0), std::memory_order_relaxed));
5342ba740aSDamien L-G     }
5442ba740aSDamien L-G   }
5542ba740aSDamien L-G };
5642ba740aSDamien L-G 
5742ba740aSDamien L-G int main(int, char**) {
5842ba740aSDamien L-G   TestEachIntegralType<TestFetchOr>()();
5942ba740aSDamien L-G 
6042ba740aSDamien L-G   TestEachFloatingPointType<TestDoesNotHaveFetchOr>()();
6142ba740aSDamien L-G 
6242ba740aSDamien L-G   TestEachPointerType<TestDoesNotHaveFetchOr>()();
6342ba740aSDamien L-G 
6442ba740aSDamien L-G   TestDoesNotHaveFetchOr<bool>()();
6542ba740aSDamien L-G   TestDoesNotHaveFetchOr<UserAtomicType>()();
6642ba740aSDamien L-G   TestDoesNotHaveFetchOr<LargeUserAtomicType>()();
6742ba740aSDamien L-G 
6842ba740aSDamien L-G   return 0;
6942ba740aSDamien L-G }
70