[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