On Thu, 15 Oct 2026 at 11:35, Daniel Krügler <[email protected]> wrote:
>
> Am Do., 15. Okt. 2026 um 11:37 Uhr schrieb Jonathan Wakely
> <[email protected]>:
>>
>> There is very little code that needs to change, just moving some #if
>> checks and moving a couple of declarations outside hosted-only groups.
>> This adds a new __glibcxx_freestanding_chrono feature test macro.
>> If/when WG21 makes <chrono> freestanding we can remove the no_stdname
>> lines in version.def to also defined __cpp_lib_freestanding_chrono.
>>
>> The parts that can't be freestanding are the now() member functions of
>> the clocks, conversions between sys_time and std::time_t, the
>> file_clock, and everything that depends on chrono::tzdb.
>>
>> The conversions to/from std::time_t depend on the type defined in
>> <time.h>, which is not freestanding. It would be possible to do
>> something like this in chrono::system_clock:
>>
>> #if _GLIBCXX_HOSTED
>> using _Sys_clock_time_t = std::time_t;
>> #else
>> using _Sys_clock_time_t = long long;
>> #endif
>>
>> and then define the member functions in terms of that type. That is not
>> done in this change but could be considered in future.
>>
>> Accessing leap second info is supported for freestanding, and therefore
>> so are conversions between utc_time and sys_time. The list of leap
>> seconds is fixed to the hardcoded list in the <chrono> header, so
>> reading an up-to-date list from tzdb is not possible in freestanding.
>>
>> The chrono::zoned_traits and chrono::zoned_time class templates are
>> freestanding, but the chrono::zoned_traits<const time_zone*> partial
>> specialization is not. The default template argument for
>> chrono::zoned_time (which is const time_zone* for hosted) is not present
>> for freestanding, neither are the deduction guides for zoned_time. The
>> zoned_time::get_info member returns sys_info which contains std::string,
>> so that can't be freestanding. The rest of zoned_time can be though.
>> This provides enough functionality for custom time zones to be provided
>> in a freestanding program.
>>
>> The last two `#if _GLIBCXX_HOSTED` checks removed from <chrono> by this
>> commit were redundant, because they surround a check for
>> `__cpp_lib_chrono >= 201803L` which is only true for hosted anyway.
>> Removing those checks is not making chrono::tzdb, chrono::time_zone etc.
>> available for freestanding, just removing the redundancy.
>>
>> libstdc++-v3/ChangeLog:
>>
>> * include/bits/chrono.h (floor, ceil, round): Change
>> preprocessor condition to __glibcxx_freestanding_chrono.
>> [!_GLIBCXX_HOSTED] (system_clock, steady_clock): Define.
>> [!_GLIBCXX_HOSTED] (__sys_t): Remove.
>> [!_GLIBCXX_HOSTED] (sys_time, sys_seconds, sys_days): Remove
>> freestanding definitions.
>> * include/bits/version.def (freestanding_chrono): Define
>> non-standard macro.
>> * include/bits/version.h: Regenerate.
>> * include/std/chrono [!_GLIBCXX_HOSTED] (utc_clock, tai_clock)
>> (gps_clock): Define.
>> (clock_time_conversion, clock_cast) [!__STDC_HOSTED__]: Define
>> the same as for hosted.
>> * testsuite/20_util/system_clock/1.cc [!__STDC_HOSTED__]: Do not
>> test now, to_time_t and from_time_t for freestanding.
>> * testsuite/20_util/system_clock/99832.cc: Require hosted
>> effective target.
>> * testsuite/20_util/time_point/comparison_operators/three_way.cc
>> [!__cpp_lib_hosted]: Do not use system_clock::now() for
>> freestanding.
>> * testsuite/std/time/clock/file/members.cc: Require hosted
>> effective target.
>> * testsuite/std/time/clock/file/overview.cc [!__STDC_HOSTED__]:
>> Do not test now() for freestanding.
>> * testsuite/std/time/clock/gps/1.cc: Likewise.
>> * testsuite/std/time/clock/tai/1.cc: Likewise.
>> * testsuite/std/time/format/data_not_present_neg.cc: Require
>> hosted effective target.
>> * testsuite/std/time/format/pr120114.cc: Likewise.
>> * testsuite/std/time/format/pr120481.cc: Likewise.
>> * testsuite/std/time/format/precision.cc: Likewise.
>> * testsuite/std/time/format/whitespace.cc: Likewise.
>> * testsuite/std/time/syn_c++20.cc [!__STDC_HOSTED__]: Do not
>> test some components for freestanding.
>> * testsuite/std/time/time_zone/requirements.cc: Require hosted
>> effective target.
>> * testsuite/std/time/traits/is_clock.cc [!__STDC_HOSTED__]: Do
>> not test standard clocks for freestanding.
>> * testsuite/std/time/zoned_time/custom.cc: Refactor to support
>> freestanding and old ABI. Do not require tzdb effective target.
>> * testsuite/std/time/zoned_time/req_neg.cc: Likewise.
>> * testsuite/util/slow_clock.h [!_GLIBCXX_HOSTED]: Do not define
>> slow_clock::now() function for freestanding.
>> ---
>>
> [..]
>
>>
>>
>> +#if _GLIBCXX_HOSTED
>> static time_point
>> now() noexcept;
>>
>> @@ -1268,6 +1264,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>> return time_point_cast<system_clock::duration>
>> (__from(chrono::seconds(__t)));
>> }
>> +#endif
>
>
> I'm wondering whether for freestanding now() should be "freestanding-deleted"?
Does it make any practical difference?
I suppose it would be observable like this:
struct my_clock : std::chrono::system_clock
{
using system_clock::now;
};
If the function just doesn't exist, that would be ill-formed. If it's
defined as deleted, that would be OK.
I doubt it will matter to any real code, but it's fairly easy to make
that change and add a test like the struct above.
>
>
>>
>> @@ -1286,8 +1283,10 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>>
>> static constexpr bool is_steady = true;
>>
>> +#if _GLIBCXX_HOSTED
>> static time_point
>> now() noexcept;
>> +#endif
>
>
> Dito here.
>
> Thanks,
>
> - Daniel