Index: libcxx/include/__config =================================================================== --- libcxx/include/__config +++ libcxx/include/__config @@ -1238,10 +1238,12 @@ # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) #endif -#if __has_attribute(require_constant_initialization) -# define _LIBCPP_SAFE_STATIC __attribute__((__require_constant_initialization__)) +#if _LIBCPP_STD_VER > 17 +# define _LIBCPP_CONSTINIT constinit +#elif __has_attribute(require_constant_initialization) +# define _LIBCPP_CONSTINIT __attribute__((__require_constant_initialization__)) #else -# define _LIBCPP_SAFE_STATIC +# define _LIBCPP_CONSTINIT #endif #if __has_attribute(diagnose_if) && !defined(_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS) Index: libcxx/src/debug.cpp =================================================================== --- libcxx/src/debug.cpp +++ libcxx/src/debug.cpp @@ -35,8 +35,7 @@ std::abort(); } -_LIBCPP_SAFE_STATIC __libcpp_debug_function_type - __libcpp_debug_function = __libcpp_abort_debug_function; +constinit __libcpp_debug_function_type __libcpp_debug_function = __libcpp_abort_debug_function; bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) { __libcpp_debug_function = __func; Index: libcxx/src/experimental/memory_resource.cpp =================================================================== --- libcxx/src/experimental/memory_resource.cpp +++ libcxx/src/experimental/memory_resource.cpp @@ -97,7 +97,7 @@ __default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept { #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER - _LIBCPP_SAFE_STATIC static atomic __res{&res_init.resources.new_delete_res}; + static constinit atomic __res{&res_init.resources.new_delete_res}; if (set) { new_res = new_res ? new_res : new_delete_resource(); // TODO: Can a weaker ordering be used? @@ -109,7 +109,7 @@ &__res, memory_order_acquire); } #elif !defined(_LIBCPP_HAS_NO_THREADS) - _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res; + static constinit memory_resource *res = &res_init.resources.new_delete_res; static mutex res_lock; if (set) { new_res = new_res ? new_res : new_delete_resource(); @@ -122,7 +122,7 @@ return res; } #else - _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res; + static constinit memory_resource *res = &res_init.resources.new_delete_res; if (set) { new_res = new_res ? new_res : new_delete_resource(); memory_resource * old_res = res; Index: libcxx/src/experimental/memory_resource_init_helper.h =================================================================== --- libcxx/src/experimental/memory_resource_init_helper.h +++ libcxx/src/experimental/memory_resource_init_helper.h @@ -1,2 +1,2 @@ #pragma GCC system_header -_LIBCPP_SAFE_STATIC ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; +static constinit ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; Index: libcxx/src/memory.cpp =================================================================== --- libcxx/src/memory.cpp +++ libcxx/src/memory.cpp @@ -132,8 +132,8 @@ #if !defined(_LIBCPP_HAS_NO_THREADS) -_LIBCPP_SAFE_STATIC static const std::size_t __sp_mut_count = 16; -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut_back[__sp_mut_count] = +static constexpr std::size_t __sp_mut_count = 16; +static constinit __libcpp_mutex_t mut_back[__sp_mut_count] = { _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, @@ -171,8 +171,7 @@ __sp_mut& __get_sp_mut(const void* p) { - static __sp_mut muts[__sp_mut_count] - { + static constinit __sp_mut muts[__sp_mut_count] = { &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3], &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7], &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11], Index: libcxx/src/mutex.cpp =================================================================== --- libcxx/src/mutex.cpp +++ libcxx/src/mutex.cpp @@ -196,8 +196,8 @@ // keep in sync with: 7741191. #ifndef _LIBCPP_HAS_NO_THREADS -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; -_LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; +static constinit __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; +static constinit __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; #endif void __call_once(volatile once_flag::_State_type& flag, void* arg, Index: libcxx/src/random_shuffle.cpp =================================================================== --- libcxx/src/random_shuffle.cpp +++ libcxx/src/random_shuffle.cpp @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_THREADS -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; +static constinit __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; #endif unsigned __rs_default::__c_ = 0; Index: libcxx/src/support/runtime/exception_fallback.ipp =================================================================== --- libcxx/src/support/runtime/exception_fallback.ipp +++ libcxx/src/support/runtime/exception_fallback.ipp @@ -11,9 +11,8 @@ namespace std { -_LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler; -_LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler; - +static constinit std::terminate_handler __terminate_handler = nullptr; +static constinit std::unexpected_handler __unexpected_handler = nullptr; // libcxxrt provides implementations of these functions itself. unexpected_handler @@ -26,7 +25,6 @@ get_unexpected() noexcept { return __libcpp_atomic_load(&__unexpected_handler); - } _LIBCPP_NORETURN Index: libcxx/src/support/runtime/new_handler_fallback.ipp =================================================================== --- libcxx/src/support/runtime/new_handler_fallback.ipp +++ libcxx/src/support/runtime/new_handler_fallback.ipp @@ -9,7 +9,7 @@ namespace std { -_LIBCPP_SAFE_STATIC static std::new_handler __new_handler; +static constinit std::new_handler __new_handler = nullptr; new_handler set_new_handler(new_handler handler) noexcept Index: libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.pass.cpp =================================================================== --- libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.pass.cpp +++ libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.pass.cpp @@ -18,13 +18,10 @@ using SuspendT = std::experimental::coroutines_v1::suspend_always; -TEST_SAFE_STATIC SuspendT safe_sa; -constexpr SuspendT constexpr_sa; - constexpr bool check_suspend_constexpr() { - SuspendT s{}; - const SuspendT scopy(s); ((void)scopy); - SuspendT smove(std::move(s)); ((void)smove); + SuspendT s; + const SuspendT scopy(s); (void)scopy; + SuspendT smove(std::move(s)); (void)smove; s = scopy; s = std::move(smove); return true; @@ -64,10 +61,6 @@ static_assert(std::is_trivially_copyable::value, ""); static_assert(check_suspend_constexpr(), ""); } - { - // suppress unused warnings for the global constexpr test variable - ((void)constexpr_sa); - } return 0; } Index: libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.pass.cpp =================================================================== --- libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.pass.cpp +++ libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.pass.cpp @@ -16,16 +16,12 @@ namespace coro = std::experimental; -// Test that the type is in the correct namespace using SuspendT = std::experimental::coroutines_v1::suspend_never; -TEST_SAFE_STATIC SuspendT safe_sn; -constexpr SuspendT constexpr_sn; - constexpr bool check_suspend_constexpr() { - SuspendT s{}; - const SuspendT scopy(s); ((void)scopy); - SuspendT smove(std::move(s)); ((void)smove); + SuspendT s; + const SuspendT scopy(s); (void)scopy; + SuspendT smove(std::move(s)); (void)smove; s = scopy; s = std::move(smove); return true; @@ -66,10 +62,6 @@ static_assert(std::is_trivially_copyable::value, ""); static_assert(check_suspend_constexpr(), ""); } - { - // suppress unused warnings for the global constexpr test variable - ((void)constexpr_sn); - } return 0; } Index: libcxx/test/std/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.pass.cpp +++ libcxx/test/std/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.pass.cpp @@ -16,8 +16,6 @@ #include "test_macros.h" -TEST_SAFE_STATIC std::suspend_always safe_sa; - constexpr bool check_suspend_constexpr() { std::suspend_always s{}; const std::suspend_always scopy(s); Index: libcxx/test/std/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.pass.cpp +++ libcxx/test/std/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.pass.cpp @@ -16,11 +16,6 @@ #include "test_macros.h" -// Test that the type 'std::suspend_never' is in the correct namespace - -TEST_SAFE_STATIC std::suspend_never safe_sn; -constexpr std::suspend_never constexpr_sn; - constexpr bool check_suspend_constexpr() { std::suspend_never s{}; const std::suspend_never scopy(s); ((void)scopy); @@ -76,10 +71,6 @@ { static_assert(test_trivial_awaitable_constexpr(true)); } - { - // suppress unused warnings for the global constexpr test variable - ((void)constexpr_sn); - } return 0; } Index: libcxx/test/std/utilities/any/any.class/any.cons/default.pass.cpp =================================================================== --- libcxx/test/std/utilities/any/any.class/any.cons/default.pass.cpp +++ libcxx/test/std/utilities/any/any.class/any.cons/default.pass.cpp @@ -33,8 +33,8 @@ struct TestConstexpr : public std::any { constexpr TestConstexpr() : std::any() {} }; - TEST_SAFE_STATIC static std::any a; - ((void)a); + static TEST_CONSTINIT std::any a; + (void)a; } { DisableAllocationGuard g; ((void)g); Index: libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp =================================================================== --- libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp +++ libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp @@ -31,8 +31,8 @@ #include "unique_ptr_test_helper.h" #if TEST_STD_VER >= 11 -TEST_SAFE_STATIC std::unique_ptr global_static_unique_ptr_single; -TEST_SAFE_STATIC std::unique_ptr global_static_unique_ptr_runtime; +TEST_CONSTINIT std::unique_ptr global_static_unique_ptr_single; +TEST_CONSTINIT std::unique_ptr global_static_unique_ptr_runtime; struct NonDefaultDeleter { NonDefaultDeleter() = delete; Index: libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp =================================================================== --- libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp +++ libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp @@ -20,8 +20,8 @@ #if TEST_STD_VER >= 11 -TEST_SAFE_STATIC std::unique_ptr global_static_unique_ptr_single(nullptr); -TEST_SAFE_STATIC std::unique_ptr global_static_unique_ptr_runtime(nullptr); +TEST_CONSTINIT std::unique_ptr global_static_unique_ptr_single(nullptr); +TEST_CONSTINIT std::unique_ptr global_static_unique_ptr_runtime(nullptr); struct NonDefaultDeleter { NonDefaultDeleter() = delete; Index: libcxx/test/support/test_macros.h =================================================================== --- libcxx/test/support/test_macros.h +++ libcxx/test/support/test_macros.h @@ -206,10 +206,12 @@ #define TEST_HAS_NO_ALIGNED_ALLOCATION #endif -#if defined(_LIBCPP_SAFE_STATIC) -#define TEST_SAFE_STATIC _LIBCPP_SAFE_STATIC +#if TEST_STD_VER > 17 +#define TEST_CONSTINIT constinit +#elif defined(_LIBCPP_CONSTINIT) +#define TEST_CONSTINIT _LIBCPP_CONSTINIT #else -#define TEST_SAFE_STATIC +#define TEST_CONSTINIT #endif #if !defined(__cpp_impl_three_way_comparison) \ Index: libcxxabi/src/cxa_default_handlers.cpp =================================================================== --- libcxxabi/src/cxa_default_handlers.cpp +++ libcxxabi/src/cxa_default_handlers.cpp @@ -20,8 +20,7 @@ #if !defined(LIBCXXABI_SILENT_TERMINATE) -_LIBCPP_SAFE_STATIC -static const char* cause = "uncaught"; +static constinit const char* cause = "uncaught"; __attribute__((noreturn)) static void demangling_terminate_handler() @@ -100,13 +99,13 @@ // Global variables that hold the pointers to the current handler // _LIBCXXABI_DATA_VIS -_LIBCPP_SAFE_STATIC std::terminate_handler __cxa_terminate_handler = default_terminate_handler; +constinit std::terminate_handler __cxa_terminate_handler = default_terminate_handler; _LIBCXXABI_DATA_VIS -_LIBCPP_SAFE_STATIC std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler; +constinit std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler; _LIBCXXABI_DATA_VIS -_LIBCPP_SAFE_STATIC std::new_handler __cxa_new_handler = 0; +constinit std::new_handler __cxa_new_handler = nullptr; namespace std { Index: libcxxabi/src/cxa_guard_impl.h =================================================================== --- libcxxabi/src/cxa_guard_impl.h +++ libcxxabi/src/cxa_guard_impl.h @@ -619,7 +619,7 @@ static T instance; }; template -_LIBCPP_SAFE_STATIC T GlobalStatic::instance = {}; +constinit T GlobalStatic::instance = {}; enum class Implementation { NoThreads, GlobalMutex, Futex }; Index: libcxxabi/src/fallback_malloc.cpp =================================================================== --- libcxxabi/src/fallback_malloc.cpp +++ libcxxabi/src/fallback_malloc.cpp @@ -33,10 +33,9 @@ // When POSIX threads are not available, make the mutex operations a nop #ifndef _LIBCXXABI_HAS_NO_THREADS -_LIBCPP_SAFE_STATIC -static std::__libcpp_mutex_t heap_mutex = _LIBCPP_MUTEX_INITIALIZER; +static constinit std::__libcpp_mutex_t heap_mutex = _LIBCPP_MUTEX_INITIALIZER; #else -static void* heap_mutex = 0; +static constinit void* heap_mutex = nullptr; #endif class mutexor { @@ -58,7 +57,7 @@ #endif }; -static const size_t HEAP_SIZE = 512; +static constexpr size_t HEAP_SIZE = 512; char heap[HEAP_SIZE] __attribute__((aligned)); typedef unsigned short heap_offset;