xref: /llvm-project/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp (revision 42ba740afffa16f991be6aa36626bd872d41ebc0)
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