[PATCH] libstdc++: Enable most of <chrono> for freestanding
Jonathan Wakely
jwakely@redhat.com
Sun Sep 15 15:20:43 GMT 2024
On Sat, 14 Sept 2024 at 15:16, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On Sat, 14 Sept 2024 at 10:39, Arsen Arsenović <arsen@aarsen.me> wrote:
> >
> > Jonathan Wakely <jwakely@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.
I've pushed this now (after adding Arsen's Reviewed-by tag).
>
>
> > > 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ć
More information about the Libstdc++
mailing list