[PATCH] libstdc++: Export explicit instantiations of __format::__do_vformat_to.

Tomasz Kaminski tkaminsk@redhat.com
Fri Apr 3 16:44:10 GMT 2026


On Fri, Apr 3, 2026 at 6:25 PM Jonathan Wakely <jwakely.gcc@gmail.com>
wrote:

>
>
> On Fri, 3 Apr 2026, 16:31 Tomasz Kaminski, <tkaminsk@redhat.com> wrote:
>
>>
>>
>> On Fri, Apr 3, 2026 at 5:21 PM Jonathan Wakely <jwakely.gcc@gmail.com>
>> wrote:
>>
>>>
>>>
>>> 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.
>>>
>> You can observe this by calling vformat_to, and we have a test checking
>> if vformat_to("{:?}", string) works or not,
>> so we will end up in unfortunae situation when ? is supported for dynamic
>> formatting, but not for static one.
>>
>> I am experimenting with adding _M_ftm member to basic_format_context and
>> basic_format_parse_context,
>> and using it to decide if given format specifier should be rejected.
>>
>
> The explicit instantiation is only declared for C++20:
>
> +#if __cplusplus <= 202002L
>
> (That should be just == not <= since format was new in C++20)
>
> So if the instantiation only knows about C++20 specifiers that's ok, it
> won't be used by C++23 and C++26 code.
>
Yes, I have discussed that with Jason and he confirmed that this is indeed
the case, i.e. the weak symbol from
.so will not be picked over program defined one for C++23 (for this version
we do not provide explicit specialization).

But then if you mix program using TUs compiled with differnt TUs, you will
get only one behavior currently.
The same applies to __formatter_int specializations, one parse/format
method is selected for whole program, and they
may not match - i.e. parse may allow more than format can handle.

My ftm based solution works (requires additional field inside the
basic_format_parse_context), however now I have noticed
that for the debug format, we need to select how to treat encoding type as
runtime, as libstdc++.so may be compiled with
different literal encoding than program is, and thus require string to be
encoded differently. I think resonable solution
here would be to put literal for char encoding indicator inside format
context, and we have last chance to do it.



>  We can figure out how to export different versions at a future date
> (maybe using an abi_tag attribute to distinguish the instantiations).
>
Jason suggested adding a non-type template argument defaulted to feature
test macro (I would preffer to use __cplusplus version).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260403/175755d5/attachment-0001.htm>


More information about the Libstdc++ mailing list