[flang] Lower procedure pointer components (#75453)
[llvm-project.git] / libcxxabi / test / guard_test_basic.pass.cpp
blobdca906a1aae7db0eb7473ba12223ebb16d3bf033
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
11 // Necessary because we include a private header of libc++abi, which
12 // only understands _LIBCXXABI_HAS_NO_THREADS.
13 #include "test_macros.h"
14 #ifdef TEST_HAS_NO_THREADS
15 # define _LIBCXXABI_HAS_NO_THREADS
16 #endif
18 #define TESTING_CXA_GUARD
19 #include "../src/cxa_guard_impl.h"
20 #include <cassert>
21 #include <type_traits>
23 #if defined(__clang__)
24 # pragma clang diagnostic ignored "-Wtautological-pointer-compare"
25 #elif defined(__GNUC__)
26 # pragma GCC diagnostic ignored "-Waddress"
27 #endif
29 using namespace __cxxabiv1;
31 template <class GuardType, class Impl>
32 struct Tests {
33 private:
34 Tests() : g{}, impl(&g) {}
35 GuardType g;
36 Impl impl;
38 uint8_t first_byte() {
39 uint8_t first;
40 std::memcpy(&first, &g, 1);
41 return first;
44 void reset() { g = {}; }
46 public:
47 // Test the post conditions on cxa_guard_acquire, cxa_guard_abort, and
48 // cxa_guard_release. Specifically, that they leave the first byte with
49 // the value 0 or 1 as specified by the ARM or Itanium specification.
50 static void test() {
51 Tests tests;
52 tests.test_acquire();
53 tests.test_abort();
54 tests.test_release();
57 void test_acquire() {
59 reset();
60 assert(first_byte() == 0);
61 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
62 assert(first_byte() == 0);
65 reset();
66 assert(first_byte() == 0);
67 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
68 impl.cxa_guard_release();
69 assert(first_byte() == 1);
70 assert(impl.cxa_guard_acquire() == INIT_IS_DONE);
74 void test_release() {
76 reset();
77 assert(first_byte() == 0);
78 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
79 assert(first_byte() == 0);
80 impl.cxa_guard_release();
81 assert(first_byte() == 1);
85 void test_abort() {
87 reset();
88 assert(first_byte() == 0);
89 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
90 assert(first_byte() == 0);
91 impl.cxa_guard_abort();
92 assert(first_byte() == 0);
93 assert(impl.cxa_guard_acquire() == INIT_IS_PENDING);
94 assert(first_byte() == 0);
99 struct NopMutex {
100 bool lock() {
101 assert(!is_locked);
102 is_locked = true;
103 return false;
105 bool unlock() {
106 assert(is_locked);
107 is_locked = false;
108 return false;
111 private:
112 bool is_locked = false;
114 NopMutex global_nop_mutex = {};
116 struct NopCondVar {
117 bool broadcast() { return false; }
118 bool wait(NopMutex&) { return false; }
120 NopCondVar global_nop_cond = {};
122 void NopFutexWait(int*, int) { assert(false); }
123 void NopFutexWake(int*) { assert(false); }
124 uint32_t MockGetThreadID() { return 0; }
126 int main(int, char**) {
128 #if defined(TEST_HAS_NO_THREADS)
129 static_assert(CurrentImplementation == Implementation::NoThreads, "");
130 static_assert(std::is_same<SelectedImplementation, NoThreadsGuard>::value, "");
131 #else
132 static_assert(CurrentImplementation == Implementation::GlobalMutex, "");
133 static_assert(std::is_same<SelectedImplementation,
134 GlobalMutexGuard<LibcppMutex, LibcppCondVar, GlobalStatic<LibcppMutex>::instance,
135 GlobalStatic<LibcppCondVar>::instance>>::value,
136 "");
137 #endif
140 #if (defined(__APPLE__) || defined(__linux__)) && !defined(TEST_HAS_NO_THREADS)
141 assert(PlatformThreadID);
142 #endif
143 if (PlatformThreadID != nullptr) {
144 assert(PlatformThreadID() != 0);
145 assert(PlatformThreadID() == PlatformThreadID());
149 Tests<uint32_t, NoThreadsGuard>::test();
150 Tests<uint64_t, NoThreadsGuard>::test();
153 using MutexImpl = GlobalMutexGuard<NopMutex, NopCondVar, global_nop_mutex, global_nop_cond, MockGetThreadID>;
154 Tests<uint32_t, MutexImpl>::test();
155 Tests<uint64_t, MutexImpl>::test();
158 using FutexImpl = FutexGuard<&NopFutexWait, &NopFutexWake, &MockGetThreadID>;
159 Tests<uint32_t, FutexImpl>::test();
160 Tests<uint64_t, FutexImpl>::test();
163 return 0;