[PATCH] libstdc++: Export explicit instantiations of __format::__do_vformat_to.
Jonathan Wakely
jwakely.gcc@gmail.com
Fri Apr 3 15:20:53 GMT 2026
On Fri, 3 Apr 2026, 12:50 Tomasz Kaminski, <tkaminsk@redhat.com> wrote:
>
>
> On Fri, Apr 3, 2026 at 1:48 PM Tomasz Kamiński <tkaminsk@redhat.com>
> wrote:
>
>> 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.
>>
> The scenarios like that are not only teoreticall, debug support (?) for
> string and char was recently added.
>
Yes, I think we should instantiate the latest definition.
Before C++26 there's no way to use those new format specifiers anyway,
because the format string is always parsed as a consteval format_string and
so only C++20 or C++23 formats will be recognized.
>> 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
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260403/859e6967/attachment.htm>
More information about the Libstdc++
mailing list