// // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 // XFAIL: !has-64-bit-atomics // integral-type operator++(int) const noexcept; // integral-type operator--(int) const noexcept; // integral-type operator++() const noexcept; // integral-type operator--() const noexcept; #include #include #include #include #include #include "atomic_helpers.h" #include "test_macros.h" template concept has_pre_increment_operator = requires { ++std::declval(); }; template concept has_post_increment_operator = requires { std::declval()++; }; template concept has_pre_decrement_operator = requires { --std::declval(); }; template concept has_post_decrement_operator = requires { std::declval()--; }; template constexpr bool does_not_have_increment_nor_decrement_operators() { return !has_pre_increment_operator && !has_pre_decrement_operator && !has_post_increment_operator && !has_post_decrement_operator; } template struct TestDoesNotHaveIncrementDecrement { void operator()() const { static_assert(does_not_have_increment_nor_decrement_operators>()); } }; template struct TestIncrementDecrement { void operator()() const { if constexpr (std::is_integral_v) { T x(T(1)); std::atomic_ref const a(x); { std::same_as decltype(auto) y = ++a; assert(y == T(2)); assert(x == T(2)); ASSERT_NOEXCEPT(++a); } { std::same_as decltype(auto) y = --a; assert(y == T(1)); assert(x == T(1)); ASSERT_NOEXCEPT(--a); } { std::same_as decltype(auto) y = a++; assert(y == T(1)); assert(x == T(2)); ASSERT_NOEXCEPT(a++); } { std::same_as decltype(auto) y = a--; assert(y == T(2)); assert(x == T(1)); ASSERT_NOEXCEPT(a--); } } else if constexpr (std::is_pointer_v) { using U = std::remove_pointer_t; U t[9] = {}; T p{&t[1]}; std::atomic_ref const a(p); { std::same_as decltype(auto) y = ++a; assert(y == &t[2]); assert(p == &t[2]); ASSERT_NOEXCEPT(++a); } { std::same_as decltype(auto) y = --a; assert(y == &t[1]); assert(p == &t[1]); ASSERT_NOEXCEPT(--a); } { std::same_as decltype(auto) y = a++; assert(y == &t[1]); assert(p == &t[2]); ASSERT_NOEXCEPT(a++); } { std::same_as decltype(auto) y = a--; assert(y == &t[2]); assert(p == &t[1]); ASSERT_NOEXCEPT(a--); } } else { static_assert(std::is_void_v); } } }; int main(int, char**) { TestEachIntegralType()(); TestEachFloatingPointType()(); TestEachPointerType()(); TestDoesNotHaveIncrementDecrement()(); TestDoesNotHaveIncrementDecrement()(); TestDoesNotHaveIncrementDecrement()(); return 0; }