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 #include <cassert> 10 #include <cxxabi.h> 11 12 #include "test_macros.h" 13 14 #ifndef TEST_HAS_NO_THREADS 15 # include <thread> 16 # include "make_test_thread.h" 17 #endif 18 19 // Ensure that we initialize each variable once and only once. 20 namespace test1 { 21 static int run_count = 0; increment()22 int increment() { 23 ++run_count; 24 return 0; 25 } helper()26 void helper() { 27 static int a = increment(); 28 ((void)a); 29 } test()30 void test() { 31 static int a = increment(); ((void)a); 32 assert(run_count == 1); 33 static int b = increment(); ((void)b); 34 assert(run_count == 2); 35 helper(); 36 assert(run_count == 3); 37 helper(); 38 assert(run_count == 3); 39 } 40 } 41 42 // When initialization fails, ensure that we try to initialize it again next 43 // time. 44 namespace test2 { 45 #ifndef TEST_HAS_NO_EXCEPTIONS 46 static int run_count = 0; increment()47 int increment() { 48 ++run_count; 49 throw 0; 50 } helper()51 void helper() { 52 try { 53 static int a = increment(); 54 assert(false); 55 ((void)a); 56 } catch (...) {} 57 } test()58 void test() { 59 helper(); 60 assert(run_count == 1); 61 helper(); 62 assert(run_count == 2); 63 } 64 #else 65 void test() {} 66 #endif 67 } 68 69 // Check that we can initialize a second value while initializing a first. 70 namespace test3 { zero()71 int zero() { 72 return 0; 73 } 74 one()75 int one() { 76 static int b = zero(); ((void)b); 77 return 0; 78 } 79 test()80 void test() { 81 static int a = one(); ((void)a); 82 } 83 } 84 85 #ifndef TEST_HAS_NO_THREADS 86 // A simple thread test of two threads racing to initialize a variable. This 87 // isn't guaranteed to catch any particular threading problems. 88 namespace test4 { 89 static int run_count = 0; increment()90 int increment() { 91 ++run_count; 92 return 0; 93 } 94 helper()95 void helper() { 96 static int a = increment(); ((void)a); 97 } 98 test()99 void test() { 100 std::thread t1 = support::make_test_thread(helper); 101 std::thread t2 = support::make_test_thread(helper); 102 t1.join(); 103 t2.join(); 104 assert(run_count == 1); 105 } 106 } 107 108 // Check that we don't re-initialize a static variable even when it's 109 // encountered from two different threads. 110 namespace test5 { 111 static int run_count = 0; zero()112 int zero() { 113 ++run_count; 114 return 0; 115 } 116 one()117 int one() { 118 static int b = zero(); ((void)b); 119 return 0; 120 } 121 another_helper()122 void another_helper() { 123 static int a = one(); ((void)a); 124 } 125 helper()126 void helper() { 127 static int a = one(); ((void)a); 128 std::thread t = support::make_test_thread(another_helper); 129 t.join(); 130 } 131 test()132 void test() { 133 std::thread t = support::make_test_thread(helper); 134 t.join(); 135 assert(run_count == 1); 136 } 137 } 138 #endif /* TEST_HAS_NO_THREADS */ 139 main(int,char **)140int main(int, char**) 141 { 142 test1::test(); 143 test2::test(); 144 test3::test(); 145 #ifndef TEST_HAS_NO_THREADS 146 test4::test(); 147 test5::test(); 148 #endif 149 150 return 0; 151 } 152