1*42ba740aSDamien L-G // 2*42ba740aSDamien L-G // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 3*42ba740aSDamien L-G // See https://llvm.org/LICENSE.txt for license information. 4*42ba740aSDamien L-G // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5*42ba740aSDamien L-G // 6*42ba740aSDamien L-G //===----------------------------------------------------------------------===// 7*42ba740aSDamien L-G 8*42ba740aSDamien L-G // UNSUPPORTED: c++03, c++11, c++14, c++17 9*42ba740aSDamien L-G // XFAIL: !has-64-bit-atomics 10*42ba740aSDamien L-G 11*42ba740aSDamien L-G // integral-type operator++(int) const noexcept; 12*42ba740aSDamien L-G // integral-type operator--(int) const noexcept; 13*42ba740aSDamien L-G // integral-type operator++() const noexcept; 14*42ba740aSDamien L-G // integral-type operator--() const noexcept; 15*42ba740aSDamien L-G 16*42ba740aSDamien L-G #include <atomic> 17*42ba740aSDamien L-G #include <cassert> 18*42ba740aSDamien L-G #include <concepts> 19*42ba740aSDamien L-G #include <type_traits> 20*42ba740aSDamien L-G 21*42ba740aSDamien L-G #include "atomic_helpers.h" 22*42ba740aSDamien L-G #include "test_macros.h" 23*42ba740aSDamien L-G 24*42ba740aSDamien L-G template <typename T> 25*42ba740aSDamien L-G concept has_pre_increment_operator = requires { ++std::declval<T const>(); }; 26*42ba740aSDamien L-G 27*42ba740aSDamien L-G template <typename T> 28*42ba740aSDamien L-G concept has_post_increment_operator = requires { std::declval<T const>()++; }; 29*42ba740aSDamien L-G 30*42ba740aSDamien L-G template <typename T> 31*42ba740aSDamien L-G concept has_pre_decrement_operator = requires { --std::declval<T const>(); }; 32*42ba740aSDamien L-G 33*42ba740aSDamien L-G template <typename T> 34*42ba740aSDamien L-G concept has_post_decrement_operator = requires { std::declval<T const>()--; }; 35*42ba740aSDamien L-G 36*42ba740aSDamien L-G template <typename T> 37*42ba740aSDamien L-G constexpr bool does_not_have_increment_nor_decrement_operators() { 38*42ba740aSDamien L-G return !has_pre_increment_operator<T> && !has_pre_decrement_operator<T> && !has_post_increment_operator<T> && 39*42ba740aSDamien L-G !has_post_decrement_operator<T>; 40*42ba740aSDamien L-G } 41*42ba740aSDamien L-G 42*42ba740aSDamien L-G template <typename T> 43*42ba740aSDamien L-G struct TestDoesNotHaveIncrementDecrement { 44*42ba740aSDamien L-G void operator()() const { static_assert(does_not_have_increment_nor_decrement_operators<T>()); } 45*42ba740aSDamien L-G }; 46*42ba740aSDamien L-G 47*42ba740aSDamien L-G template <typename T> 48*42ba740aSDamien L-G struct TestIncrementDecrement { 49*42ba740aSDamien L-G void operator()() const { 50*42ba740aSDamien L-G static_assert(std::is_integral_v<T>); 51*42ba740aSDamien L-G 52*42ba740aSDamien L-G T x(T(1)); 53*42ba740aSDamien L-G std::atomic_ref<T> const a(x); 54*42ba740aSDamien L-G 55*42ba740aSDamien L-G { 56*42ba740aSDamien L-G std::same_as<T> decltype(auto) y = ++a; 57*42ba740aSDamien L-G assert(y == T(2)); 58*42ba740aSDamien L-G assert(x == T(2)); 59*42ba740aSDamien L-G ASSERT_NOEXCEPT(++a); 60*42ba740aSDamien L-G } 61*42ba740aSDamien L-G 62*42ba740aSDamien L-G { 63*42ba740aSDamien L-G std::same_as<T> decltype(auto) y = --a; 64*42ba740aSDamien L-G assert(y == T(1)); 65*42ba740aSDamien L-G assert(x == T(1)); 66*42ba740aSDamien L-G ASSERT_NOEXCEPT(--a); 67*42ba740aSDamien L-G } 68*42ba740aSDamien L-G 69*42ba740aSDamien L-G { 70*42ba740aSDamien L-G std::same_as<T> decltype(auto) y = a++; 71*42ba740aSDamien L-G assert(y == T(1)); 72*42ba740aSDamien L-G assert(x == T(2)); 73*42ba740aSDamien L-G ASSERT_NOEXCEPT(a++); 74*42ba740aSDamien L-G } 75*42ba740aSDamien L-G 76*42ba740aSDamien L-G { 77*42ba740aSDamien L-G std::same_as<T> decltype(auto) y = a--; 78*42ba740aSDamien L-G assert(y == T(2)); 79*42ba740aSDamien L-G assert(x == T(1)); 80*42ba740aSDamien L-G ASSERT_NOEXCEPT(a--); 81*42ba740aSDamien L-G } 82*42ba740aSDamien L-G } 83*42ba740aSDamien L-G }; 84*42ba740aSDamien L-G 85*42ba740aSDamien L-G int main(int, char**) { 86*42ba740aSDamien L-G TestEachIntegralType<TestIncrementDecrement>()(); 87*42ba740aSDamien L-G 88*42ba740aSDamien L-G TestEachFloatingPointType<TestDoesNotHaveIncrementDecrement>()(); 89*42ba740aSDamien L-G 90*42ba740aSDamien L-G TestEachPointerType<TestDoesNotHaveIncrementDecrement>()(); 91*42ba740aSDamien L-G 92*42ba740aSDamien L-G TestDoesNotHaveIncrementDecrement<bool>()(); 93*42ba740aSDamien L-G TestDoesNotHaveIncrementDecrement<UserAtomicType>()(); 94*42ba740aSDamien L-G TestDoesNotHaveIncrementDecrement<LargeUserAtomicType>()(); 95*42ba740aSDamien L-G 96*42ba740aSDamien L-G return 0; 97*42ba740aSDamien L-G } 98