diff mbox series

libstdc++: Enable most of <chrono> for freestanding

Message ID 20240912204436.478587-1-jwakely@redhat.com
State New
Headers show
Series libstdc++: Enable most of <chrono> for freestanding | expand

Commit Message

Jonathan Wakely Sept. 12, 2024, 8:19 p.m. UTC
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.

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

Comments

Arsen Arsenović Sept. 14, 2024, 9:38 a.m. UTC | #1
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?

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.

The patch seems OK either way.

> 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">&lt;chrono&gt;</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">&lt;chrono&gt;</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
Jonathan Wakely Sept. 14, 2024, 2:16 p.m. UTC | #2
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.


> > 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">&lt;chrono&gt;</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">&lt;chrono&gt;</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ć
Jonathan Wakely Sept. 15, 2024, 3:20 p.m. UTC | #3
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">&lt;chrono&gt;</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">&lt;chrono&gt;</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ć
diff mbox series

Patch

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">&lt;chrono&gt;</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">&lt;chrono&gt;</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