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