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