https://gcc.gnu.org/g:3a8d05b61a9568d60ee922f899408555470eeff1
commit r14-11367-g3a8d05b61a9568d60ee922f899408555470eeff1 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Feb 12 17:29:59 2025 +0000 libstdc++: Use init_priority attribute for tzdb globals [PR118811] When linking statically to libstdc++.a (or to libstdc++_nonshared.a in the RHEL devtoolset compiler) there's a static initialization order problem where user code might be constructed before the std::chrono::tzdb_list globals, and so might try to use them after they've already been destroyed. Use the init_priority attribute on those globals so that they are initialized early. Since r15-7511-g4e7f74225116e7 we can disable the warnings for using a reserved priority using a diagnostic pragma. However, for the backport to the release branch the warnings can only be suppressed by defining the objects in a system header. Move them to a new file that uses '#pragma GCC system_header' and then include that in tzdb.cc. libstdc++-v3/ChangeLog: PR libstdc++/118811 * src/c++20/tzdb.cc (tzdb_list::_Node): Move definitions of static data members to new header. * src/c++20/tzdb_globals.h: New header. Use init_priority attribute on static data members. * testsuite/std/time/tzdb_list/pr118811.cc: New test. (cherry picked from commit 99f57446e63b8ebeaeeae8dc48981cd5f1dfb831) Diff: --- libstdc++-v3/src/c++20/tzdb.cc | 14 +++--------- libstdc++-v3/src/c++20/tzdb_globals.h | 14 ++++++++++++ .../testsuite/std/time/tzdb_list/pr118811.cc | 25 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc index 7e8cce7ce8cf..3fe426d2800b 100644 --- a/libstdc++-v3/src/c++20/tzdb.cc +++ b/libstdc++-v3/src/c++20/tzdb.cc @@ -133,6 +133,8 @@ namespace std::chrono // of this type gives them access to the private members of time_zone // and tzdb, without needing them declared in the <chrono> header. + // The tzdb_list singleton. This doesn't contain the actual linked list, + // but it has member functions that give access to it. static tzdb_list _S_the_list; #if USE_ATOMIC_SHARED_PTR @@ -177,17 +179,7 @@ namespace std::chrono // Implementation of the private constructor used for the singleton object. constexpr tzdb_list::tzdb_list(nullptr_t) { } - // The tzdb_list singleton. This doesn't contain the actual linked list, - // but it has member functions that give access to it. - constinit tzdb_list tzdb_list::_Node::_S_the_list(nullptr); - - // Shared pointer to the first Node in the list. - constinit tzdb_list::_Node::head_ptr tzdb_list::_Node::_S_head_owner{nullptr}; - -#if USE_ATOMIC_LIST_HEAD - // Lock-free access to the first Node in the list. - constinit atomic<tzdb_list::_Node*> tzdb_list::_Node::_S_head_cache{nullptr}; -#endif +#include "tzdb_globals.h" // The data structures defined in this file (Rule, on_day, at_time etc.) // are used to represent the information parsed from the tzdata.zi file diff --git a/libstdc++-v3/src/c++20/tzdb_globals.h b/libstdc++-v3/src/c++20/tzdb_globals.h new file mode 100644 index 000000000000..94d54dad1401 --- /dev/null +++ b/libstdc++-v3/src/c++20/tzdb_globals.h @@ -0,0 +1,14 @@ +// This is only in a header so we can use the system_header pragma, +// to suppress the warning caused by using a reserved init_priority. +#pragma GCC system_header + +[[gnu::init_priority(98)]] +constinit tzdb_list tzdb_list::_Node::_S_the_list(nullptr); + +[[gnu::init_priority(98)]] +constinit tzdb_list::_Node::head_ptr tzdb_list::_Node::_S_head_owner{nullptr}; + +#if USE_ATOMIC_LIST_HEAD +[[gnu::init_priority(98)]] +constinit atomic<tzdb_list::_Node*> tzdb_list::_Node::_S_head_cache{nullptr}; +#endif diff --git a/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc b/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc new file mode 100644 index 000000000000..3968be3f0eca --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc @@ -0,0 +1,25 @@ +// { dg-do run { target c++20 } } +// { dg-require-effective-target tzdb } +// { dg-require-effective-target cxx11_abi } +// { dg-require-static-libstdcxx } +// { dg-additional-options "-static-libstdc++" } + +#include <chrono> + +struct Global +{ + Global() + { + (void) std::chrono::current_zone(); // initialize tzdb on first use + } + + ~Global() + { + (void) std::chrono::current_zone(); // attempt to use it again on exit + } + +} global; + +int main() +{ +}