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()
+{
+}

Reply via email to