xref: /llvm-project/libcxx/test/std/atomics/atomics.types.generic/pointer.compile.pass.cpp (revision bf1666fb0bc19ffa18072e2727e4611c293a9aee)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03
10 
11 // XFAIL: availability-synchronization_library-missing
12 
13 // <atomic>
14 
15 // Tests the basic features and makes sure they work with a hijacking operator&.
16 
17 //  template<class T> struct atomic<T*> {
18 //    using value_type = T*;
19 //    using difference_type = ptrdiff_t;
20 //
21 //    static constexpr bool is_always_lock_free = implementation-defined;
22 //    bool is_lock_free() const volatile noexcept;
23 //    bool is_lock_free() const noexcept;
24 //
25 //    constexpr atomic() noexcept;
26 //    constexpr atomic(T*) noexcept;
27 //    atomic(const atomic&) = delete;
28 //    atomic& operator=(const atomic&) = delete;
29 //    atomic& operator=(const atomic&) volatile = delete;
30 //
31 //    void store(T*, memory_order = memory_order::seq_cst) volatile noexcept;
32 //    void store(T*, memory_order = memory_order::seq_cst) noexcept;
33 //    T* operator=(T*) volatile noexcept;
34 //    T* operator=(T*) noexcept;
35 //    T* load(memory_order = memory_order::seq_cst) const volatile noexcept;
36 //    T* load(memory_order = memory_order::seq_cst) const noexcept;
37 //    operator T*() const volatile noexcept;
38 //    operator T*() const noexcept;
39 //
40 //    T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept;
41 //    T* exchange(T*, memory_order = memory_order::seq_cst) noexcept;
42 //    bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept;
43 //    bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept;
44 //    bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept;
45 //    bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept;
46 //    bool compare_exchange_weak(T*&, T*,
47 //                               memory_order = memory_order::seq_cst) volatile noexcept;
48 //    bool compare_exchange_weak(T*&, T*,
49 //                               memory_order = memory_order::seq_cst) noexcept;
50 //    bool compare_exchange_strong(T*&, T*,
51 //                                 memory_order = memory_order::seq_cst) volatile noexcept;
52 //    bool compare_exchange_strong(T*&, T*,
53 //                                 memory_order = memory_order::seq_cst) noexcept;
54 //
55 //    T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
56 //    T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
57 //    T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept;
58 //    T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept;
59 //
60 //    T* operator++(int) volatile noexcept;
61 //    T* operator++(int) noexcept;
62 //    T* operator--(int) volatile noexcept;
63 //    T* operator--(int) noexcept;
64 //    T* operator++() volatile noexcept;
65 //    T* operator++() noexcept;
66 //    T* operator--() volatile noexcept;
67 //    T* operator--() noexcept;
68 //    T* operator+=(ptrdiff_t) volatile noexcept;
69 //    T* operator+=(ptrdiff_t) noexcept;
70 //    T* operator-=(ptrdiff_t) volatile noexcept;
71 //    T* operator-=(ptrdiff_t) noexcept;
72 //
73 //    void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept;
74 //    void wait(T*, memory_order = memory_order::seq_cst) const noexcept;
75 //    void notify_one() volatile noexcept;
76 //    void notify_one() noexcept;
77 //    void notify_all() volatile noexcept;
78 //    void notify_all() noexcept;
79 //  };
80 
81 #include <atomic>
82 #include <type_traits>
83 
84 #include "operator_hijacker.h"
85 #include "test_macros.h"
86 
87 template <class T>
88 void test() {
89   T a;
90   typename T::value_type v = nullptr;
91 #if TEST_STD_VER >= 20
92   std::memory_order m = std::memory_order::seq_cst;
93 #else
94   std::memory_order m = std::memory_order_seq_cst;
95 #endif
96 
97   TEST_IGNORE_NODISCARD a.is_lock_free();
98 
99   a.store(v);
100   a = v;
101 
102   TEST_DIAGNOSTIC_PUSH
103   // MSVC warning C4197: 'volatile std::atomic<operator_hijacker *>': top-level volatile in cast is ignored
104   TEST_MSVC_DIAGNOSTIC_IGNORED(4197)
105 
106   TEST_IGNORE_NODISCARD T();
107   TEST_IGNORE_NODISCARD T(v);
108 
109   TEST_DIAGNOSTIC_POP
110 
111   TEST_IGNORE_NODISCARD a.load();
112   TEST_IGNORE_NODISCARD static_cast<typename T::value_type>(a);
113   TEST_IGNORE_NODISCARD* a;
114 
115   TEST_IGNORE_NODISCARD a.exchange(v);
116   TEST_IGNORE_NODISCARD a.compare_exchange_weak(v, v, m, m);
117   TEST_IGNORE_NODISCARD a.compare_exchange_strong(v, v, m, m);
118   TEST_IGNORE_NODISCARD a.compare_exchange_weak(v, v);
119   TEST_IGNORE_NODISCARD a.compare_exchange_strong(v, v, m);
120 
121   TEST_IGNORE_NODISCARD a.fetch_add(0);
122   TEST_IGNORE_NODISCARD a.fetch_sub(0);
123 
124   TEST_IGNORE_NODISCARD a++;
125   TEST_IGNORE_NODISCARD a--;
126   TEST_IGNORE_NODISCARD++ a;
127   TEST_IGNORE_NODISCARD-- a;
128   a += 0;
129   a -= 0;
130 
131 #if TEST_STD_VER >= 20
132   a.wait(v);
133   a.notify_one();
134   a.notify_all();
135 #endif
136 }
137 
138 void test() {
139   test<std::atomic<operator_hijacker*>>();
140   test<volatile std::atomic<operator_hijacker*>>();
141 }
142