[libcxx-commits] [libcxx] [libc++] Work around benign initialization order fiasco in locale (PR #73533)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Nov 27 08:04:15 PST 2023
https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/73533
Technically, it is possible for the ios initializers to run before the initializer of classic_locale_imp_, which would cause `.emplace` to be called on a not-yet-initialized __no_destroy variable.
This patch fixes that by making the variable trivially constinit, since we're not doing anything in its constructor anyway.
>From 8484ff20ad032812ffbc46bfe6d769ddba0a5acf Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 27 Nov 2023 11:01:35 -0500
Subject: [PATCH] [libc++] Work around benign initialization order fiasco in
locale
Technically, it is possible for the ios initializers to run before
the initializer of classic_locale_imp_, which would cause `.emplace`
to be called on a not-yet-initialized __no_destroy variable.
This patch fixes that by making the variable trivially constinit,
since we're not doing anything in its constructor anyway.
---
libcxx/include/__utility/no_destroy.h | 13 +++++++------
libcxx/src/locale.cpp | 2 +-
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/libcxx/include/__utility/no_destroy.h b/libcxx/include/__utility/no_destroy.h
index c8581cf9606b571..fc936d2d287316a 100644
--- a/libcxx/include/__utility/no_destroy.h
+++ b/libcxx/include/__utility/no_destroy.h
@@ -28,22 +28,23 @@ struct __uninitialized_tag {};
// initialization using __emplace.
template <class _Tp>
struct __no_destroy {
- _LIBCPP_HIDE_FROM_ABI explicit __no_destroy(__uninitialized_tag) {}
- _LIBCPP_HIDE_FROM_ABI ~__no_destroy() {
+ _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI explicit __no_destroy(__uninitialized_tag) {}
+ _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI ~__no_destroy() {
// nothing
}
template <class... _Args>
- _LIBCPP_HIDE_FROM_ABI explicit __no_destroy(_Args&&... __args) : __obj_(std::forward<_Args>(__args)...) {}
+ _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI explicit __no_destroy(_Args&&... __args)
+ : __obj_(std::forward<_Args>(__args)...) {}
template <class... _Args>
- _LIBCPP_HIDE_FROM_ABI _Tp& __emplace(_Args&&... __args) {
+ _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _Tp& __emplace(_Args&&... __args) {
new (&__obj_) _Tp(std::forward<_Args>(__args)...);
return __obj_;
}
- _LIBCPP_HIDE_FROM_ABI _Tp& __get() { return __obj_; }
- _LIBCPP_HIDE_FROM_ABI _Tp const& __get() const { return __obj_; }
+ _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _Tp& __get() { return __obj_; }
+ _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _Tp const& __get() const { return __obj_; }
private:
union {
diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp
index 2cb75f81b36da33..d6ba490a00a1109 100644
--- a/libcxx/src/locale.cpp
+++ b/libcxx/src/locale.cpp
@@ -546,7 +546,7 @@ locale::__imp::use_facet(long id) const
// expensive in parallel applications. The classic locale is used by default
// in all streams. Note: if a new global locale is installed, then we lose
// the benefit of no reference counting.
-__no_destroy<locale::__imp> locale::__imp::classic_locale_imp_(__uninitialized_tag{}); // initialized below in classic()
+constinit __no_destroy<locale::__imp> locale::__imp::classic_locale_imp_(__uninitialized_tag{}); // initialized below in classic()
const locale& locale::classic() {
static const __no_destroy<locale> classic_locale(__private_tag{}, [] {
More information about the libcxx-commits
mailing list