81 lines · cpp
1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7 8// UNSUPPORTED: c++03, c++11, c++14, c++179// XFAIL: !has-64-bit-atomics10 11// integral-type operator+=(integral-type) const noexcept;12// floating-point-type operator+=(floating-point-type) const noexcept;13// T* operator+=(difference_type) const noexcept;14 15#include <atomic>16#include <cassert>17#include <concepts>18#include <type_traits>19#include <utility>20 21#include "atomic_helpers.h"22#include "test_helper.h"23#include "test_macros.h"24 25template <typename T>26concept has_operator_plus_equals = requires { std::declval<T const>() += std::declval<T>(); };27 28template <typename T>29struct TestDoesNotHaveOperatorPlusEquals {30 void operator()() const { static_assert(!has_operator_plus_equals<std::atomic_ref<T>>); }31};32 33template <typename T>34struct TestOperatorPlusEquals {35 void operator()() const {36 if constexpr (std::is_arithmetic_v<T>) {37 T x(T(1));38 std::atomic_ref<T> const a(x);39 40 std::same_as<T> decltype(auto) y = (a += T(2));41 assert(y == T(3));42 assert(x == T(3));43 ASSERT_NOEXCEPT(a += T(0));44 } else if constexpr (std::is_pointer_v<T>) {45 using U = std::remove_pointer_t<T>;46 U t[9] = {};47 T p{&t[1]};48 std::atomic_ref<T> const a(p);49 50 std::same_as<T> decltype(auto) y = (a += 2);51 assert(y == &t[3]);52 assert(a == &t[3]);53 ASSERT_NOEXCEPT(a += 0);54 } else {55 static_assert(std::is_void_v<T>);56 }57 58 // memory_order::seq_cst59 {60 auto plus_equals = [](std::atomic_ref<T> const& x, T old_val, T new_val) { x += (new_val - old_val); };61 auto load = [](std::atomic_ref<T> const& x) { return x.load(); };62 test_seq_cst<T>(plus_equals, load);63 }64 }65};66 67int main(int, char**) {68 TestEachIntegralType<TestOperatorPlusEquals>()();69 70 TestOperatorPlusEquals<float>()();71 TestOperatorPlusEquals<double>()();72 73 TestEachPointerType<TestOperatorPlusEquals>()();74 75 TestDoesNotHaveOperatorPlusEquals<bool>()();76 TestDoesNotHaveOperatorPlusEquals<UserAtomicType>()();77 TestDoesNotHaveOperatorPlusEquals<LargeUserAtomicType>()();78 79 return 0;80}81