On Mon, Oct 26, 2026 at 11:25 AM Tomasz Kaminski <[email protected]> wrote:
> > > On Thu, Oct 15, 2026 at 11:37 AM Jonathan Wakely <[email protected]> > wrote: > >> 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. >> --- >> >> Tested x86_64-linux, using all my usual RUNTESTFLAGS but also tested the >> <chrono> parts of the testsuite with -ffreestanding. >> >> Also tested with the "only-old-abi" config that I was working on >> recently, so the combination of no-SSO-string and freestanding also >> works. >> >> libstdc++-v3/include/bits/chrono.h | 35 +++---- >> libstdc++-v3/include/bits/version.def | 25 ++++- >> libstdc++-v3/include/bits/version.h | 17 ++++ >> libstdc++-v3/include/std/chrono | 46 ++++----- >> .../testsuite/20_util/system_clock/1.cc | 10 +- >> .../testsuite/20_util/system_clock/99832.cc | 1 + >> .../comparison_operators/three_way.cc | 4 + >> .../testsuite/std/time/clock/file/members.cc | 1 + >> .../testsuite/std/time/clock/file/overview.cc | 1 + >> .../testsuite/std/time/clock/gps/1.cc | 2 + >> .../testsuite/std/time/clock/tai/1.cc | 2 + >> .../std/time/format/data_not_present_neg.cc | 1 + >> .../testsuite/std/time/format/pr120114.cc | 1 + >> .../testsuite/std/time/format/pr120481.cc | 1 + >> .../testsuite/std/time/format/precision.cc | 1 + >> .../testsuite/std/time/format/whitespace.cc | 1 + >> libstdc++-v3/testsuite/std/time/syn_c++20.cc | 21 +++- >> .../std/time/time_zone/requirements.cc | 2 +- >> .../testsuite/std/time/traits/is_clock.cc | 2 + >> .../testsuite/std/time/zoned_time/custom.cc | 96 +++++++++++++------ >> .../testsuite/std/time/zoned_time/req_neg.cc | 5 +- >> libstdc++-v3/testsuite/util/slow_clock.h | 14 ++- >> 22 files changed, 200 insertions(+), 89 deletions(-) >> >> diff --git a/libstdc++-v3/include/bits/chrono.h >> b/libstdc++-v3/include/bits/chrono.h >> index a71d1435f2f6..0a6be709b76d 100644 >> --- a/libstdc++-v3/include/bits/chrono.h >> +++ b/libstdc++-v3/include/bits/chrono.h >> @@ -376,9 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> { }; >> #endif // C++20 >> >> - // This should use __glibcxx_chrono >= 201611L but that implies >> HOSTED >> - // and we want these functions to be freestanding. >> -#if __cplusplus >= 201703L // C++ >= 17 >> +#if __glibcxx_freestanding_chrono >= 201611L // C++ >= 17 >> /** Convert a `duration` to type `ToDur` and round down. >> * >> * If the duration cannot be represented exactly in the result type, >> @@ -1032,9 +1030,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> return >> __time_point(duration_cast<_ToDur>(__t.time_since_epoch())); >> } >> >> - // This should use __glibcxx_chrono >= 201611L but that implies >> HOSTED >> - // and we want these functions to be freestanding. >> -#if __cplusplus >= 201703L // C++ >= 17 >> +#if __glibcxx_freestanding_chrono >= 201611L // C++ >= 17 >> /** Convert a `time_point` to type `ToDur` and round down. >> * >> * The result is the same time point as measured by the same clock, >> but >> @@ -1208,7 +1204,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> /// @} >> /// @} group chrono >> >> -#if _GLIBCXX_HOSTED >> // Clocks. >> >> // Why nanosecond resolution as the default? >> @@ -1248,6 +1243,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2) >> >> static constexpr bool is_steady = false; >> >> +#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 >> }; >> >> >> @@ -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 >> }; >> >> >> @@ -1311,29 +1310,23 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) >> using sys_seconds = sys_time<seconds>; >> using sys_days = sys_time<days>; >> >> + template<> struct is_clock<system_clock> : true_type { }; >> + template<> inline constexpr bool is_clock_v<system_clock> = true; >> + >> + template<> struct is_clock<steady_clock> : true_type { }; >> + template<> inline constexpr bool is_clock_v<steady_clock> = true; >> + >> +#if _GLIBCXX_HOSTED >> using file_clock = ::std::filesystem::__file_clock; >> >> template<typename _Duration> >> using file_time = time_point<file_clock, _Duration>; >> >> - template<> struct is_clock<system_clock> : true_type { }; >> - template<> struct is_clock<steady_clock> : true_type { }; >> template<> struct is_clock<file_clock> : true_type { }; >> - >> - template<> inline constexpr bool is_clock_v<system_clock> = true; >> - template<> inline constexpr bool is_clock_v<steady_clock> = true; >> template<> inline constexpr bool is_clock_v<file_clock> = true; >> +#endif >> /// @} >> #endif // C++20 >> -#elif defined __glibcxx_chrono_cxx20 // C++ >= 20 >> - // Define a fake clock like chrono::local_t so that sys_time etc. >> - // can be used for freestanding. >> - struct __sys_t; >> - template<typename _Duration> >> - using sys_time = time_point<__sys_t, _Duration>; >> - using sys_seconds = sys_time<seconds>; >> - using sys_days = sys_time<days>; >> -#endif // _GLIBCXX_HOSTED >> } // namespace chrono >> >> #ifdef __glibcxx_chrono_udls // C++ >= 14 >> diff --git a/libstdc++-v3/include/bits/version.def >> b/libstdc++-v3/include/bits/version.def >> index 914c1d40db7d..340ef4203e11 100644 >> --- a/libstdc++-v3/include/bits/version.def >> +++ b/libstdc++-v3/include/bits/version.def >> @@ -627,12 +627,12 @@ ftms = { >> values = { >> v = 201611; >> cxxmin = 17; >> - hosted = yes; >> + hosted = yes; // system_clock::now() and steady_clock::now() are >> hosted >> }; >> }; >> >> ftms = { >> - // Unofficial macro for chrono features supported for old string ABI. >> + // Unofficial macro for <chrono> subset supported for old string ABI. >> name = chrono_cxx20; >> values = { >> v = 202306; >> @@ -646,6 +646,27 @@ ftms = { >> }; >> }; >> >> +ftms = { >> + // Unofficial macro for <chrono> subset supported for freestanding. >> + // This excludes Clock::now() functions and everything that depends on >> tzdb. >> + name = freestanding_chrono; >> + values = { >> + v = 202306; >> + cxxmin = 26; >> + no_stdname = yes; >> + }; >> + values = { >> + v = 201907; >> + cxxmin = 20; >> + no_stdname = yes; >> + }; >> + values = { >> + v = 201611; >> + cxxmin = 17; >> + no_stdname = yes; >> + }; >> +}; >> + >> ftms = { >> name = execution; >> values = { >> diff --git a/libstdc++-v3/include/bits/version.h >> b/libstdc++-v3/include/bits/version.h >> index 2a12a69ed98b..3175bc1b65b4 100644 >> --- a/libstdc++-v3/include/bits/version.h >> +++ b/libstdc++-v3/include/bits/version.h >> @@ -713,6 +713,23 @@ >> #endif /* !defined(__cpp_lib_chrono_cxx20) */ >> #undef __glibcxx_want_chrono_cxx20 >> >> +#if !defined(__cpp_lib_freestanding_chrono) >> +# if (__cplusplus > 202302L) >> +# define __glibcxx_freestanding_chrono 202306L >> +# if defined(__glibcxx_want_all) || >> defined(__glibcxx_want_freestanding_chrono) >> +# endif >> +# elif (__cplusplus >= 202002L) >> +# define __glibcxx_freestanding_chrono 201907L >> +# if defined(__glibcxx_want_all) || >> defined(__glibcxx_want_freestanding_chrono) >> +# endif >> +# elif (__cplusplus >= 201703L) >> +# define __glibcxx_freestanding_chrono 201611L >> +# if defined(__glibcxx_want_all) || >> defined(__glibcxx_want_freestanding_chrono) >> +# endif >> +# endif >> +#endif /* !defined(__cpp_lib_freestanding_chrono) */ >> +#undef __glibcxx_want_freestanding_chrono >> + >> #if !defined(__cpp_lib_execution) >> # if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED >> # define __glibcxx_execution 201902L >> diff --git a/libstdc++-v3/include/std/chrono >> b/libstdc++-v3/include/std/chrono >> index 2c020ff7a3a9..10e2830b66cf 100644 >> --- a/libstdc++-v3/include/std/chrono >> +++ b/libstdc++-v3/include/std/chrono >> @@ -54,6 +54,7 @@ >> # include <bit> // __countr_zero >> #endif >> #ifdef __glibcxx_chrono_cxx20 >> +# include <string_view> >> # include <bits/stl_algo.h> // upper_bound >> # include <bits/range_access.h> // begin/end for arrays >> #endif >> @@ -96,7 +97,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> using local_seconds = local_time<seconds>; >> using local_days = local_time<days>; >> >> -#if _GLIBCXX_HOSTED >> class utc_clock; >> class tai_clock; >> class gps_clock; >> @@ -153,10 +153,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> using time_point = chrono::time_point<utc_clock>; >> static constexpr bool is_steady = false; >> >> +#if _GLIBCXX_HOSTED >> [[nodiscard]] >> static time_point >> now() >> { return from_sys(system_clock::now()); } >> +#endif >> >> template<typename _Duration> >> [[nodiscard]] >> @@ -192,9 +194,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> using time_point = chrono::time_point<tai_clock>; >> static constexpr bool is_steady = false; >> >> +#if _GLIBCXX_HOSTED >> [[nodiscard]] >> static time_point >> now(); // in src/c++20/clock.cc >> +#endif >> >> template<typename _Duration> >> [[nodiscard]] >> @@ -230,9 +234,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> using time_point = chrono::time_point<gps_clock>; >> static constexpr bool is_steady = false; >> >> +#if _GLIBCXX_HOSTED >> [[nodiscard]] >> static time_point >> now(); // in src/c++20/clock.cc >> +#endif >> >> template<typename _Duration> >> [[nodiscard]] >> @@ -252,7 +258,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> return gps_time<_CDur>{__t.time_since_epoch()} - 315964809s; >> } >> }; >> -#endif // _GLIBCXX_HOSTED >> >> template<typename _DestClock, typename _SourceClock> >> struct clock_time_conversion >> @@ -269,7 +274,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> { return __t; } >> }; >> >> -#if _GLIBCXX_HOSTED >> template<> >> struct clock_time_conversion<system_clock, system_clock> >> { >> @@ -376,7 +380,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> return _DestClock::from_utc(__t); >> } >> }; >> -#endif // _GLIBCXX_HOSTED >> >> /// @cond undocumented >> namespace __detail >> @@ -387,7 +390,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> clock_time_conversion<_DestClock, _SourceClock>{}(__t); >> }; >> >> -#if _GLIBCXX_HOSTED >> template<typename _DestClock, typename _SourceClock, typename >> _Duration> >> concept __clock_convs_sys >> = requires (const time_point<_SourceClock, _Duration>& __t) { >> @@ -417,7 +419,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> clock_time_conversion<system_clock, utc_clock>{}( >> clock_time_conversion<utc_clock, _SourceClock>{}(__t))); >> }; >> -#endif // _GLIBCXX_HOSTED >> } // namespace __detail >> /// @endcond >> >> @@ -427,12 +428,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> inline auto >> clock_cast(const time_point<_SourceClock, _Duration>& __t) >> requires __detail::__clock_convs<_DestClock, _SourceClock, >> _Duration> >> -#if _GLIBCXX_HOSTED >> || __detail::__clock_convs_sys<_DestClock, _SourceClock, >> _Duration> >> || __detail::__clock_convs_utc<_DestClock, _SourceClock, >> _Duration> >> || __detail::__clock_convs_sys_utc<_DestClock, _SourceClock, >> _Duration> >> || __detail::__clock_convs_utc_sys<_DestClock, _SourceClock, >> _Duration> >> -#endif // _GLIBCXX_HOSTED >> { >> constexpr bool __direct >> = __detail::__clock_convs<_DestClock, _SourceClock, _Duration>; >> @@ -440,7 +439,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> { >> return clock_time_conversion<_DestClock, _SourceClock>{}(__t); >> } >> -#if _GLIBCXX_HOSTED >> else >> { >> constexpr bool __convert_via_sys_clock >> @@ -491,7 +489,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> } >> } >> } >> -#endif // _GLIBCXX_HOSTED >> } >> >> // CALENDRICAL TYPES >> @@ -2528,10 +2525,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> } >> } >> >> -#if _GLIBCXX_HOSTED >> -#if __cpp_lib_chrono >= 201803L >> // C++20 [time.zones] Time zones >> >> + template<class _Tp> struct zoned_traits { }; >> + >> + enum class choose { earliest, latest }; >> + >> +#if __cpp_lib_chrono >= 201803L // C++ >= 20 && HOSTED && USE_CXX11_ABI >> struct tzdb; >> >> struct sys_info >> @@ -2622,8 +2622,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> } >> /// @endcond >> >> - enum class choose { earliest, latest }; >> - >> class time_zone >> { >> public: >> @@ -2947,8 +2945,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> seconds _M_s; // == date().time_since_epoch() * value().count() >> }; >> >> - template<class _Tp> struct zoned_traits { }; >> - >> template<> >> struct zoned_traits<const time_zone*> >> { >> @@ -2987,6 +2983,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> string remote_version(); >> >> template<typename _Duration, typename _TimeZonePtr = const >> time_zone*> >> + class zoned_time; >> +#endif // __cpp_lib_chrono >= 201803L >> + >> + template<typename _Duration, typename _TimeZonePtr> >> class zoned_time >> { >> static_assert(__is_duration_v<_Duration>); >> @@ -3141,10 +3141,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> get_sys_time() const >> { return _M_tp; } >> >> +#if __cpp_lib_chrono >= 201803L // C++ >= 20 && HOSTED && USE_CXX11_ABI >> [[nodiscard]] >> sys_info >> get_info() const >> { return _M_zone->get_info(_M_tp); } >> +#endif >> >> [[nodiscard]] friend bool >> operator==(const zoned_time&, const zoned_time&) = default; >> @@ -3157,6 +3159,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> friend class zoned_time; >> }; >> >> +#if __cpp_lib_chrono >= 201803L // C++ >= 20 && HOSTED && USE_CXX11_ABI >> + >> zoned_time() -> zoned_time<seconds>; >> >> template<typename _Duration> >> @@ -3193,6 +3197,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> -> zoned_time<common_type_t<_Duration, seconds>, >> __time_zone_representation<_TimeZonePtrOrName>>; >> > As for freestanding you need to provide your own time zone pointer, the > above CTADs > are very useful, as you could do zoned_time tp(my_zone_pointer, time), > withotu specifying. > > I think for freestanding we should define time_zone_representation as: > template<typename _TimeZonePtrOrName> > struct __time_zone_representation_struct > { > static_assert(is_convertible_v<_TimeZonePtrOrName, string_view>, > "time_zone is not supported on freedstanding, a > custom time zone pointer need to provided"); > using type = remove_cvref_t<_TimeZonePtrOrName>; > }; > > template<typename _TimeZonePtrOrName> > using __time_zone_representation = typename > __time_zone_representation_struct<_TimeZonePtrOrName>::type; > > We want to static_assert on is_convertible to string_view, so we guarantee > that what is supported on freestanding, > is true subset of hosted mode. Otherwise, for malicous time_zone_ptr type > that is convertible to string_view we may get > different results. > > > >> >> + using zoned_seconds = zoned_time<seconds>; >> + >> +#endif // __cpp_lib_chrono >= 201803L >> + >> template<typename _Dur1, typename _TZPtr1, typename _Dur2, typename >> _TZPtr2> >> [[nodiscard]] >> inline bool >> @@ -3203,9 +3211,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> && __x.get_sys_time() == __y.get_sys_time(); >> } >> >> - using zoned_seconds = zoned_time<seconds>; >> -#endif // __cpp_lib_chrono >= 201803L >> - >> namespace __detail >> { >> // This function is inline to support fast conversions between >> utc_time >> @@ -3318,7 +3323,6 @@ namespace __detail >> const auto __li = __detail::__get_leap_second_info(__s, false); >> return utc_time<_CDur>{__t.time_since_epoch()} + __li.elapsed; >> } >> -#endif // _GLIBCXX_HOSTED >> >> /// @} group chrono >> #endif // C++20 >> @@ -3585,7 +3589,6 @@ namespace __detail >> } >> }; >> >> -#if _GLIBCXX_HOSTED >> #if __cpp_lib_chrono >= 201803L >> // zoned_time >> template<typename _Duration, typename _TimeZonePtr> >> @@ -3644,7 +3647,6 @@ namespace __detail >> } >> }; >> #endif // __cpp_lib_chrono >= 201803L >> -#endif // _GLIBCXX_HOSTED >> #endif // __glibcxx_chrono_cxx20 >= 202306 >> >> #ifdef __glibcxx_chrono_cxx20 >> diff --git a/libstdc++-v3/testsuite/20_util/system_clock/1.cc >> b/libstdc++-v3/testsuite/20_util/system_clock/1.cc >> index b0cb3a1ac59e..7541d501321b 100644 >> --- a/libstdc++-v3/testsuite/20_util/system_clock/1.cc >> +++ b/libstdc++-v3/testsuite/20_util/system_clock/1.cc >> @@ -28,12 +28,12 @@ main() >> { >> using namespace std::chrono; >> >> - system_clock::time_point t1 = system_clock::now(); >> - bool is_steady = system_clock::is_steady; >> - is_steady = is_steady; // suppress unused warning >> + [[maybe_unused]] system_clock::time_point t1; >> +#if __STDC_HOSTED__ >> + t1 = system_clock::now(); >> std::time_t t2 = system_clock::to_time_t(t1); >> system_clock::time_point t3 = system_clock::from_time_t(t2); >> t3 = t3; // suppress unused warning >> - >> - return 0; >> +#endif >> + [[maybe_unused]] bool is_steady = system_clock::is_steady; >> } >> diff --git a/libstdc++-v3/testsuite/20_util/system_clock/99832.cc >> b/libstdc++-v3/testsuite/20_util/system_clock/99832.cc >> index 693d4d647d9b..7d32cecdcc11 100644 >> --- a/libstdc++-v3/testsuite/20_util/system_clock/99832.cc >> +++ b/libstdc++-v3/testsuite/20_util/system_clock/99832.cc >> @@ -1,5 +1,6 @@ >> // { dg-options "-O0 -g0" } >> // { dg-do compile { target c++20 } } >> +// { dg-require-effective-target hosted } >> // { dg-final { scan-assembler-not "system_clock9to_time_t" } } >> >> // Bug libstdc++/99832 >> diff --git >> a/libstdc++-v3/testsuite/20_util/time_point/comparison_operators/three_way.cc >> b/libstdc++-v3/testsuite/20_util/time_point/comparison_operators/three_way.cc >> index 104c4b3bf118..e5c7d7522a03 100644 >> --- >> a/libstdc++-v3/testsuite/20_util/time_point/comparison_operators/three_way.cc >> +++ >> b/libstdc++-v3/testsuite/20_util/time_point/comparison_operators/three_way.cc >> @@ -27,7 +27,11 @@ test01() >> { >> using namespace std::chrono; >> >> +#if __STDC_HOSTED__ >> auto ns = system_clock::now(); >> +#else >> + auto ns = system_clock::time_point(12345s); >> +#endif >> auto s = time_point_cast<seconds>(ns + seconds(2)); >> >> VERIFY( s != ns ); >> diff --git a/libstdc++-v3/testsuite/std/time/clock/file/members.cc >> b/libstdc++-v3/testsuite/std/time/clock/file/members.cc >> index a23d6b1f9d20..c37015139196 100644 >> --- a/libstdc++-v3/testsuite/std/time/clock/file/members.cc >> +++ b/libstdc++-v3/testsuite/std/time/clock/file/members.cc >> @@ -16,6 +16,7 @@ >> // <http://www.gnu.org/licenses/>. >> >> // { dg-do run { target c++20 } } >> +// { dg-require-effective-target hosted } >> >> #include <chrono> >> #include <testsuite_hooks.h> >> diff --git a/libstdc++-v3/testsuite/std/time/clock/file/overview.cc >> b/libstdc++-v3/testsuite/std/time/clock/file/overview.cc >> index ac56e3d16aba..2d0482204f72 100644 >> --- a/libstdc++-v3/testsuite/std/time/clock/file/overview.cc >> +++ b/libstdc++-v3/testsuite/std/time/clock/file/overview.cc >> @@ -16,6 +16,7 @@ >> // <http://www.gnu.org/licenses/>. >> >> // { dg-do compile { target c++20 } } >> +// { dg-require-effective-target hosted } >> >> #include <chrono> >> >> diff --git a/libstdc++-v3/testsuite/std/time/clock/gps/1.cc >> b/libstdc++-v3/testsuite/std/time/clock/gps/1.cc >> index 8be517b316bb..95bdc504a8fe 100644 >> --- a/libstdc++-v3/testsuite/std/time/clock/gps/1.cc >> +++ b/libstdc++-v3/testsuite/std/time/clock/gps/1.cc >> @@ -33,6 +33,7 @@ test02() >> void >> test03() >> { >> +#if __STDC_HOSTED__ >> using namespace std::chrono; >> >> gps_time<gps_clock::duration> gps1 = gps_clock::now(); >> @@ -45,6 +46,7 @@ test03() >> >> gps_seconds s = time_point_cast<seconds>(gps1); >> VERIFY( gps1 - s < 1s ); >> +#endif >> } >> >> int main() >> diff --git a/libstdc++-v3/testsuite/std/time/clock/tai/1.cc >> b/libstdc++-v3/testsuite/std/time/clock/tai/1.cc >> index 63cc9927859e..8925d7624149 100644 >> --- a/libstdc++-v3/testsuite/std/time/clock/tai/1.cc >> +++ b/libstdc++-v3/testsuite/std/time/clock/tai/1.cc >> @@ -36,6 +36,7 @@ test02() >> void >> test03() >> { >> +#if __STDC_HOSTED__ >> using namespace std::chrono; >> >> tai_time<tai_clock::duration> tai1 = tai_clock::now(); >> @@ -48,6 +49,7 @@ test03() >> >> tai_seconds s = time_point_cast<seconds>(tai1); >> VERIFY( tai1 - s < 1s ); >> +#endif >> } >> >> int main() >> diff --git >> a/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc >> b/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc >> index 5b769d56af55..7e8c1f581ffd 100644 >> --- a/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc >> +++ b/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc >> @@ -1,4 +1,5 @@ >> // { dg-do compile { target c++20 } } >> +// { dg-require-effective-target hosted } >> >> #include <chrono> >> #include <format> >> diff --git a/libstdc++-v3/testsuite/std/time/format/pr120114.cc >> b/libstdc++-v3/testsuite/std/time/format/pr120114.cc >> index cdde4685eda6..c9ec16904079 100644 >> --- a/libstdc++-v3/testsuite/std/time/format/pr120114.cc >> +++ b/libstdc++-v3/testsuite/std/time/format/pr120114.cc >> @@ -1,6 +1,7 @@ >> // { dg-do run { target c++23 } } >> // { dg-options "-fexec-charset=UTF-8" } >> // { dg-timeout-factor 2 } >> +// { dg-require-effective-target hosted } >> >> #include <algorithm> >> #include <chrono> >> diff --git a/libstdc++-v3/testsuite/std/time/format/pr120481.cc >> b/libstdc++-v3/testsuite/std/time/format/pr120481.cc >> index a748acb59a9b..e7bd2108e273 100644 >> --- a/libstdc++-v3/testsuite/std/time/format/pr120481.cc >> +++ b/libstdc++-v3/testsuite/std/time/format/pr120481.cc >> @@ -1,6 +1,7 @@ >> // { dg-do run { target c++23 } } >> // { dg-options "-fexec-charset=UTF-8" } >> // { dg-timeout-factor 2 } >> +// { dg-require-effective-target hosted } >> >> #include <algorithm> >> #include <chrono> >> diff --git a/libstdc++-v3/testsuite/std/time/format/precision.cc >> b/libstdc++-v3/testsuite/std/time/format/precision.cc >> index aa266156c1ff..5425d671199d 100644 >> --- a/libstdc++-v3/testsuite/std/time/format/precision.cc >> +++ b/libstdc++-v3/testsuite/std/time/format/precision.cc >> @@ -1,4 +1,5 @@ >> // { dg-do run { target c++20 } } >> +// { dg-require-effective-target hosted } >> >> #include <chrono> >> #include <ranges> >> diff --git a/libstdc++-v3/testsuite/std/time/format/whitespace.cc >> b/libstdc++-v3/testsuite/std/time/format/whitespace.cc >> index 9637886aae5b..cd5a2840c31b 100644 >> --- a/libstdc++-v3/testsuite/std/time/format/whitespace.cc >> +++ b/libstdc++-v3/testsuite/std/time/format/whitespace.cc >> @@ -1,4 +1,5 @@ >> // { dg-do run { target c++20 } } >> +// { dg-require-effective-target hosted } >> >> #include <chrono> >> #include <testsuite_hooks.h> >> diff --git a/libstdc++-v3/testsuite/std/time/syn_c++20.cc >> b/libstdc++-v3/testsuite/std/time/syn_c++20.cc >> index 62abbc52ad2f..59bb38a01fb3 100644 >> --- a/libstdc++-v3/testsuite/std/time/syn_c++20.cc >> +++ b/libstdc++-v3/testsuite/std/time/syn_c++20.cc >> @@ -27,12 +27,25 @@ >> # define EXPECTED_VALUE 201611L >> #endif >> >> +#if __STDC_HOSTED__ >> + >> #ifndef __cpp_lib_chrono >> # error "Feature test macro for chrono is missing in <chrono>" >> #elif __cpp_lib_chrono < EXPECTED_VALUE >> # error "Feature test macro for chrono has wrong value in <chrono>" >> #endif >> >> +#else // __cpp_lib_chrono is not defined for freestanding >> + >> +#ifndef __glibcxx_freestanding_chrono >> +# error "Feature test macro for freestanding chrono is missing in >> <chrono>" >> +#elif __glibcxx_freestanding_chrono < EXPECTED_VALUE >> +# error "Feature test macro for chrono has wrong value in <chrono>" >> +#endif >> + >> +#endif >> + >> + >> namespace __gnu_test >> { >> // Check for the new additions to <chrono> in C++20 >> @@ -64,8 +77,10 @@ namespace __gnu_test >> using std::chrono::gps_time; >> using std::chrono::gps_seconds; >> >> +#if __STDC_HOSTED__ // no file_clock in freestanding >> using std::chrono::file_clock; >> using std::chrono::file_time; >> +#endif >> >> using std::chrono::local_t; >> using std::chrono::local_time; >> @@ -101,7 +116,7 @@ namespace __gnu_test >> using std::chrono::make12; >> using std::chrono::make24; >> >> -#if __cpp_lib_chrono >= 201803L >> +#if __cpp_lib_chrono >= 201803L // full C++20 tzdb support >> using std::chrono::tzdb; >> using std::chrono::tzdb_list; >> using std::chrono::get_tzdb; >> @@ -130,10 +145,12 @@ namespace __gnu_test >> using std::chrono::time_zone_link; >> #endif >> >> +#if __STDC_HOSTED__ // no chrono I/O in freestanding >> using std::chrono::local_time_format; >> >> using std::chrono::from_stream; >> using std::chrono::parse; >> +#endif >> >> using std::chrono::last; >> using std::chrono::Sunday; >> @@ -197,6 +214,8 @@ namespace __gnu_test >> static_assert( is_time_point<local_seconds> ); >> static_assert( is_time_point<local_days> ); >> >> +#if __STDC_HOSTED__ // no file_clock in freestanding >> static_assert( std::is_class_v<file_clock> ); >> static_assert( is_time_point<file_time<std::chrono::milliseconds>> ); >> +#endif >> } >> diff --git a/libstdc++-v3/testsuite/std/time/time_zone/requirements.cc >> b/libstdc++-v3/testsuite/std/time/time_zone/requirements.cc >> index 929fea2c0eb1..865a7caf917a 100644 >> --- a/libstdc++-v3/testsuite/std/time/time_zone/requirements.cc >> +++ b/libstdc++-v3/testsuite/std/time/time_zone/requirements.cc >> @@ -1,5 +1,5 @@ >> // { dg-do compile { target c++20 } } >> -// { dg-require-effective-target cxx11_abi } >> +// { dg-require-effective-target tzdb } >> >> #include <chrono> >> >> diff --git a/libstdc++-v3/testsuite/std/time/traits/is_clock.cc >> b/libstdc++-v3/testsuite/std/time/traits/is_clock.cc >> index e52691c6f16d..81b16e9a3961 100644 >> --- a/libstdc++-v3/testsuite/std/time/traits/is_clock.cc >> +++ b/libstdc++-v3/testsuite/std/time/traits/is_clock.cc >> @@ -22,6 +22,7 @@ >> >> namespace chrono = std::chrono; >> >> +#if __cpp_lib_chrono >= 201803L >> static_assert( chrono::is_clock<chrono::system_clock>::value ); >> static_assert( chrono::is_clock_v<chrono::system_clock> ); >> >> @@ -48,6 +49,7 @@ static_assert( >> chrono::is_clock_v<Clock<chrono::steady_clock>> ); >> >> static_assert(chrono::is_clock<Clock<chrono::file_clock>>::value); >> static_assert(chrono::is_clock_v<Clock<chrono::file_clock>>); >> +#endif >> >> static_assert( chrono::is_clock<__gnu_test::slow_clock>::value ); >> static_assert( chrono::is_clock_v<__gnu_test::slow_clock> ); >> diff --git a/libstdc++-v3/testsuite/std/time/zoned_time/custom.cc >> b/libstdc++-v3/testsuite/std/time/zoned_time/custom.cc >> index 83e1f6dca43d..572bed60d4a9 100644 >> --- a/libstdc++-v3/testsuite/std/time/zoned_time/custom.cc >> +++ b/libstdc++-v3/testsuite/std/time/zoned_time/custom.cc >> @@ -1,58 +1,94 @@ >> // { dg-do run { target c++20 } } >> -// { dg-require-effective-target tzdb } >> > I would prefer to have a separate test that uses a "non-pointer" zone > pointer, something like > (and do not modify this one): > struct ZoneOffset > { > minutes offset; > > ZoneOffset operator->() const noexcept > { return *this; } > > template<typename Dur> > std::chrono::sys_time<Dur> to_sys(const > std::chrono::local_time<Dur>& tp) const noexcept > { > return tp - offset; > } > > template<typename Dur> > std::chrono::local_time<Dur> to_local(const > std::chrono::sys_time<Dur>& tp) const noexcept > { > return tp + offset; > } > }; > > The zoned_traits remains empty (the default constructor and cosntructor > from string_view are constrained), > znd then this can be used (assuming CTAD changes): > > zoned_time tz{ZoneOffset(10min), ...}; > We then could link to this test in the documentation, showing how the zoned_time can be used effectively on such target, embeding information inside the "pointer", instead of requiring separate set of variables. > > >> >> #include <chrono> >> #include <set> >> #include <stdexcept> >> #include <testsuite_hooks.h> >> >> +// Get the name of the current zone. >> +std::string_view >> +current_zone_name() >> +{ >> +#if __cpp_lib_chrono >= 201803L // Full tzdb support >> + return std::chrono::current_zone()->name(); >> +#else // freestanding or old ABI >> + return "Freestanding/Zone"; >> +#endif >> +} >> + >> +// Get the canonical name of a zone or link. >> +std::string_view >> +resolved_zone_name(std::string_view name) >> +{ >> +#if __cpp_lib_chrono >= 201803L // Full tzdb support >> + return std::chrono::locate_zone(name)->name(); >> +#else // freestanding or old ABI >> + return name; >> +#endif >> +} >> + >> struct local_tz >> { >> - local_tz() : name(std::chrono::current_zone()->name()) { } >> + local_tz() : name(current_zone_name()) { } >> >> explicit local_tz(std::string_view name) : name(name) { } >> >> template<typename Dur> >> - std::chrono::sys_time<Dur> to_sys(const >> std::chrono::local_time<Dur>& d) >> - { return std::chrono::locate_zone(name)->to_sys(d); } >> + std::chrono::sys_time<Dur> to_sys(const >> std::chrono::local_time<Dur>& tp) >> + { >> +#if __cpp_lib_chrono >= 201803L // Full tzdb support >> + return std::chrono::locate_zone(name)->to_sys(tp); >> +#else >> + return { tp.time_since_epoch() }; >> +#endif >> + } >> >> template<typename Dur> >> - std::chrono::sys_time<Dur> to_local(const >> std::chrono::sys_time<Dur>& d) >> - { return std::chrono::locate_zone(name)->to_sys(d); } >> + std::chrono::local_time<Dur> to_local(const >> std::chrono::sys_time<Dur>& tp) >> + { >> +#if __cpp_lib_chrono >= 201803L // Full tzdb support >> + return std::chrono::locate_zone(name)->to_local(tp); >> +#else >> + return { tp.time_since_epoch() }; >> +#endif >> + } >> >> +#if __cpp_lib_chrono >= 201803L // Full tzdb support >> template<typename Dur> >> - std::chrono::sys_info get_info(const std::chrono::sys_time<Dur>& d) >> - { return std::chrono::locate_zone(name)->get_info(d); } >> + std::chrono::sys_info get_info(const std::chrono::sys_time<Dur>& tp) >> + { return std::chrono::locate_zone(name)->get_info(tp); } >> +#endif >> >> - struct indirect_cmp >> - { >> - bool operator()(const local_tz* lhs, const local_tz* rhs) const >> - { return lhs->name < rhs->name; } >> - }; >> - >> - bool eq(const std::chrono::time_zone* tz) const noexcept >> - { return name == tz->name(); } >> + // Not part of the required API, used for testing below. >> + bool eq(std::string_view s) const { return s == name; } >> >> private: >> std::string_view name; >> + >> + friend struct std::chrono::zoned_traits<const local_tz*>; >> }; >> >> template<> struct std::chrono::zoned_traits<const local_tz*> >> { >> - static const local_tz* default_zone() >> - { >> - return locate_zone(std::chrono::current_zone()->name()); >> - } >> + static const local_tz* >> + default_zone() { return locate_zone(current_zone_name()); } >> >> - static const local_tz* locate_zone(std::string_view name) >> + static const local_tz* >> + locate_zone(std::string_view name) >> { >> - static std::set<const local_tz*, local_tz::indirect_cmp> zones; >> - local_tz tz(name); >> - if (auto z = zones.find(&tz); z != zones.end()) >> - return *z; >> - if (std::chrono::locate_zone(name)) >> - return *zones.insert(new local_tz(tz)).first; >> - throw std::runtime_error("zone not found"); >> +#if __cpp_lib_chrono >= 201803L // Full tzdb support >> + if (!std::chrono::locate_zone(name)) >> + throw std::runtime_error("zone not found"); >> +#endif >> + >> + struct cmp >> + { >> + bool operator()(const local_tz& lhs, const local_tz& rhs) const >> + { return lhs.name < rhs.name; } >> + }; >> + static std::set<local_tz, cmp> zones; >> + >> + return &*zones.emplace(name).first; >> } >> }; >> >> @@ -62,10 +98,10 @@ test_custom_tzptr() >> using namespace std::chrono; >> >> zoned_time<seconds, const local_tz*> z; >> - VERIFY( z.get_time_zone()->eq(std::chrono::current_zone()) ); >> + VERIFY( z.get_time_zone()->eq(current_zone_name()) ); >> >> zoned_time<seconds, const local_tz*> >> z2(std::string_view("Europe/London")); >> - VERIFY( >> z2.get_time_zone()->eq(std::chrono::locate_zone("Europe/London")) ); >> + VERIFY( z2.get_time_zone()->eq(resolved_zone_name("Europe/London")) ); >> } >> >> int main() >> diff --git a/libstdc++-v3/testsuite/std/time/zoned_time/req_neg.cc >> b/libstdc++-v3/testsuite/std/time/zoned_time/req_neg.cc >> index 9950a1f8394d..95d95a59c07f 100644 >> --- a/libstdc++-v3/testsuite/std/time/zoned_time/req_neg.cc >> +++ b/libstdc++-v3/testsuite/std/time/zoned_time/req_neg.cc >> @@ -1,8 +1,9 @@ >> // { dg-do compile { target c++20 } } >> -// { dg-require-effective-target tzdb } >> >> #include <chrono> >> >> -std::chrono::zoned_time<std::chrono::year> z; // { dg-error "here" } >> +struct TZ; // custom zone so this works even for freestanding and old ABI >> + >> +std::chrono::zoned_time<std::chrono::year, const TZ*> z; // { dg-error >> "here" } >> // { dg-error "static assertion failed" "" { target *-*-* } 0 } >> // { dg-prune-output "common_type" } >> diff --git a/libstdc++-v3/testsuite/util/slow_clock.h >> b/libstdc++-v3/testsuite/util/slow_clock.h >> index f11a1a6410fc..a3138374fead 100644 >> --- a/libstdc++-v3/testsuite/util/slow_clock.h >> +++ b/libstdc++-v3/testsuite/util/slow_clock.h >> @@ -32,10 +32,14 @@ struct slow_clock >> using time_point = std::chrono::time_point<slow_clock, duration>; >> static constexpr bool is_steady = false; >> >> - static time_point now() >> - { >> - auto real = std::chrono::system_clock::now(); >> - return time_point{real.time_since_epoch() / 3}; >> - } >> + static time_point now(); >> }; >> + >> +#if _GLIBCXX_HOSTED >> +inline slow_clock::time_point slow_clock::now() >> +{ >> + auto real = std::chrono::system_clock::now(); >> + return time_point{real.time_since_epoch() / 3}; >> +} >> +#endif >> } >> -- >> 2.56.0 >> >>
