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
87template <class T>
88void 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 a.wait(v);
132 a.notify_one();
133 a.notify_all();
134}
135
136void test() {
137 test<std::atomic<operator_hijacker*>>();
138 test<volatile std::atomic<operator_hijacker*>>();
139}
140

source code of libcxx/test/std/atomics/atomics.types.generic/pointer.compile.pass.cpp