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 Dionneint 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