[PATCH] libstdc++: Export explicit instantiations of __format::__do_vformat_to.
Tomasz Kamiński
tkaminsk@redhat.com
Fri Apr 3 11:39:20 GMT 2026
This patch exports instantiations of __format::__do_vformat_to
for _Sink_iter and char/wchar_t. As every format function is
implementing as delegating the one of these overloads, this
significantly reduces the compliation time.
Instantiating __format::__do_vformat_to triggers specializations
of formatters for types stored in handle direclty (arithmetic
types, strings), however we do not export any of their symbols.
This keeps the interface boundary minimal. This file should
be recompiled in later mode, when it is called stable.
libstdc++-v3/ChangeLog:
* config/abi/pre/gnu.ver (GLIBCXX_3.4): Exclude exports
of std::basic_fo* (matching basic_format_context).
(GLIBCXX_3.4.35): Export __format::__do_vformat_to
specializations for _Sink_iter and char/wchar_t.
* include/std/format: (__format::__do_vformat_to):
Remove inline and declare extern instantiation
of __format::__do_vformat_to _Sink_iter and char/wchar_t.
* src/c++20/Makefile.am: Add format-inst.cc.
* src/c++20/Makefile.in: Regenerate.
* src/c++20/format-inst.cc: New file defining explicit
instantiation.
---
>From simple test on files from testsuite/std/format/functions/, the
results looks very promising:
Before After
format.cc 24.203s 10.846s
format_to.cc 18.475s 2.844s
format_to_n.cc 18.677s 3.074s
vformat_to.cc 17.281s 2.246s
However, I am a bit concerned if the approach works, as
libstdc++.so will always contains weak simbol for __do_vformat_to
for _Sink_iter<char>, that supports only C++20 specifiers.
Should we instead compile the format-inst in latest mode, and
always provide extern defintion?
Note that the same problem will also be present for the print function,
but I haven not realized it then.
I plan to do similar change for __formatter_chrono<char>::_M_format
functions (entry point).
libstdc++-v3/config/abi/pre/gnu.ver | 8 ++++-
libstdc++-v3/include/std/format | 13 +++++++-
libstdc++-v3/src/c++20/Makefile.am | 3 +-
libstdc++-v3/src/c++20/Makefile.in | 6 ++--
libstdc++-v3/src/c++20/format-inst.cc | 46 +++++++++++++++++++++++++++
5 files changed, 71 insertions(+), 5 deletions(-)
create mode 100644 libstdc++-v3/src/c++20/format-inst.cc
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index fb968e122d8..2b391584c94 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -34,7 +34,9 @@ GLIBCXX_3.4 {
std::basic_[a-e]*;
std::basic_f[a-h]*;
# std::basic_filebuf;
- std::basic_f[j-r]*;
+ std::basic_f[j-n]*;
+# std::basic_format_context;
+ std::basic_f[p-r]*;
# std::basic_fstream;
std::basic_f[t-z]*;
std::basic_[g-h]*;
@@ -2587,6 +2589,10 @@ GLIBCXX_3.4.35 {
_ZNSt12__cow_stringaSEOS_;
_ZNKSt12__cow_string5c_strEv;
+ # __format::__do_vformat_to(_Sink_iter<char>, string_view, const format_args&, const locale*);
+ # __format::__do_vformat_to(_Sink_iter<wchar_t>, wstring_view, const wformat_args&, const locale*);
+ _ZNSt8__format15__do_vformat_toINS_10_Sink_iterI[wc]EE[wc]St20basic_format_contextIS2_[wc]EEET_S5_St17basic_string_viewIT0_St11char_traitsIS7_EERKSt17basic_format_argsIT1_EPKSt6locale;
+
#if defined (_WIN32) && !defined (__CYGWIN__)
_ZSt19__get_once_callablev;
_ZSt15__get_once_callv;
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index eca5bd213aa..2a8229a2eb5 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -5220,7 +5220,7 @@ namespace __format
};
template<typename _Out, typename _CharT, typename _Context>
- inline _Out
+ _Out
__do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
const basic_format_args<_Context>& __args,
const locale* __loc)
@@ -5310,6 +5310,17 @@ namespace __format
}
}
+#if __cplusplus <= 202002L && _GLIBCXX_EXTERN_TEMPLATE > 0
+ extern template _Sink_iter<char>
+ __do_vformat_to(_Sink_iter<char>, string_view,
+ const format_args&, const locale*);
+# ifdef _GLIBCXX_USE_WCHAR_T
+ extern template _Sink_iter<wchar_t>
+ __do_vformat_to(_Sink_iter<wchar_t>, wstring_view,
+ const wformat_args&, const locale*);
+# endif
+#endif
+
template<typename _Out, typename _CharT>
format_to_n_result<_Out>
__do_vformat_to_n(_Out __out, iter_difference_t<_Out> __n,
diff --git a/libstdc++-v3/src/c++20/Makefile.am b/libstdc++-v3/src/c++20/Makefile.am
index 0061678dc0f..7744fa43a63 100644
--- a/libstdc++-v3/src/c++20/Makefile.am
+++ b/libstdc++-v3/src/c++20/Makefile.am
@@ -30,7 +30,8 @@ headers =
if ENABLE_EXTERN_TEMPLATE
# XTEMPLATE_FLAGS = -fno-implicit-templates
inst_sources = \
- sstream-inst.cc
+ sstream-inst.cc \
+ format-inst.cc
else
# XTEMPLATE_FLAGS =
inst_sources =
diff --git a/libstdc++-v3/src/c++20/Makefile.in b/libstdc++-v3/src/c++20/Makefile.in
index f481ad08edb..566d7292021 100644
--- a/libstdc++-v3/src/c++20/Makefile.in
+++ b/libstdc++-v3/src/c++20/Makefile.in
@@ -124,7 +124,8 @@ CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libc__20convenience_la_LIBADD =
am__objects_1 = tzdb.lo format.lo atomic.lo clock.lo syncbuf.lo
-@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_2 = sstream-inst.lo
+@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_2 = sstream-inst.lo \
+@ENABLE_EXTERN_TEMPLATE_TRUE@ format-inst.lo
@GLIBCXX_HOSTED_TRUE@am_libc__20convenience_la_OBJECTS = \
@GLIBCXX_HOSTED_TRUE@ $(am__objects_1) $(am__objects_2)
libc__20convenience_la_OBJECTS = $(am_libc__20convenience_la_OBJECTS)
@@ -433,7 +434,8 @@ headers =
# XTEMPLATE_FLAGS = -fno-implicit-templates
@ENABLE_EXTERN_TEMPLATE_TRUE@inst_sources = \
-@ENABLE_EXTERN_TEMPLATE_TRUE@ sstream-inst.cc
+@ENABLE_EXTERN_TEMPLATE_TRUE@ sstream-inst.cc \
+@ENABLE_EXTERN_TEMPLATE_TRUE@ format-inst.cc
sources = tzdb.cc format.cc atomic.cc clock.cc syncbuf.cc
@GLIBCXX_HOSTED_FALSE@libc__20convenience_la_SOURCES =
diff --git a/libstdc++-v3/src/c++20/format-inst.cc b/libstdc++-v3/src/c++20/format-inst.cc
new file mode 100644
index 00000000000..1904de35f7b
--- /dev/null
+++ b/libstdc++-v3/src/c++20/format-inst.cc
@@ -0,0 +1,46 @@
+// Definitions for <chrono> formatting -*- 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, 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.
+
+// 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 <format>
+#include <chrono>
+
+namespace std
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __format
+{
+
+ template _Sink_iter<char>
+ __do_vformat_to(_Sink_iter<char>, string_view,
+ const format_args&, const locale*);
+
+# ifdef _GLIBCXX_USE_WCHAR_T
+ template _Sink_iter<wchar_t>
+ __do_vformat_to(_Sink_iter<wchar_t>, wstring_view,
+ const wformat_args&, const locale*);
+# endif
+
+} // namespace __format
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
--
2.53.0
More information about the Libstdc++
mailing list