[committed] libstdc++: Add Filesystem TS and std::stacktrace symbols to libstdc++exp.a

Jonathan Wakely jwakely@redhat.com
Fri Sep 8 17:06:57 GMT 2023


This consolidates the three static archives for extensions into one, so
that -lstdc++exp can be used to provide the definitions of all unstable
library features.

The libstdc++_libbacktrace.a archive is now just a "noinst" convenience
library that is only used during the build, not installed. Its contents
are added to libstdc++exp.a, along with the new non-inline definitions
of std::stacktrace symbols.

The libstdc++fs.a archive is still installed, but its contents are
duplicated in libstdc++exp.a now. This means -lstdc++exp can be used
instead of -lstdc++fs. For targets using the GNU linker we should
consider replacing libstdc++fs.a with a linker script that does
INPUT(libstdc++exp.a).

The tests for <experimental/filesystem> could be changed to use
-lstdc++exp instead of -lstdc++fs, which would allow removing
src/filesystem/.libs from the LDFLAGS in scripts/testsuite_flags.in,
but that can be done at a later date.

libstdc++-v3/ChangeLog:

	* acinclude.m4 (GLIBCXX_CONFIGURE): Add c++23 directory.
	* configure: Regenerate.
	* doc/html/manual/*: Regenerate.
	* doc/xml/manual/using.xml: Update documentation on linking.
	* include/std/stacktrace: Remove declarations of libbacktrace
	APIs.
	(stacktrace_entry::_S_err_handler, stacktrace_entry::_S_init):
	Remove.
	(stacktrace_entry::_Info): New class.
	(stacktrace_entry::_M_get_info): Use _Info.
	(__stacktrace_impl): New class.
	(basic_stacktrace): Derive from __stacktrace_impl.
	(basic_stacktrace::current): Use __stacktrace_impl::_S_current.
	* scripts/testsuite_flags.in: Adjust LDFLAGS to find
	libstdc++exp instead of libstdc++_libbacktrace.
	* src/Makefile.am (SUBDIRS): Add c++23 directory.
	* src/Makefile.in: Regenerate.
	* src/c++20/Makefile.am: Fix comment.
	* src/c++20/Makefile.in: Regenerate.
	* src/c++23/Makefile.am: New file.
	* src/c++23/Makefile.in: New file.
	* src/c++23/stacktrace.cc: New file with definitions of
	stacktrace_entry::_Info and __stacktrace_impl members.
	* src/experimental/Makefile.am: Use LIBADD to include other
	libraries.
	* src/experimental/Makefile.in: Regenerate.
	* src/libbacktrace/Makefile.am: Use noinst_LTLIBRARIES.
	* src/libbacktrace/Makefile.in: Regenerate.
	* testsuite/19_diagnostics/stacktrace/current.cc: Adjust
	dg-options to use -lstdc++exp.
	* testsuite/19_diagnostics/stacktrace/entry.cc: Likewise.
	* testsuite/19_diagnostics/stacktrace/stacktrace.cc: Likewise.
	* testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc:
	Likewise.
---
 libstdc++-v3/acinclude.m4                     |   2 +-
 libstdc++-v3/configure                        |  16 +-
 libstdc++-v3/doc/html/manual/using.html       |  26 +-
 .../html/manual/using_dynamic_or_shared.html  |   4 +
 libstdc++-v3/doc/xml/manual/using.xml         |  37 +-
 libstdc++-v3/include/std/stacktrace           | 144 +---
 libstdc++-v3/scripts/testsuite_flags.in       |   8 +-
 libstdc++-v3/src/Makefile.am                  |   4 +-
 libstdc++-v3/src/Makefile.in                  |   7 +-
 libstdc++-v3/src/c++20/Makefile.am            |   2 +-
 libstdc++-v3/src/c++20/Makefile.in            |   2 +-
 libstdc++-v3/src/c++23/Makefile.am            | 109 +++
 libstdc++-v3/src/c++23/Makefile.in            | 747 ++++++++++++++++++
 libstdc++-v3/src/c++23/stacktrace.cc          | 171 ++++
 libstdc++-v3/src/experimental/Makefile.am     |  20 +
 libstdc++-v3/src/experimental/Makefile.in     |  15 +-
 libstdc++-v3/src/libbacktrace/Makefile.am     |   3 +-
 libstdc++-v3/src/libbacktrace/Makefile.in     |  88 +--
 .../19_diagnostics/stacktrace/current.cc      |   2 +-
 .../19_diagnostics/stacktrace/entry.cc        |   2 +-
 .../19_diagnostics/stacktrace/stacktrace.cc   |   2 +-
 .../vector/debug/assign4_backtrace_neg.cc     |   2 +-
 22 files changed, 1185 insertions(+), 228 deletions(-)
 create mode 100644 libstdc++-v3/src/c++23/Makefile.am
 create mode 100644 libstdc++-v3/src/c++23/Makefile.in
 create mode 100644 libstdc++-v3/src/c++23/stacktrace.cc

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index fcf79503265..34faa3c049f 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -49,7 +49,7 @@ AC_DEFUN([GLIBCXX_CONFIGURE], [
   # Keep these sync'd with the list in Makefile.am.  The first provides an
   # expandable list at autoconf time; the second provides an expandable list
   # (i.e., shell variable) at configure time.
-  m4_define([glibcxx_SUBDIRS],[include libsupc++ src src/c++98 src/c++11 src/c++17 src/c++20 src/filesystem src/libbacktrace src/experimental doc po testsuite python])
+  m4_define([glibcxx_SUBDIRS],[include libsupc++ src src/c++98 src/c++11 src/c++17 src/c++20 src/c++23 src/filesystem src/libbacktrace src/experimental doc po testsuite python])
   SUBDIRS='glibcxx_SUBDIRS'
 
   # These need to be absolute paths, yet at the same time need to
diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml
index 3a507fc1671..7276cad0feb 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -100,30 +100,27 @@
       </entry>
     </row>
 
-    <row>
-      <entry><literal>-lstdc++fs</literal></entry>
-      <entry>Linking to <filename class="libraryfile">libstdc++fs</filename>
-        is required for use of the Filesystem library extensions in
-        <filename class="headerfile"><experimental/filesystem></filename>.
-      </entry>
-    </row>
-
     <row>
       <entry><literal>-lstdc++exp</literal></entry>
-      <entry>Linking to <filename class="libraryfile">libstdc++exp</filename>
-        is required for use of the C++ Contracts extensions enabled by
-        <literal>-fcontracts</literal>.
+      <entry>Linking to <filename class="libraryfile">libstdc++exp.a</filename>
+        is required for use of experimental C++ library features.
+        This currently provides support for the C++23 types defined in the
+        <filename class="headerfile"><stacktrace></filename> header,
+        the Filesystem library extensions defined in the
+        <filename class="headerfile"><experimental/filesystem></filename>
+        header,
+        and the Contracts extensions enabled by <literal>-fcontracts</literal>.
       </entry>
     </row>
 
     <row>
-      <entry><literal>-lstdc++_libbacktrace</literal></entry>
-      <entry>Until C++23 support is non-experimental, linking to
-	<filename class="libraryfile">libstdc++_libbacktrace.a</filename>
-	is required for use of the C++23 type
-	<classname>std::stacktrace</classname>
-	and related types in
-	<filename class="headerfile"><stacktrace></filename>.
+      <entry><literal>-lstdc++fs</literal></entry>
+      <entry>Linking to <filename class="libraryfile">libstdc++fs.a</filename>
+        is another way to use the Filesystem library extensions defined in the
+        <filename class="headerfile"><experimental/filesystem></filename>
+        header.
+        The <filename class="libraryfile">libstdc++exp.a</filename> library
+        also provides all the symbols contained in this library.
       </entry>
     </row>
 
@@ -1710,6 +1707,10 @@ A quick read of the relevant part of the GCC
       and link with <option>-lstdc++fs</option>. The library implementation
       is incomplete on non-POSIX platforms, specifically Windows is only
       partially supported.
+      Since GCC 14, <filename class="libraryfile">libstdc++exp.a</filename>
+      also contains the definitions for this library,
+      so <option>-lstdc++exp</option> can be used instead of
+      <option>-lstdc++fs</option>.
     </para>
 
     <para>
diff --git a/libstdc++-v3/include/std/stacktrace b/libstdc++-v3/include/std/stacktrace
index 07949e70861..358a81b82e5 100644
--- a/libstdc++-v3/include/std/stacktrace
+++ b/libstdc++-v3/include/std/stacktrace
@@ -45,43 +45,6 @@
 #include <bits/stl_uninitialized.h>
 #include <ext/numeric_traits.h>
 
-struct __glibcxx_backtrace_state;
-struct __glibcxx_backtrace_simple_data;
-
-extern "C"
-{
-__glibcxx_backtrace_state*
-__glibcxx_backtrace_create_state(const char*, int,
-				 void(*)(void*, const char*, int),
-				 void*);
-
-int
-__glibcxx_backtrace_simple(__glibcxx_backtrace_state*, int,
-			   int (*) (void*, __UINTPTR_TYPE__),
-			   void(*)(void*, const char*, int),
-			   void*);
-int
-__glibcxx_backtrace_pcinfo(__glibcxx_backtrace_state*, __UINTPTR_TYPE__,
-			   int (*)(void*, __UINTPTR_TYPE__,
-				   const char*, int, const char*),
-			   void(*)(void*, const char*, int),
-			   void*);
-
-int
-__glibcxx_backtrace_syminfo(__glibcxx_backtrace_state*, __UINTPTR_TYPE__ addr,
-			    void (*) (void*, __UINTPTR_TYPE__, const char*,
-				      __UINTPTR_TYPE__, __UINTPTR_TYPE__),
-			    void(*)(void*, const char*, int),
-			    void*);
-}
-
-namespace __cxxabiv1
-{
-  extern "C" char*
-  __cxa_demangle(const char* __mangled_name, char* __output_buffer,
-		 size_t* __length, int* __status);
-}
-
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -156,80 +119,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     template<typename _Allocator> friend class basic_stacktrace;
 
-    static void _S_err_handler(void*, const char*, int) { }
-
-    static __glibcxx_backtrace_state*
-    _S_init()
-    {
-      static __glibcxx_backtrace_state* __state
-	= __glibcxx_backtrace_create_state(nullptr, 1, _S_err_handler, nullptr);
-      return __state;
-    }
-
     friend ostream&
     operator<<(ostream&, const stacktrace_entry&);
 
+    // Type-erased wrapper for the fields of a stacktrace entry.
+    // This type is independent of which std::string ABI is in use.
+    struct _Info
+    {
+      void* _M_desc;
+      void* _M_file;
+      int* _M_line;
+      void (*_M_set)(void*, const char*);
+
+      _GLIBCXX_DEFAULT_ABI_TAG
+      static void
+      _S_set(void* __dest, const char* __str)
+      { static_cast<string*>(__dest)->assign(__str); }
+
+      _Info(string* __desc, string* __file, int* __line)
+      : _M_desc(__desc), _M_file(__file), _M_line(__line), _M_set(_S_set)
+      { }
+
+      bool
+      _M_populate(native_handle_type);
+
+      void _M_set_file(const char*);
+      void _M_set_desc(const char*);
+    };
+
     bool
     _M_get_info(string* __desc, string* __file, int* __line) const
     {
       if (!*this)
 	return false;
-
-      struct _Data
-      {
-	string* _M_desc;
-	string* _M_file;
-	int* _M_line;
-      } __data = { __desc, __file, __line };
-
-      auto __cb = [](void* __data, uintptr_t, const char* __filename,
-		     int __lineno, const char* __function) -> int {
-	  auto& __d = *static_cast<_Data*>(__data);
-	  if (__function && __d._M_desc)
-	    *__d._M_desc = _S_demangle(__function);
-	  if (__filename && __d._M_file)
-	    *__d._M_file = __filename;
-	  if (__d._M_line)
-	    *__d._M_line = __lineno;
-	  return __function != nullptr;
-      };
-      const auto __state = _S_init();
-      if (::__glibcxx_backtrace_pcinfo(__state, _M_pc, +__cb, _S_err_handler,
-				       &__data))
-	return true;
-      if (__desc && __desc->empty())
-	{
-	  auto __cb2 = [](void* __data, uintptr_t, const char* __symname,
-	      uintptr_t, uintptr_t) {
-	      if (__symname)
-		*static_cast<_Data*>(__data)->_M_desc = _S_demangle(__symname);
-	  };
-	  if (::__glibcxx_backtrace_syminfo(__state, _M_pc, +__cb2,
-					    _S_err_handler, &__data))
-	    return true;
-	}
-      return false;
+      return _Info(__desc, __file, __line)._M_populate(_M_pc);
     }
+  };
 
-    static string
-    _S_demangle(const char* __name)
-    {
-      string __s;
-      int __status;
-      char* __str = __cxxabiv1::__cxa_demangle(__name, nullptr, nullptr,
-					       &__status);
-      if (__status == 0)
-	__s = __str;
-      else
-	__s = __name;
-      __builtin_free(__str);
-      return __s;
-    }
+  class __stacktrace_impl
+  {
+  protected:
+    static int _S_current(int (*) (void*, __UINTPTR_TYPE__), void*, int = 0);
   };
 
   // [stacktrace.basic], class template basic_stacktrace
   template<typename _Allocator>
     class basic_stacktrace
+    : private __stacktrace_impl
     {
       using _AllocTraits = allocator_traits<_Allocator>;
       using uintptr_t = __UINTPTR_TYPE__;
@@ -256,10 +192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	basic_stacktrace __ret(__alloc);
 	if (auto __cb = __ret._M_prepare()) [[likely]]
 	  {
-	    auto __state = stacktrace_entry::_S_init();
-	    if (__glibcxx_backtrace_simple(__state, 1, __cb,
-					   stacktrace_entry::_S_err_handler,
-					   std::__addressof(__ret)))
+	    if (_S_current(__cb, std::__addressof(__ret)))
 	      __ret._M_clear();
 	  }
 	return __ret;
@@ -275,10 +208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  return __ret;
 	if (auto __cb = __ret._M_prepare()) [[likely]]
 	  {
-	    auto __state = stacktrace_entry::_S_init();
-	    if (__glibcxx_backtrace_simple(__state, __skip + 1, __cb,
-					   stacktrace_entry::_S_err_handler,
-					   std::__addressof(__ret)))
+	    if (_S_current(__cb, std::__addressof(__ret), __skip))
 	      __ret._M_clear();
 	  }
 
@@ -299,11 +229,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  return __ret;
 	if (auto __cb = __ret._M_prepare(__max_depth)) [[likely]]
 	  {
-	    auto __state = stacktrace_entry::_S_init();
-	    int __err = __glibcxx_backtrace_simple(__state, __skip + 1, __cb,
-						   stacktrace_entry::_S_err_handler,
-						   std::__addressof(__ret));
-	    if (__err < 0)
+	    if (_S_current(__cb, std::__addressof(__ret), __skip) < 0)
 	      __ret._M_clear();
 	    else if (__ret.size() > __max_depth)
 	      {
diff --git a/libstdc++-v3/scripts/testsuite_flags.in b/libstdc++-v3/scripts/testsuite_flags.in
index 18748f0f9ce..8bf4918287a 100755
--- a/libstdc++-v3/scripts/testsuite_flags.in
+++ b/libstdc++-v3/scripts/testsuite_flags.in
@@ -78,14 +78,14 @@ case ${query} in
       ;;
     --cxxldflags)
       FS_LDFLAGS=
-      BT_LDFLAGS=
+      EXP_LDFLAGS=
       if [ -d ${BUILD_DIR}/src/filesystem/.libs ]; then
         FS_LDFLAGS=-L${BUILD_DIR}/src/filesystem/.libs
       fi
-      if [ -d ${BUILD_DIR}/src/libbacktrace/.libs ]; then
-        BT_LDFLAGS=-L${BUILD_DIR}/src/libbacktrace/.libs
+      if [ -d ${BUILD_DIR}/src/experimental/.libs ]; then
+        EXP_LDFLAGS=-L${BUILD_DIR}/src/experimental/.libs
       fi
-      SECTIONLDFLAGS="@SECTION_LDFLAGS@ @LIBICONV@ $FS_LDFLAGS $BT_LDFLAGS"
+      SECTIONLDFLAGS="@SECTION_LDFLAGS@ @LIBICONV@ $FS_LDFLAGS $EXP_LDFLAGS"
       echo ${SECTIONLDFLAGS}
       ;;
     *)
diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am
index 5b9af41cdb9..32de5304122 100644
--- a/libstdc++-v3/src/Makefile.am
+++ b/libstdc++-v3/src/Makefile.am
@@ -43,7 +43,8 @@ experimental_dir =
 endif
 
 ## Keep this list sync'd with acinclude.m4:GLIBCXX_CONFIGURE.
-SUBDIRS = c++98 c++11 c++17 c++20 $(filesystem_dir) $(backtrace_dir) $(experimental_dir)
+SUBDIRS = c++98 c++11 c++17 c++20 c++23 \
+	$(filesystem_dir) $(backtrace_dir) $(experimental_dir)
 
 # Cross compiler support.
 if VTV_CYGMIN
@@ -75,6 +76,7 @@ vpath % $(top_srcdir)/src/c++98
 vpath % $(top_srcdir)/src/c++11
 vpath % $(top_srcdir)/src/c++17
 vpath % $(top_srcdir)/src/c++20
+vpath % $(top_srcdir)/src/c++23
 if ENABLE_FILESYSTEM_TS
 vpath % $(top_srcdir)/src/filesystem
 endif
diff --git a/libstdc++-v3/src/c++20/Makefile.am b/libstdc++-v3/src/c++20/Makefile.am
index 0bc8a7b832a..e947855e6ae 100644
--- a/libstdc++-v3/src/c++20/Makefile.am
+++ b/libstdc++-v3/src/c++20/Makefile.am
@@ -22,7 +22,7 @@
 
 include $(top_srcdir)/fragment.am
 
-# Convenience library for C++17 runtime.
+# Convenience library for C++20 runtime.
 noinst_LTLIBRARIES = libc++20convenience.la
 
 headers =
diff --git a/libstdc++-v3/src/c++23/Makefile.am b/libstdc++-v3/src/c++23/Makefile.am
new file mode 100644
index 00000000000..da988c352f8
--- /dev/null
+++ b/libstdc++-v3/src/c++23/Makefile.am
@@ -0,0 +1,109 @@
+## Makefile for the C++23 sources of the GNU C++ Standard library.
+##
+## Copyright (C) 1997-2023 Free Software Foundation, Inc.
+##
+## This file is part of the libstdc++ version 3 distribution.
+## Process this file with automake to produce Makefile.in.
+
+## This file is part of the GNU ISO C++ Library.  This library is free
+## software; you can redistribute it and/or modify it under the
+## terms of the GNU General Public License as published by the
+## Free Software Foundation; either version 3, or (at your option)
+## any later version.
+
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+## You should have received a copy of the GNU General Public License along
+## with this library; see the file COPYING3.  If not see
+## <http://www.gnu.org/licenses/>.
+
+include $(top_srcdir)/fragment.am
+
+# Convenience library for C++23 runtime.
+noinst_LTLIBRARIES = libc++23convenience.la
+
+headers =
+
+if ENABLE_EXTERN_TEMPLATE
+# XTEMPLATE_FLAGS = -fno-implicit-templates
+inst_sources =
+else
+# XTEMPLATE_FLAGS =
+inst_sources =
+endif
+
+sources = stacktrace.cc
+
+vpath % $(top_srcdir)/src/c++23
+
+
+if GLIBCXX_HOSTED
+libc__23convenience_la_SOURCES = $(sources)  $(inst_sources)
+else
+libc__23convenience_la_SOURCES =
+endif
+
+# AM_CXXFLAGS needs to be in each subdirectory so that it can be
+# modified in a per-library or per-sub-library way.  Need to manually
+# set this option because CONFIG_CXXFLAGS has to be after
+# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
+# as the occasion calls for it.
+AM_CXXFLAGS = \
+	-std=gnu++23 \
+	$(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
+	$(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \
+	$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) \
+	-fimplicit-templates
+
+AM_MAKEFLAGS = \
+	"gxx_include_dir=$(gxx_include_dir)"
+
+# Libtool notes
+
+# 1) In general, libtool expects an argument such as `--tag=CXX' when
+# using the C++ compiler, because that will enable the settings
+# detected when C++ support was being configured.  However, when no
+# such flag is given in the command line, libtool attempts to figure
+# it out by matching the compiler name in each configuration section
+# against a prefix of the command line.  The problem is that, if the
+# compiler name and its initial flags stored in the libtool
+# configuration file don't match those in the command line, libtool
+# can't decide which configuration to use, and it gives up.  The
+# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
+# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
+# attempt to infer which configuration to use.
+#
+# The second tag argument, `--tag disable-shared` means that libtool
+# only compiles each source once, for static objects. In actuality,
+# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to
+# the libtool command that is used create the object, which is
+# suitable for shared libraries.  The `--tag disable-shared` must be
+# placed after --tag CXX lest things CXX undo the affect of
+# disable-shared.
+
+# 2) Need to explicitly set LTCXXCOMPILE so that EXTRA_CXX_FLAGS is
+# last. (That way, things like -O2 passed down from the toplevel can
+# be overridden by --enable-debug.)
+LTCXXCOMPILE = \
+	$(LIBTOOL) --tag CXX --tag disable-shared \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CXX) $(TOPLEVEL_INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(EXTRA_CXX_FLAGS)
+
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
+
+# 3) We'd have a problem when building the shared libstdc++ object if
+# the rules automake generates would be used.  We cannot allow g++ to
+# be used since this would add -lstdc++ to the link line which of
+# course is problematic at this point.  So, we get the top-level
+# directory to configure libstdc++-v3 to use gcc as the C++
+# compilation driver.
+CXXLINK = \
+	$(LIBTOOL) --tag CXX --tag disable-shared \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CXX) \
+	$(VTV_CXXLINKFLAGS) \
+	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
diff --git a/libstdc++-v3/src/c++23/stacktrace.cc b/libstdc++-v3/src/c++23/stacktrace.cc
new file mode 100644
index 00000000000..10cfa44e4f5
--- /dev/null
+++ b/libstdc++-v3/src/c++23/stacktrace.cc
@@ -0,0 +1,171 @@
+// Implementation of <stacktrace> -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#include <stacktrace>
+#include <cstdlib>
+
+#ifdef __cpp_lib_stacktrace // C++ >= 23 && hosted && HAVE_STACKTRACE
+struct __glibcxx_backtrace_state;
+
+extern "C"
+{
+__glibcxx_backtrace_state*
+__glibcxx_backtrace_create_state(const char*, int,
+				 void(*)(void*, const char*, int),
+				 void*);
+
+int
+__glibcxx_backtrace_simple(__glibcxx_backtrace_state*, int,
+			   int (*) (void*, __UINTPTR_TYPE__),
+			   void(*)(void*, const char*, int),
+			   void*);
+int
+__glibcxx_backtrace_pcinfo(__glibcxx_backtrace_state*, __UINTPTR_TYPE__,
+			   int (*)(void*, __UINTPTR_TYPE__,
+				   const char*, int, const char*),
+			   void(*)(void*, const char*, int),
+			   void*);
+
+int
+__glibcxx_backtrace_syminfo(__glibcxx_backtrace_state*, __UINTPTR_TYPE__ addr,
+			    void (*) (void*, __UINTPTR_TYPE__, const char*,
+				      __UINTPTR_TYPE__, __UINTPTR_TYPE__),
+			    void(*)(void*, const char*, int),
+			    void*);
+}
+
+namespace __cxxabiv1
+{
+  extern "C" char*
+  __cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length,
+		 int* status);
+}
+
+namespace std
+{
+namespace
+{
+  char*
+  demangle(const char* name)
+  {
+    int status;
+    char* str = __cxxabiv1::__cxa_demangle(name, nullptr, nullptr, &status);
+    if (status == 0)
+      return str;
+    else
+      {
+	std::free(str);
+	return nullptr;
+      }
+  }
+
+  void
+  err_handler(void*, const char*, int)
+  { }
+
+  __glibcxx_backtrace_state*
+  init()
+  {
+#if __GTHREADS && ! defined(__cpp_threadsafe_static_init)
+# warning "std::stacktrace initialization will not be thread-safe"
+#endif
+    static __glibcxx_backtrace_state* state
+      = __glibcxx_backtrace_create_state(nullptr, 1, err_handler, nullptr);
+    return state;
+  }
+}
+
+void
+stacktrace_entry::_Info::_M_set_file(const char* filename)
+{
+  if (filename && _M_file)
+    _M_set(_M_file, filename);
+}
+
+void
+stacktrace_entry::_Info::_M_set_desc(const char* function)
+{
+  if (function && _M_desc)
+    {
+      if (char* s = demangle(function))
+	{
+	  _M_set(_M_desc, s);
+	  std::free(s);
+	}
+      else
+	_M_set(_M_desc, function);
+    }
+}
+
+#pragma GCC diagnostic push
+// The closure types below don't escape so we don't care about their mangling.
+#pragma GCC diagnostic ignored "-Wabi"
+bool
+stacktrace_entry::_Info::_M_populate(native_handle_type pc)
+{
+  auto cb = [](void* self, uintptr_t, const char* filename, int lineno,
+	       const char* function) -> int
+  {
+    auto& info = *static_cast<_Info*>(self);
+    info._M_set_desc(function);
+    info._M_set_file(filename);
+    if (info._M_line)
+      *info._M_line = lineno;
+    return function != nullptr;
+  };
+  const auto state = init();
+  if (::__glibcxx_backtrace_pcinfo(state, pc, +cb, err_handler, this))
+    return true;
+
+  // If we get here then backtrace_pcinfo did not give us a function name.
+  // If the caller wanted a function name, try again using backtrace_syminfo.
+  if (_M_desc)
+    {
+      auto cb2 = [](void* self, uintptr_t, const char* symname,
+		    uintptr_t, uintptr_t)
+      {
+	static_cast<_Info*>(self)->_M_set_desc(symname);
+      };
+      if (::__glibcxx_backtrace_syminfo(state, pc, +cb2, err_handler, this))
+	return true;
+    }
+  return false;
+}
+#pragma GCC diagnostic pop
+
+// Ensure no tail-call optimization, so that this frame isn't reused for the
+// backtrace_simple call, so that the number of frames to skip doesn't vary.
+[[gnu::optimize("no-optimize-sibling-calls")]]
+int
+__stacktrace_impl::_S_current(int (*cb) (void*, __UINTPTR_TYPE__), void* obj,
+			      int skip)
+{
+  const auto state = init();
+  // skip+2 because we don't want this function or its caller to be included.
+  int r = ::__glibcxx_backtrace_simple(state, skip + 2, cb, err_handler, obj);
+  // Could also use this to prevent tail-call optim: __asm ("" : "+g" (r));
+  return r;
+}
+
+}
+#endif
diff --git a/libstdc++-v3/src/experimental/Makefile.am b/libstdc++-v3/src/experimental/Makefile.am
index 3b962e7d804..a61465f4eaf 100644
--- a/libstdc++-v3/src/experimental/Makefile.am
+++ b/libstdc++-v3/src/experimental/Makefile.am
@@ -24,6 +24,18 @@ include $(top_srcdir)/fragment.am
 
 toolexeclib_LTLIBRARIES = libstdc++exp.la
 
+if ENABLE_FILESYSTEM_TS
+filesystem_lib = $(top_builddir)/src/filesystem/libstdc++fs.la
+else
+filesystem_lib =
+endif
+
+if ENABLE_BACKTRACE
+backtrace_lib = $(top_builddir)/src/libbacktrace/libstdc++_libbacktrace.la
+else
+backtrace_lib =
+endif
+
 headers =
 
 sources = \
@@ -33,6 +45,14 @@ sources = \
 
 libstdc__exp_la_SOURCES = $(sources)
 
+libstdc__exp_la_LIBADD = \
+	$(top_builddir)/src/c++23/libc++23convenience.la \
+	$(filesystem_lib) $(backtrace_lib)
+
+libstdc__exp_la_DEPENDENCIES = \
+	$(top_builddir)/src/c++23/libc++23convenience.la \
+	$(filesystem_lib) $(backtrace_lib)
+
 # AM_CXXFLAGS needs to be in each subdirectory so that it can be
 # modified in a per-library or per-sub-library way.  Need to manually
 # set this option because CONFIG_CXXFLAGS has to be after
diff --git a/libstdc++-v3/src/libbacktrace/Makefile.am b/libstdc++-v3/src/libbacktrace/Makefile.am
index 27c1ea570e0..492d3b6e952 100644
--- a/libstdc++-v3/src/libbacktrace/Makefile.am
+++ b/libstdc++-v3/src/libbacktrace/Makefile.am
@@ -31,7 +31,8 @@
 
 include $(top_srcdir)/fragment.am
 
-toolexeclib_LTLIBRARIES = libstdc++_libbacktrace.la
+# Convenience library for C++23 runtime.
+noinst_LTLIBRARIES = libstdc++_libbacktrace.la
 
 ACLOCAL_AMFLAGS = -I ../.. -I ../../config
 
diff --git a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/current.cc b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/current.cc
index 184e23b460e..f6c860fc7a4 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/current.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/current.cc
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++23 -lstdc++_libbacktrace" }
+// { dg-options "-std=gnu++23 -lstdc++exp" }
 // { dg-do run { target c++23 } }
 // { dg-require-effective-target stacktrace }
 
diff --git a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/entry.cc b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/entry.cc
index a222c425b20..f0406953d03 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/entry.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/entry.cc
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++23 -lstdc++_libbacktrace" }
+// { dg-options "-std=gnu++23 -lstdc++exp" }
 // { dg-do run { target c++23 } }
 // { dg-require-effective-target stacktrace }
 
diff --git a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/stacktrace.cc b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/stacktrace.cc
index 8dfdf4739be..0a358b7b8ff 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/stacktrace.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/stacktrace.cc
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++23 -lstdc++_libbacktrace" }
+// { dg-options "-std=gnu++23 -lstdc++exp" }
 // { dg-do run { target c++23 } }
 // { dg-require-effective-target stacktrace }
 
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc
index 520788d5cb7..43a82fb1201 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc
@@ -1,5 +1,5 @@
 // { dg-do run { xfail *-*-* } }
-// { dg-options "-D_GLIBCXX_DEBUG_BACKTRACE -lstdc++_libbacktrace" }
+// { dg-options "-D_GLIBCXX_DEBUG_BACKTRACE -lstdc++exp" }
 // { dg-require-effective-target stacktrace }
 
 #include <debug/vector>
-- 
2.41.0



More information about the Gcc-patches mailing list