[PATCH] libstdc++: Export explicit instantiations of __format::__do_vformat_to.
Tomasz Kaminski
tkaminsk@redhat.com
Fri Apr 3 17:25:02 GMT 2026
On Fri, Apr 3, 2026 at 6:44 PM Tomasz Kaminski <tkaminsk@redhat.com> wrote:
>
>
> 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.
>
This problem also exists for C++20 chrono, where we transcode output for
localized formatting.
>
>
>
>> 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/8f09a699/attachment.htm>
More information about the Libstdc++
mailing list