On Sat, 14 Sept 2024 at 10:39, Arsen Arsenović <[email protected]> wrote:
>
> Jonathan Wakely <[email protected]> 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ć