On Sat, 14 Sept 2024 at 10:39, Arsen Arsenović <ar...@aarsen.me> wrote: > > Jonathan Wakely <jwak...@redhat.com> writes: > > > This restores support for most of <chrono> with -ffreestanding. In case > > there are users who want a minimal freestanding implementation that only > > provides what the standard guarantees, there's a new macro that disables > > <chrono> again. This can be used to write more portable freestanding > > code that doesn't rely on <chrono> being usable. As we add other things > > to the freestanding subset (e.g. <string> for PR 113398 and <cmath> for > > PR 109814) we can add other _GLIBCXX_NO_FREESTANDING_XXX macros, and a > > _GLIBCXX_NO_FREESTANDING_EXTRAS to define all of them at once. I haven't > > done that in this patch, because there's on the CHRONO one for now. > > That seems reasonable to me. > > Do we want to count the headers that we moved into the non-hosted > configuration into this 'extras' set also (such as tuple)? Or just > things not installed in the --disable-hosted-libstdcxx configuration?
Ah yes, good point. I think logically it makes sense for the macro to disable all extensions, including <tuple> etc. That's assuming the macros will actually be used. Somebody emailed me off-list saying maybe we should support "freestanding plus extras" and "freestanding without extras" but I don't know if they actually want to use the latter, or if it was just a thought they had. > > That also impacts what we do if/when we move the stuff that was made not > freestanding due to std::allocator (IIRC vector and string are in this > set) into the std_freestanding subset. Yup. > The patch seems OK either way. Thanks for looking. > > Tested x86_64-linux. > > > > -- >8 -- > > > > This makes durations, time points and calendrical types available for > > freestanding. The clocks and time zone utilities are disabled for > > freestanding, as they require functions in the hosted lib. > > > > Add support for a new macro _GLIBCXX_NO_FREESTANDING_CHRONO which can be > > used to explicitly disable <chrono> for freestanding. > > > > libstdc++-v3/ChangeLog: > > > > * doc/xml/manual/using.xml (_GLIBCXX_NO_FREESTANDING_CHRONO): > > Document macro. > > * doc/html/*: Regenerate. > > * include/bits/chrono.h [_GLIBCXX_NO_FREESTANDING_CHRONO]: > > Only include <bits/require_hosted.h> when this macro is defined. > > [_GLIBCXX_HOSTED]: Only define clocks for hosted. > > * include/bits/version.def (chrono_udls): Remove hosted=yes. > > * include/bits/version.h: Regenerate. > > * include/std/chrono [_GLIBCXX_HOSTED]: Only define clocks and > > time zone utilities for hosted. > > * testsuite/std/time/freestanding.cc: New test. > > --- > > .../doc/html/manual/using_macros.html | 7 +++ > > libstdc++-v3/doc/xml/manual/using.xml | 12 +++++ > > libstdc++-v3/include/bits/chrono.h | 24 ++++++--- > > libstdc++-v3/include/bits/version.def | 1 - > > libstdc++-v3/include/bits/version.h | 2 +- > > libstdc++-v3/include/std/chrono | 24 +++++++-- > > .../testsuite/std/time/freestanding.cc | 52 +++++++++++++++++++ > > 7 files changed, 109 insertions(+), 13 deletions(-) > > create mode 100644 libstdc++-v3/testsuite/std/time/freestanding.cc > > > > diff --git a/libstdc++-v3/doc/html/manual/using_macros.html > > b/libstdc++-v3/doc/html/manual/using_macros.html > > index ae564692630..67623b5e2af 100644 > > --- a/libstdc++-v3/doc/html/manual/using_macros.html > > +++ b/libstdc++-v3/doc/html/manual/using_macros.html > > @@ -124,4 +124,11 @@ > > must be present on all vector operations or none, so this macro > > must > > be defined to the same value for all translation units that create, > > destroy, or modify vectors. > > + </p></dd><dt><span class="term"><code > > class="code">_GLIBCXX_NO_FREESTANDING_CHRONO</code></span></dt><dd><p> > > + Undefined by default. When defined, the > > + <code class="filename"><chrono></code> header cannot > > + be used with <code class="option">-ffreestanding</code>. > > + When not defined, durations, time points, and calendar types are > > + available for freestanding, but the standard clocks and the time zone > > + database are not (because they require OS support). > > </p></dd></dl></div></div><div class="navfooter"><hr /><table > > width="100%" summary="Navigation footer"><tr><td width="40%" > > align="left"><a accesskey="p" href="using_headers.html">Prev</a> </td><td > > width="20%" align="center"><a accesskey="u" > > href="using.html">Up</a></td><td width="40%" align="right"> <a > > accesskey="n" href="using_dual_abi.html">Next</a></td></tr><tr><td > > width="40%" align="left" valign="top">Headers </td><td width="20%" > > align="center"><a accesskey="h" href="../index.html">Home</a></td><td > > width="40%" align="right" valign="top"> Dual > > ABI</td></tr></table></div></body></html> > > \ No newline at end of file > > diff --git a/libstdc++-v3/doc/xml/manual/using.xml > > b/libstdc++-v3/doc/xml/manual/using.xml > > index 6675359f3b3..4e1c70040b5 100644 > > --- a/libstdc++-v3/doc/xml/manual/using.xml > > +++ b/libstdc++-v3/doc/xml/manual/using.xml > > @@ -1321,6 +1321,18 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 > > hello.cc -o test.exe > > destroy, or modify vectors. > > </para> > > </listitem></varlistentry> > > + > > + <varlistentry><term><code>_GLIBCXX_NO_FREESTANDING_CHRONO</code></term> > > + <listitem> > > + <para> > > + Undefined by default. When defined, the > > + <filename class="headerfile"><chrono></filename> header cannot > > + be used with <option>-ffreestanding</option>. > > + When not defined, durations, time points, and calendar types are > > + available for freestanding, but the standard clocks and the time zone > > + database are not (because they require OS support). > > + </para> > > + </listitem></varlistentry> > > </variablelist> > > > > </section> > > diff --git a/libstdc++-v3/include/bits/chrono.h > > b/libstdc++-v3/include/bits/chrono.h > > index 0773867da71..fd9c4642f4f 100644 > > --- a/libstdc++-v3/include/bits/chrono.h > > +++ b/libstdc++-v3/include/bits/chrono.h > > @@ -37,7 +37,9 @@ > > #include <ratio> > > #include <type_traits> > > #include <limits> > > -#include <ctime> > > +#if _GLIBCXX_HOSTED > > +# include <ctime> > > +#endif > > #include <bits/parse_numbers.h> // for literals support. > > #if __cplusplus >= 202002L > > # include <concepts> > > @@ -50,7 +52,7 @@ namespace std _GLIBCXX_VISIBILITY(default) > > { > > _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > > -#if __cplusplus >= 201703L > > +#if __cplusplus >= 201703L && _GLIBCXX_HOSTED > > namespace filesystem { struct __file_clock; }; > > #endif > > > > @@ -372,7 +374,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > { }; > > #endif // C++20 > > > > -#ifdef __glibcxx_chrono // C++ >= 17 && HOSTED > > +#if __cplusplus >= 201703L // C++ >= 17 > > /** Convert a `duration` to type `ToDur` and round down. > > * > > * If the duration cannot be represented exactly in the result type, > > @@ -1196,6 +1198,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > /// @} > > /// @} group chrono > > > > +#if _GLIBCXX_HOSTED > > // Clocks. > > > > // Why nanosecond resolution as the default? > > @@ -1310,9 +1313,18 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) > > template<> inline constexpr bool is_clock_v<file_clock> = true; > > /// @} > > #endif // C++20 > > +#elif __cplusplus >= 202002L > > + // 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 && HOSTED > > +#ifdef __glibcxx_chrono_udls // C++ >= 14 > > inline namespace literals > > { > > /** ISO C++ 2014 namespace for suffixes for duration literals. > > @@ -1435,7 +1447,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) > > } // namespace chrono > > #endif // __glibcxx_chrono_udls > > > > -#if __cplusplus >= 201703L > > +#if __cplusplus >= 201703L && _GLIBCXX_HOSTED > > namespace filesystem > > { > > struct __file_clock > > @@ -1497,7 +1509,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) > > } > > }; > > } // namespace filesystem > > -#endif // C++17 > > +#endif // C++17 && HOSTED > > > > _GLIBCXX_END_NAMESPACE_VERSION > > } // namespace std > > diff --git a/libstdc++-v3/include/bits/version.def > > b/libstdc++-v3/include/bits/version.def > > index bd3af9cba99..36f9ea429c4 100644 > > --- a/libstdc++-v3/include/bits/version.def > > +++ b/libstdc++-v3/include/bits/version.def > > @@ -275,7 +275,6 @@ ftms = { > > values = { > > v = 201304; > > cxxmin = 14; > > - hosted = yes; > > }; > > }; > > > > diff --git a/libstdc++-v3/include/bits/version.h > > b/libstdc++-v3/include/bits/version.h > > index 364e3a05f0e..fb97e67fb99 100644 > > --- a/libstdc++-v3/include/bits/version.h > > +++ b/libstdc++-v3/include/bits/version.h > > @@ -289,7 +289,7 @@ > > #undef __glibcxx_want_to_chars > > > > #if !defined(__cpp_lib_chrono_udls) > > -# if (__cplusplus >= 201402L) && _GLIBCXX_HOSTED > > +# if (__cplusplus >= 201402L) > > # define __glibcxx_chrono_udls 201304L > > # if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono_udls) > > # define __cpp_lib_chrono_udls 201304L > > diff --git a/libstdc++-v3/include/std/chrono > > b/libstdc++-v3/include/std/chrono > > index 7ffa5360728..aa78254dac9 100644 > > --- a/libstdc++-v3/include/std/chrono > > +++ b/libstdc++-v3/include/std/chrono > > @@ -32,7 +32,9 @@ > > > > #pragma GCC system_header > > > > -#include <bits/requires_hosted.h> // for <ctime> and clocks > > +#ifdef _GLIBCXX_NO_FREESTANDING_CHRONO > > +# include <bits/requires_hosted.h> // for <ctime> and clocks > > +#endif > > > > #if __cplusplus < 201103L > > # include <bits/c++0x_warning.h> > > @@ -41,7 +43,9 @@ > > #include <bits/chrono.h> > > > > #if __cplusplus >= 202002L > > -# include <bit> > > +# include <bit> // __countr_zero > > +#endif > > +#if __cplusplus >= 202002L && _GLIBCXX_HOSTED > > # include <sstream> > > # include <string> > > # include <vector> > > @@ -82,6 +86,7 @@ _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; > > @@ -234,7 +239,7 @@ _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 > > @@ -251,6 +256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > { return __t; } > > }; > > > > +#if _GLIBCXX_HOSTED > > template<> > > struct clock_time_conversion<system_clock, system_clock> > > { > > @@ -355,6 +361,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > return _DestClock::from_utc(__t); > > } > > }; > > +#endif // _GLIBCXX_HOSTED > > > > /// @cond undocumented > > namespace __detail > > @@ -365,6 +372,7 @@ _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) { > > @@ -394,7 +402,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > clock_time_conversion<system_clock, utc_clock>{}( > > clock_time_conversion<utc_clock, _SourceClock>{}(__t))); > > }; > > - > > +#endif // _GLIBCXX_HOSTED > > } // namespace __detail > > /// @endcond > > > > @@ -404,10 +412,12 @@ _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>; > > @@ -415,6 +425,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > { > > return clock_time_conversion<_DestClock, _SourceClock>{}(__t); > > } > > +#if _GLIBCXX_HOSTED > > else > > { > > constexpr bool __convert_via_sys_clock > > @@ -465,6 +476,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > } > > } > > } > > +#endif // _GLIBCXX_HOSTED > > } > > > > // CALENDRICAL TYPES > > @@ -2530,6 +2542,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > } > > } > > > > +#if _GLIBCXX_HOSTED > > #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI > > // C++20 [time.zones] Time zones > > > > @@ -3324,6 +3337,7 @@ 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 > > @@ -3358,7 +3372,7 @@ namespace __detail > > _GLIBCXX_END_NAMESPACE_VERSION > > } // namespace std > > > > -#if __cplusplus >= 202002L > > +#if __cplusplus >= 202002L && _GLIBCXX_HOSTED > > # include <bits/chrono_io.h> > > #endif > > > > diff --git a/libstdc++-v3/testsuite/std/time/freestanding.cc > > b/libstdc++-v3/testsuite/std/time/freestanding.cc > > new file mode 100644 > > index 00000000000..afda0d5e561 > > --- /dev/null > > +++ b/libstdc++-v3/testsuite/std/time/freestanding.cc > > @@ -0,0 +1,52 @@ > > +// { dg-options "-ffreestanding" } > > +// { dg-do compile { target c++11 } } > > + > > +#include <chrono> > > + > > +using namespace std::chrono; > > + > > +milliseconds > > +test_duration() > > +{ > > + seconds sec{1}; > > + sec = sec + -sec; > > + return duration_cast<milliseconds>(sec + microseconds{100}); > > +} > > + > > +struct Clock > > +{ > > + using rep = long; > > + using period = std::ratio<1,10>; > > + using duration = std::chrono::duration<rep, period>; > > + using time_point = std::chrono::time_point<Clock>; > > + > > + static const bool is_steady = true; > > + > > + static time_point now() noexcept > > + { > > + static time_point tick{duration{0}}; > > + return tick + tick.time_since_epoch(); > > + } > > +}; > > + > > +Clock::time_point > > +test_time_point() > > +{ > > + auto t = Clock::now() + milliseconds{1}; > > + return time_point_cast<Clock::duration>(t); > > +} > > + > > +#if __cplusplus > 202002L > > +static_assert( is_clock_v<Clock> ); > > + > > +bool > > +test_calendar() > > +{ > > + auto t = test_time_point(); > > + t = clock_cast<Clock>(t); > > + local_days d{floor<days>(t + 1h + 1min + 1s).time_since_epoch()}; > > + year_month_day ymd{d}; > > + weekday w{d}; > > + return w.ok(); > > +} > > +#endif > > -- > Arsen Arsenović