xref: /llvm-project/libcxxabi/test/test_guard.pass.cpp (revision 851bfc07c86e7f84ee38d918cb4b6b49a47434f1)
1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===//
2e434b34fSJonathan Roelofs //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e434b34fSJonathan Roelofs //
7e434b34fSJonathan Roelofs //===----------------------------------------------------------------------===//
8e434b34fSJonathan Roelofs 
9e434b34fSJonathan Roelofs #include <cassert>
10*851bfc07SLouis Dionne #include <cxxabi.h>
11e434b34fSJonathan Roelofs 
12*851bfc07SLouis Dionne #include "test_macros.h"
13*851bfc07SLouis Dionne 
14*851bfc07SLouis Dionne #ifndef TEST_HAS_NO_THREADS
15e434b34fSJonathan Roelofs #   include <thread>
1656462801SLouis Dionne #   include "make_test_thread.h"
17e434b34fSJonathan Roelofs #endif
18e434b34fSJonathan Roelofs 
19e434b34fSJonathan Roelofs // Ensure that we initialize each variable once and only once.
20e434b34fSJonathan Roelofs namespace test1 {
21e434b34fSJonathan Roelofs     static int run_count = 0;
increment()22e434b34fSJonathan Roelofs     int increment() {
23e434b34fSJonathan Roelofs         ++run_count;
24e434b34fSJonathan Roelofs         return 0;
25e434b34fSJonathan Roelofs     }
helper()26e434b34fSJonathan Roelofs     void helper() {
27e434b34fSJonathan Roelofs         static int a = increment();
28a140cba7SEric Fiselier         ((void)a);
29e434b34fSJonathan Roelofs     }
test()30e434b34fSJonathan Roelofs     void test() {
31a140cba7SEric Fiselier         static int a = increment(); ((void)a);
32e434b34fSJonathan Roelofs         assert(run_count == 1);
33a140cba7SEric Fiselier         static int b = increment(); ((void)b);
34e434b34fSJonathan Roelofs         assert(run_count == 2);
35e434b34fSJonathan Roelofs         helper();
36e434b34fSJonathan Roelofs         assert(run_count == 3);
37e434b34fSJonathan Roelofs         helper();
38e434b34fSJonathan Roelofs         assert(run_count == 3);
39e434b34fSJonathan Roelofs     }
40e434b34fSJonathan Roelofs }
41e434b34fSJonathan Roelofs 
42e434b34fSJonathan Roelofs // When initialization fails, ensure that we try to initialize it again next
43e434b34fSJonathan Roelofs // time.
44e434b34fSJonathan Roelofs namespace test2 {
45e6d94f4bSLouis Dionne #ifndef TEST_HAS_NO_EXCEPTIONS
46e434b34fSJonathan Roelofs     static int run_count = 0;
increment()47e434b34fSJonathan Roelofs     int increment() {
48e434b34fSJonathan Roelofs         ++run_count;
49e434b34fSJonathan Roelofs         throw 0;
50e434b34fSJonathan Roelofs     }
helper()51e434b34fSJonathan Roelofs     void helper() {
52e434b34fSJonathan Roelofs         try {
53e434b34fSJonathan Roelofs             static int a = increment();
54a140cba7SEric Fiselier             assert(false);
55a140cba7SEric Fiselier             ((void)a);
56e434b34fSJonathan Roelofs         } catch (...) {}
57e434b34fSJonathan Roelofs     }
test()58e434b34fSJonathan Roelofs     void test() {
59e434b34fSJonathan Roelofs         helper();
60e434b34fSJonathan Roelofs         assert(run_count == 1);
61e434b34fSJonathan Roelofs         helper();
62e434b34fSJonathan Roelofs         assert(run_count == 2);
63e434b34fSJonathan Roelofs     }
6457e446daSAsiri Rathnayake #else
6557e446daSAsiri Rathnayake    void test() {}
6657e446daSAsiri Rathnayake #endif
67e434b34fSJonathan Roelofs }
68e434b34fSJonathan Roelofs 
69e434b34fSJonathan Roelofs // Check that we can initialize a second value while initializing a first.
70e434b34fSJonathan Roelofs namespace test3 {
zero()71e434b34fSJonathan Roelofs     int zero() {
72e434b34fSJonathan Roelofs         return 0;
73e434b34fSJonathan Roelofs     }
74e434b34fSJonathan Roelofs 
one()75e434b34fSJonathan Roelofs     int one() {
76a140cba7SEric Fiselier         static int b = zero(); ((void)b);
77e434b34fSJonathan Roelofs         return 0;
78e434b34fSJonathan Roelofs     }
79e434b34fSJonathan Roelofs 
test()80e434b34fSJonathan Roelofs     void test() {
81a140cba7SEric Fiselier         static int a = one(); ((void)a);
82e434b34fSJonathan Roelofs     }
83e434b34fSJonathan Roelofs }
84e434b34fSJonathan Roelofs 
85*851bfc07SLouis Dionne #ifndef TEST_HAS_NO_THREADS
86e434b34fSJonathan Roelofs // A simple thread test of two threads racing to initialize a variable. This
87e434b34fSJonathan Roelofs // isn't guaranteed to catch any particular threading problems.
88e434b34fSJonathan Roelofs namespace test4 {
89e434b34fSJonathan Roelofs     static int run_count = 0;
increment()90e434b34fSJonathan Roelofs     int increment() {
91e434b34fSJonathan Roelofs         ++run_count;
92e434b34fSJonathan Roelofs         return 0;
93e434b34fSJonathan Roelofs     }
94e434b34fSJonathan Roelofs 
helper()95e434b34fSJonathan Roelofs     void helper() {
96a140cba7SEric Fiselier         static int a = increment(); ((void)a);
97e434b34fSJonathan Roelofs     }
98e434b34fSJonathan Roelofs 
test()99e434b34fSJonathan Roelofs     void test() {
10056462801SLouis Dionne         std::thread t1 = support::make_test_thread(helper);
10156462801SLouis Dionne         std::thread t2 = support::make_test_thread(helper);
102e434b34fSJonathan Roelofs         t1.join();
103e434b34fSJonathan Roelofs         t2.join();
104e434b34fSJonathan Roelofs         assert(run_count == 1);
105e434b34fSJonathan Roelofs     }
106e434b34fSJonathan Roelofs }
107e434b34fSJonathan Roelofs 
108e434b34fSJonathan Roelofs // Check that we don't re-initialize a static variable even when it's
109e434b34fSJonathan Roelofs // encountered from two different threads.
110e434b34fSJonathan Roelofs namespace test5 {
111e434b34fSJonathan Roelofs     static int run_count = 0;
zero()112e434b34fSJonathan Roelofs     int zero() {
113e434b34fSJonathan Roelofs         ++run_count;
114e434b34fSJonathan Roelofs         return 0;
115e434b34fSJonathan Roelofs     }
116e434b34fSJonathan Roelofs 
one()117e434b34fSJonathan Roelofs     int one() {
118a140cba7SEric Fiselier         static int b = zero(); ((void)b);
119e434b34fSJonathan Roelofs         return 0;
120e434b34fSJonathan Roelofs     }
121e434b34fSJonathan Roelofs 
another_helper()122e434b34fSJonathan Roelofs     void another_helper() {
123a140cba7SEric Fiselier         static int a = one(); ((void)a);
124e434b34fSJonathan Roelofs     }
125e434b34fSJonathan Roelofs 
helper()126e434b34fSJonathan Roelofs     void helper() {
127a140cba7SEric Fiselier         static int a = one(); ((void)a);
12856462801SLouis Dionne         std::thread t = support::make_test_thread(another_helper);
129e434b34fSJonathan Roelofs         t.join();
130e434b34fSJonathan Roelofs     }
131e434b34fSJonathan Roelofs 
test()132e434b34fSJonathan Roelofs     void test() {
13356462801SLouis Dionne         std::thread t = support::make_test_thread(helper);
134e434b34fSJonathan Roelofs         t.join();
135e434b34fSJonathan Roelofs         assert(run_count == 1);
136e434b34fSJonathan Roelofs     }
137e434b34fSJonathan Roelofs }
138*851bfc07SLouis Dionne #endif /* TEST_HAS_NO_THREADS */
139e434b34fSJonathan Roelofs 
main(int,char **)140504bc07dSLouis Dionne int main(int, char**)
141e434b34fSJonathan Roelofs {
142e434b34fSJonathan Roelofs     test1::test();
143e434b34fSJonathan Roelofs     test2::test();
144e434b34fSJonathan Roelofs     test3::test();
145*851bfc07SLouis Dionne #ifndef TEST_HAS_NO_THREADS
146e434b34fSJonathan Roelofs     test4::test();
147e434b34fSJonathan Roelofs     test5::test();
148e434b34fSJonathan Roelofs #endif
149504bc07dSLouis Dionne 
150504bc07dSLouis Dionne     return 0;
151e434b34fSJonathan Roelofs }
152