152 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include <cassert>10#include <cxxabi.h>11 12#include "test_macros.h"13 14#ifndef TEST_HAS_NO_THREADS15# include <thread>16# include "make_test_thread.h"17#endif18 19// Ensure that we initialize each variable once and only once.20namespace test1 {21 static int run_count = 0;22 int increment() {23 ++run_count;24 return 0;25 }26 void helper() {27 static int a = increment();28 ((void)a);29 }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 next43// time.44namespace test2 {45#ifndef TEST_HAS_NO_EXCEPTIONS46 static int run_count = 0;47 int increment() {48 ++run_count;49 throw 0;50 }51 void helper() {52 try {53 static int a = increment();54 assert(false);55 ((void)a);56 } catch (...) {}57 }58 void test() {59 helper();60 assert(run_count == 1);61 helper();62 assert(run_count == 2);63 }64#else65 void test() {}66#endif67}68 69// Check that we can initialize a second value while initializing a first.70namespace test3 {71 int zero() {72 return 0;73 }74 75 int one() {76 static int b = zero(); ((void)b);77 return 0;78 }79 80 void test() {81 static int a = one(); ((void)a);82 }83}84 85#ifndef TEST_HAS_NO_THREADS86// A simple thread test of two threads racing to initialize a variable. This87// isn't guaranteed to catch any particular threading problems.88namespace test4 {89 static int run_count = 0;90 int increment() {91 ++run_count;92 return 0;93 }94 95 void helper() {96 static int a = increment(); ((void)a);97 }98 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's109// encountered from two different threads.110namespace test5 {111 static int run_count = 0;112 int zero() {113 ++run_count;114 return 0;115 }116 117 int one() {118 static int b = zero(); ((void)b);119 return 0;120 }121 122 void another_helper() {123 static int a = one(); ((void)a);124 }125 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 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 140int main(int, char**)141{142 test1::test();143 test2::test();144 test3::test();145#ifndef TEST_HAS_NO_THREADS146 test4::test();147 test5::test();148#endif149 150 return 0;151}152