There is very little code that needs to change, just moving some #if
checks and moving a couple of declarations outside hosted-only groups.
This adds a new __glibcxx_freestanding_chrono feature test macro.
If/when WG21 makes <chrono> freestanding we can remove the no_stdname
lines in version.def to also defined __cpp_lib_freestanding_chrono.

The parts that can't be freestanding are the now() member functions of
the clocks, conversions between sys_time and std::time_t, the
file_clock, and everything that depends on chrono::tzdb.

The conversions to/from std::time_t depend on the type defined in
<time.h>, which is not freestanding. It would be possible to do
something like this in chrono::system_clock:

  #if _GLIBCXX_HOSTED
    using _Sys_clock_time_t = std::time_t;
  #else
    using _Sys_clock_time_t = long long;
  #endif

and then define the member functions in terms of that type. That is not
done in this change but could be considered in future.

Accessing leap second info is supported for freestanding, and therefore
so are conversions between utc_time and sys_time. The list of leap
seconds is fixed to the hardcoded list in the <chrono> header, so
reading an up-to-date list from tzdb is not possible in freestanding.

The chrono::zoned_traits and chrono::zoned_time class templates are
freestanding, but the chrono::zoned_traits<const time_zone*> partial
specialization is not. The default template argument for
chrono::zoned_time (which is const time_zone* for hosted) is not present
for freestanding, neither are the deduction guides for zoned_time. The
zoned_time::get_info member returns sys_info which contains std::string,
so that can't be freestanding. The rest of zoned_time can be though.
This provides enough functionality for custom time zones to be provided
in a freestanding program.

The last two `#if _GLIBCXX_HOSTED` checks removed from <chrono> by this
commit were redundant, because they surround a check for
`__cpp_lib_chrono >= 201803L` which is only true for hosted anyway.
Removing those checks is not making chrono::tzdb, chrono::time_zone etc.
available for freestanding, just removing the redundancy.

libstdc++-v3/ChangeLog:

        * include/bits/chrono.h (floor, ceil, round): Change
        preprocessor condition to __glibcxx_freestanding_chrono.
        [!_GLIBCXX_HOSTED] (system_clock, steady_clock): Define.
        [!_GLIBCXX_HOSTED] (__sys_t): Remove.
        [!_GLIBCXX_HOSTED] (sys_time, sys_seconds, sys_days): Remove
        freestanding definitions.
        * include/bits/version.def (freestanding_chrono): Define
        non-standard macro.
        * include/bits/version.h: Regenerate.
        * include/std/chrono [!_GLIBCXX_HOSTED] (utc_clock, tai_clock)
        (gps_clock): Define.
        (clock_time_conversion, clock_cast) [!__STDC_HOSTED__]: Define
        the same as for hosted.
        * testsuite/20_util/system_clock/1.cc [!__STDC_HOSTED__]: Do not
        test now, to_time_t and from_time_t for freestanding.
        * testsuite/20_util/system_clock/99832.cc: Require hosted
        effective target.
        * testsuite/20_util/time_point/comparison_operators/three_way.cc
        [!__cpp_lib_hosted]: Do not use system_clock::now() for
        freestanding.
        * testsuite/std/time/clock/file/members.cc: Require hosted
        effective target.
        * testsuite/std/time/clock/file/overview.cc [!__STDC_HOSTED__]:
        Do not test now() for freestanding.
        * testsuite/std/time/clock/gps/1.cc: Likewise.
        * testsuite/std/time/clock/tai/1.cc: Likewise.
        * testsuite/std/time/format/data_not_present_neg.cc: Require
        hosted effective target.
        * testsuite/std/time/format/pr120114.cc: Likewise.
        * testsuite/std/time/format/pr120481.cc: Likewise.
        * testsuite/std/time/format/precision.cc: Likewise.
        * testsuite/std/time/format/whitespace.cc: Likewise.
        * testsuite/std/time/syn_c++20.cc [!__STDC_HOSTED__]: Do not
        test some components for freestanding.
        * testsuite/std/time/time_zone/requirements.cc: Require hosted
        effective target.
        * testsuite/std/time/traits/is_clock.cc [!__STDC_HOSTED__]: Do
        not test standard clocks for freestanding.
        * testsuite/std/time/zoned_time/custom.cc: Refactor to support
        freestanding and old ABI.  Do not require tzdb effective target.
        * testsuite/std/time/zoned_time/req_neg.cc: Likewise.
        * testsuite/util/slow_clock.h [!_GLIBCXX_HOSTED]: Do not define
        slow_clock::now() function for freestanding.
---

Tested x86_64-linux, using all my usual RUNTESTFLAGS but also tested the
<chrono> parts of the testsuite with -ffreestanding.

Also tested with the "only-old-abi" config that I was working on
recently, so the combination of no-SSO-string and freestanding also
works.

 libstdc++-v3/include/bits/chrono.h            | 35 +++----
 libstdc++-v3/include/bits/version.def         | 25 ++++-
 libstdc++-v3/include/bits/version.h           | 17 ++++
 libstdc++-v3/include/std/chrono               | 46 ++++-----
 .../testsuite/20_util/system_clock/1.cc       | 10 +-
 .../testsuite/20_util/system_clock/99832.cc   |  1 +
 .../comparison_operators/three_way.cc         |  4 +
 .../testsuite/std/time/clock/file/members.cc  |  1 +
 .../testsuite/std/time/clock/file/overview.cc |  1 +
 .../testsuite/std/time/clock/gps/1.cc         |  2 +
 .../testsuite/std/time/clock/tai/1.cc         |  2 +
 .../std/time/format/data_not_present_neg.cc   |  1 +
 .../testsuite/std/time/format/pr120114.cc     |  1 +
 .../testsuite/std/time/format/pr120481.cc     |  1 +
 .../testsuite/std/time/format/precision.cc    |  1 +
 .../testsuite/std/time/format/whitespace.cc   |  1 +
 libstdc++-v3/testsuite/std/time/syn_c++20.cc  | 21 +++-
 .../std/time/time_zone/requirements.cc        |  2 +-
 .../testsuite/std/time/traits/is_clock.cc     |  2 +
 .../testsuite/std/time/zoned_time/custom.cc   | 96 +++++++++++++------
 .../testsuite/std/time/zoned_time/req_neg.cc  |  5 +-
 libstdc++-v3/testsuite/util/slow_clock.h      | 14 ++-
 22 files changed, 200 insertions(+), 89 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono.h 
b/libstdc++-v3/include/bits/chrono.h
index a71d1435f2f6..0a6be709b76d 100644
--- a/libstdc++-v3/include/bits/chrono.h
+++ b/libstdc++-v3/include/bits/chrono.h
@@ -376,9 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { };
 #endif // C++20
 
-    // This should use __glibcxx_chrono >= 201611L but that implies HOSTED
-    // and we want these functions to be freestanding.
-#if __cplusplus >= 201703L // C++ >= 17
+#if __glibcxx_freestanding_chrono >= 201611L // C++ >= 17
     /** Convert a `duration` to type `ToDur` and round down.
      *
      * If the duration cannot be represented exactly in the result type,
@@ -1032,9 +1030,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return __time_point(duration_cast<_ToDur>(__t.time_since_epoch()));
       }
 
-    // This should use __glibcxx_chrono >= 201611L but that implies HOSTED
-    // and we want these functions to be freestanding.
-#if __cplusplus >= 201703L // C++ >= 17
+#if __glibcxx_freestanding_chrono >= 201611L // C++ >= 17
     /** Convert a `time_point` to type `ToDur` and round down.
      *
      * The result is the same time point as measured by the same clock, but
@@ -1208,7 +1204,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     /// @}
     /// @} group chrono
 
-#if _GLIBCXX_HOSTED
     // Clocks.
 
     // Why nanosecond resolution as the default?
@@ -1248,6 +1243,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
 
       static constexpr bool is_steady = false;
 
+#if _GLIBCXX_HOSTED
       static time_point
       now() noexcept;
 
@@ -1268,6 +1264,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
        return time_point_cast<system_clock::duration>
               (__from(chrono::seconds(__t)));
       }
+#endif
     };
 
 
@@ -1286,8 +1283,10 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
 
       static constexpr bool is_steady = true;
 
+#if _GLIBCXX_HOSTED
       static time_point
       now() noexcept;
+#endif
     };
 
 
@@ -1311,29 +1310,23 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
     using sys_seconds = sys_time<seconds>;
     using sys_days = sys_time<days>;
 
+    template<> struct is_clock<system_clock> : true_type { };
+    template<> inline constexpr bool is_clock_v<system_clock> = true;
+
+    template<> struct is_clock<steady_clock> : true_type { };
+    template<> inline constexpr bool is_clock_v<steady_clock> = true;
+
+#if _GLIBCXX_HOSTED
     using file_clock = ::std::filesystem::__file_clock;
 
     template<typename _Duration>
       using file_time = time_point<file_clock, _Duration>;
 
-    template<> struct is_clock<system_clock> : true_type { };
-    template<> struct is_clock<steady_clock> : true_type { };
     template<> struct is_clock<file_clock> : true_type { };
-
-    template<> inline constexpr bool is_clock_v<system_clock> = true;
-    template<> inline constexpr bool is_clock_v<steady_clock> = true;
     template<> inline constexpr bool is_clock_v<file_clock> = true;
+#endif
     /// @}
 #endif // C++20
-#elif defined __glibcxx_chrono_cxx20 // C++ >= 20
-    // 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
diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 914c1d40db7d..340ef4203e11 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -627,12 +627,12 @@ ftms = {
   values = {
     v = 201611;
     cxxmin = 17;
-    hosted = yes;
+    hosted = yes; // system_clock::now() and steady_clock::now() are hosted
   };
 };
 
 ftms = {
-  // Unofficial macro for chrono features supported for old string ABI.
+  // Unofficial macro for <chrono> subset supported for old string ABI.
   name = chrono_cxx20;
   values = {
     v = 202306;
@@ -646,6 +646,27 @@ ftms = {
   };
 };
 
+ftms = {
+  // Unofficial macro for <chrono> subset supported for freestanding.
+  // This excludes Clock::now() functions and everything that depends on tzdb.
+  name = freestanding_chrono;
+  values = {
+    v = 202306;
+    cxxmin = 26;
+    no_stdname = yes;
+  };
+  values = {
+    v = 201907;
+    cxxmin = 20;
+    no_stdname = yes;
+  };
+  values = {
+    v = 201611;
+    cxxmin = 17;
+    no_stdname = yes;
+  };
+};
+
 ftms = {
   name = execution;
   values = {
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index 2a12a69ed98b..3175bc1b65b4 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -713,6 +713,23 @@
 #endif /* !defined(__cpp_lib_chrono_cxx20) */
 #undef __glibcxx_want_chrono_cxx20
 
+#if !defined(__cpp_lib_freestanding_chrono)
+# if (__cplusplus >  202302L)
+#  define __glibcxx_freestanding_chrono 202306L
+#  if defined(__glibcxx_want_all) || 
defined(__glibcxx_want_freestanding_chrono)
+#  endif
+# elif (__cplusplus >= 202002L)
+#  define __glibcxx_freestanding_chrono 201907L
+#  if defined(__glibcxx_want_all) || 
defined(__glibcxx_want_freestanding_chrono)
+#  endif
+# elif (__cplusplus >= 201703L)
+#  define __glibcxx_freestanding_chrono 201611L
+#  if defined(__glibcxx_want_all) || 
defined(__glibcxx_want_freestanding_chrono)
+#  endif
+# endif
+#endif /* !defined(__cpp_lib_freestanding_chrono) */
+#undef __glibcxx_want_freestanding_chrono
+
 #if !defined(__cpp_lib_execution)
 # if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED
 #  define __glibcxx_execution 201902L
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index 2c020ff7a3a9..10e2830b66cf 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -54,6 +54,7 @@
 # include <bit> // __countr_zero
 #endif
 #ifdef __glibcxx_chrono_cxx20
+# include <string_view>
 # include <bits/stl_algo.h>     // upper_bound
 # include <bits/range_access.h> // begin/end for arrays
 #endif
@@ -96,7 +97,6 @@ _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;
@@ -153,10 +153,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using time_point                = chrono::time_point<utc_clock>;
       static constexpr bool is_steady = false;
 
+#if _GLIBCXX_HOSTED
       [[nodiscard]]
       static time_point
       now()
       { return from_sys(system_clock::now()); }
+#endif
 
       template<typename _Duration>
        [[nodiscard]]
@@ -192,9 +194,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using time_point                = chrono::time_point<tai_clock>;
       static constexpr bool is_steady = false;
 
+#if _GLIBCXX_HOSTED
       [[nodiscard]]
       static time_point
       now();  // in src/c++20/clock.cc
+#endif
 
       template<typename _Duration>
        [[nodiscard]]
@@ -230,9 +234,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using time_point                = chrono::time_point<gps_clock>;
       static constexpr bool is_steady = false;
 
+#if _GLIBCXX_HOSTED
       [[nodiscard]]
       static time_point
       now();  // in src/c++20/clock.cc
+#endif
 
       template<typename _Duration>
        [[nodiscard]]
@@ -252,7 +258,6 @@ _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
@@ -269,7 +274,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          { return __t; }
       };
 
-#if _GLIBCXX_HOSTED
     template<>
       struct clock_time_conversion<system_clock, system_clock>
       {
@@ -376,7 +380,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            return _DestClock::from_utc(__t);
          }
       };
-#endif // _GLIBCXX_HOSTED
 
     /// @cond undocumented
     namespace __detail
@@ -387,7 +390,6 @@ _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) {
@@ -417,7 +419,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
              clock_time_conversion<system_clock, utc_clock>{}(
                clock_time_conversion<utc_clock, _SourceClock>{}(__t)));
          };
-#endif // _GLIBCXX_HOSTED
     } // namespace __detail
     /// @endcond
 
@@ -427,12 +428,10 @@ _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>;
@@ -440,7 +439,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         {
           return clock_time_conversion<_DestClock, _SourceClock>{}(__t);
         }
-#if _GLIBCXX_HOSTED
        else
         {
           constexpr bool __convert_via_sys_clock
@@ -491,7 +489,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                 }
             }
         }
-#endif // _GLIBCXX_HOSTED
       }
 
     // CALENDRICAL TYPES
@@ -2528,10 +2525,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
     }
 
-#if _GLIBCXX_HOSTED
-#if __cpp_lib_chrono >= 201803L
     // C++20 [time.zones] Time zones
 
+    template<class _Tp> struct zoned_traits { };
+
+    enum class choose { earliest, latest };
+
+#if __cpp_lib_chrono >= 201803L // C++ >= 20 && HOSTED && USE_CXX11_ABI
     struct tzdb;
 
     struct sys_info
@@ -2622,8 +2622,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
     /// @endcond
 
-    enum class choose { earliest, latest };
-
     class time_zone
     {
     public:
@@ -2947,8 +2945,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       seconds _M_s; // == date().time_since_epoch() * value().count()
     };
 
-    template<class _Tp> struct zoned_traits { };
-
     template<>
       struct zoned_traits<const time_zone*>
       {
@@ -2987,6 +2983,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     string remote_version();
 
     template<typename _Duration, typename _TimeZonePtr = const time_zone*>
+      class zoned_time;
+#endif // __cpp_lib_chrono >= 201803L
+
+    template<typename _Duration, typename _TimeZonePtr>
       class zoned_time
       {
        static_assert(__is_duration_v<_Duration>);
@@ -3141,10 +3141,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        get_sys_time() const
        { return _M_tp; }
 
+#if __cpp_lib_chrono >= 201803L // C++ >= 20 && HOSTED && USE_CXX11_ABI
        [[nodiscard]]
        sys_info
        get_info() const
        { return _M_zone->get_info(_M_tp); }
+#endif
 
        [[nodiscard]] friend bool
        operator==(const zoned_time&, const zoned_time&) = default;
@@ -3157,6 +3159,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          friend class zoned_time;
       };
 
+#if __cpp_lib_chrono >= 201803L // C++ >= 20 && HOSTED && USE_CXX11_ABI
+
     zoned_time() -> zoned_time<seconds>;
 
     template<typename _Duration>
@@ -3193,6 +3197,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       -> zoned_time<common_type_t<_Duration, seconds>,
                     __time_zone_representation<_TimeZonePtrOrName>>;
 
+    using zoned_seconds = zoned_time<seconds>;
+
+#endif // __cpp_lib_chrono >= 201803L
+
   template<typename _Dur1, typename _TZPtr1, typename _Dur2, typename _TZPtr2>
     [[nodiscard]]
     inline bool
@@ -3203,9 +3211,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
               && __x.get_sys_time() == __y.get_sys_time();
     }
 
-    using zoned_seconds = zoned_time<seconds>;
-#endif // __cpp_lib_chrono >= 201803L
-
 namespace __detail
 {
     // This function is inline to support fast conversions between utc_time
@@ -3318,7 +3323,6 @@ 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
@@ -3585,7 +3589,6 @@ namespace __detail
       }
     };
 
-#if _GLIBCXX_HOSTED
 #if __cpp_lib_chrono >= 201803L
   // zoned_time
   template<typename _Duration, typename _TimeZonePtr>
@@ -3644,7 +3647,6 @@ namespace __detail
       }
     };
 #endif // __cpp_lib_chrono >= 201803L
-#endif // _GLIBCXX_HOSTED
 #endif // __glibcxx_chrono_cxx20 >= 202306
 
 #ifdef __glibcxx_chrono_cxx20
diff --git a/libstdc++-v3/testsuite/20_util/system_clock/1.cc 
b/libstdc++-v3/testsuite/20_util/system_clock/1.cc
index b0cb3a1ac59e..7541d501321b 100644
--- a/libstdc++-v3/testsuite/20_util/system_clock/1.cc
+++ b/libstdc++-v3/testsuite/20_util/system_clock/1.cc
@@ -28,12 +28,12 @@ main()
 {
   using namespace std::chrono;
 
-  system_clock::time_point t1 = system_clock::now();
-  bool is_steady = system_clock::is_steady;
-  is_steady = is_steady; // suppress unused warning
+  [[maybe_unused]] system_clock::time_point t1;
+#if __STDC_HOSTED__
+  t1 = system_clock::now();
   std::time_t t2 = system_clock::to_time_t(t1);
   system_clock::time_point t3 = system_clock::from_time_t(t2);
   t3 = t3; // suppress unused warning
-  
-  return 0;
+#endif
+  [[maybe_unused]] bool is_steady = system_clock::is_steady;
 }
diff --git a/libstdc++-v3/testsuite/20_util/system_clock/99832.cc 
b/libstdc++-v3/testsuite/20_util/system_clock/99832.cc
index 693d4d647d9b..7d32cecdcc11 100644
--- a/libstdc++-v3/testsuite/20_util/system_clock/99832.cc
+++ b/libstdc++-v3/testsuite/20_util/system_clock/99832.cc
@@ -1,5 +1,6 @@
 // { dg-options "-O0 -g0" }
 // { dg-do compile { target c++20 } }
+// { dg-require-effective-target hosted }
 // { dg-final { scan-assembler-not "system_clock9to_time_t" } }
 
 // Bug libstdc++/99832
diff --git 
a/libstdc++-v3/testsuite/20_util/time_point/comparison_operators/three_way.cc 
b/libstdc++-v3/testsuite/20_util/time_point/comparison_operators/three_way.cc
index 104c4b3bf118..e5c7d7522a03 100644
--- 
a/libstdc++-v3/testsuite/20_util/time_point/comparison_operators/three_way.cc
+++ 
b/libstdc++-v3/testsuite/20_util/time_point/comparison_operators/three_way.cc
@@ -27,7 +27,11 @@ test01()
 {
   using namespace std::chrono;
 
+#if __STDC_HOSTED__
   auto ns = system_clock::now();
+#else
+  auto ns = system_clock::time_point(12345s);
+#endif
   auto s = time_point_cast<seconds>(ns + seconds(2));
 
   VERIFY( s != ns );
diff --git a/libstdc++-v3/testsuite/std/time/clock/file/members.cc 
b/libstdc++-v3/testsuite/std/time/clock/file/members.cc
index a23d6b1f9d20..c37015139196 100644
--- a/libstdc++-v3/testsuite/std/time/clock/file/members.cc
+++ b/libstdc++-v3/testsuite/std/time/clock/file/members.cc
@@ -16,6 +16,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do run { target c++20 } }
+// { dg-require-effective-target hosted }
 
 #include <chrono>
 #include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/std/time/clock/file/overview.cc 
b/libstdc++-v3/testsuite/std/time/clock/file/overview.cc
index ac56e3d16aba..2d0482204f72 100644
--- a/libstdc++-v3/testsuite/std/time/clock/file/overview.cc
+++ b/libstdc++-v3/testsuite/std/time/clock/file/overview.cc
@@ -16,6 +16,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile { target c++20 } }
+// { dg-require-effective-target hosted }
 
 #include <chrono>
 
diff --git a/libstdc++-v3/testsuite/std/time/clock/gps/1.cc 
b/libstdc++-v3/testsuite/std/time/clock/gps/1.cc
index 8be517b316bb..95bdc504a8fe 100644
--- a/libstdc++-v3/testsuite/std/time/clock/gps/1.cc
+++ b/libstdc++-v3/testsuite/std/time/clock/gps/1.cc
@@ -33,6 +33,7 @@ test02()
 void
 test03()
 {
+#if __STDC_HOSTED__
   using namespace std::chrono;
 
   gps_time<gps_clock::duration> gps1 = gps_clock::now();
@@ -45,6 +46,7 @@ test03()
 
   gps_seconds s = time_point_cast<seconds>(gps1);
   VERIFY( gps1 - s < 1s );
+#endif
 }
 
 int main()
diff --git a/libstdc++-v3/testsuite/std/time/clock/tai/1.cc 
b/libstdc++-v3/testsuite/std/time/clock/tai/1.cc
index 63cc9927859e..8925d7624149 100644
--- a/libstdc++-v3/testsuite/std/time/clock/tai/1.cc
+++ b/libstdc++-v3/testsuite/std/time/clock/tai/1.cc
@@ -36,6 +36,7 @@ test02()
 void
 test03()
 {
+#if __STDC_HOSTED__
   using namespace std::chrono;
 
   tai_time<tai_clock::duration> tai1 = tai_clock::now();
@@ -48,6 +49,7 @@ test03()
 
   tai_seconds s = time_point_cast<seconds>(tai1);
   VERIFY( tai1 - s < 1s );
+#endif
 }
 
 int main()
diff --git a/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc 
b/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc
index 5b769d56af55..7e8c1f581ffd 100644
--- a/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc
+++ b/libstdc++-v3/testsuite/std/time/format/data_not_present_neg.cc
@@ -1,4 +1,5 @@
 // { dg-do compile { target c++20 } }
+// { dg-require-effective-target hosted }
 
 #include <chrono>
 #include <format>
diff --git a/libstdc++-v3/testsuite/std/time/format/pr120114.cc 
b/libstdc++-v3/testsuite/std/time/format/pr120114.cc
index cdde4685eda6..c9ec16904079 100644
--- a/libstdc++-v3/testsuite/std/time/format/pr120114.cc
+++ b/libstdc++-v3/testsuite/std/time/format/pr120114.cc
@@ -1,6 +1,7 @@
 // { dg-do run { target c++23 } }
 // { dg-options "-fexec-charset=UTF-8" }
 // { dg-timeout-factor 2 }
+// { dg-require-effective-target hosted }
 
 #include <algorithm>
 #include <chrono>
diff --git a/libstdc++-v3/testsuite/std/time/format/pr120481.cc 
b/libstdc++-v3/testsuite/std/time/format/pr120481.cc
index a748acb59a9b..e7bd2108e273 100644
--- a/libstdc++-v3/testsuite/std/time/format/pr120481.cc
+++ b/libstdc++-v3/testsuite/std/time/format/pr120481.cc
@@ -1,6 +1,7 @@
 // { dg-do run { target c++23 } }
 // { dg-options "-fexec-charset=UTF-8" }
 // { dg-timeout-factor 2 }
+// { dg-require-effective-target hosted }
 
 #include <algorithm>
 #include <chrono>
diff --git a/libstdc++-v3/testsuite/std/time/format/precision.cc 
b/libstdc++-v3/testsuite/std/time/format/precision.cc
index aa266156c1ff..5425d671199d 100644
--- a/libstdc++-v3/testsuite/std/time/format/precision.cc
+++ b/libstdc++-v3/testsuite/std/time/format/precision.cc
@@ -1,4 +1,5 @@
 // { dg-do run { target c++20 } }
+// { dg-require-effective-target hosted }
 
 #include <chrono>
 #include <ranges>
diff --git a/libstdc++-v3/testsuite/std/time/format/whitespace.cc 
b/libstdc++-v3/testsuite/std/time/format/whitespace.cc
index 9637886aae5b..cd5a2840c31b 100644
--- a/libstdc++-v3/testsuite/std/time/format/whitespace.cc
+++ b/libstdc++-v3/testsuite/std/time/format/whitespace.cc
@@ -1,4 +1,5 @@
 // { dg-do run { target c++20 } }
+// { dg-require-effective-target hosted }
 
 #include <chrono>
 #include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/std/time/syn_c++20.cc 
b/libstdc++-v3/testsuite/std/time/syn_c++20.cc
index 62abbc52ad2f..59bb38a01fb3 100644
--- a/libstdc++-v3/testsuite/std/time/syn_c++20.cc
+++ b/libstdc++-v3/testsuite/std/time/syn_c++20.cc
@@ -27,12 +27,25 @@
 # define EXPECTED_VALUE 201611L
 #endif
 
+#if __STDC_HOSTED__
+
 #ifndef __cpp_lib_chrono
 # error "Feature test macro for chrono is missing in <chrono>"
 #elif __cpp_lib_chrono < EXPECTED_VALUE
 # error "Feature test macro for chrono has wrong value in <chrono>"
 #endif
 
+#else // __cpp_lib_chrono is not defined for freestanding
+
+#ifndef __glibcxx_freestanding_chrono
+# error "Feature test macro for freestanding chrono is missing in <chrono>"
+#elif __glibcxx_freestanding_chrono < EXPECTED_VALUE
+# error "Feature test macro for chrono has wrong value in <chrono>"
+#endif
+
+#endif
+
+
 namespace __gnu_test
 {
   // Check for the new additions to <chrono> in C++20
@@ -64,8 +77,10 @@ namespace __gnu_test
   using std::chrono::gps_time;
   using std::chrono::gps_seconds;
 
+#if __STDC_HOSTED__ // no file_clock in freestanding
   using std::chrono::file_clock;
   using std::chrono::file_time;
+#endif
 
   using std::chrono::local_t;
   using std::chrono::local_time;
@@ -101,7 +116,7 @@ namespace __gnu_test
   using std::chrono::make12;
   using std::chrono::make24;
 
-#if __cpp_lib_chrono >= 201803L
+#if __cpp_lib_chrono >= 201803L // full C++20 tzdb support
   using std::chrono::tzdb;
   using std::chrono::tzdb_list;
   using std::chrono::get_tzdb;
@@ -130,10 +145,12 @@ namespace __gnu_test
   using std::chrono::time_zone_link;
 #endif
 
+#if __STDC_HOSTED__ // no chrono I/O in freestanding
   using std::chrono::local_time_format;
 
   using std::chrono::from_stream;
   using std::chrono::parse;
+#endif
 
   using std::chrono::last;
   using std::chrono::Sunday;
@@ -197,6 +214,8 @@ namespace __gnu_test
   static_assert( is_time_point<local_seconds> );
   static_assert( is_time_point<local_days> );
 
+#if __STDC_HOSTED__ // no file_clock in freestanding
   static_assert( std::is_class_v<file_clock> );
   static_assert( is_time_point<file_time<std::chrono::milliseconds>> );
+#endif
 }
diff --git a/libstdc++-v3/testsuite/std/time/time_zone/requirements.cc 
b/libstdc++-v3/testsuite/std/time/time_zone/requirements.cc
index 929fea2c0eb1..865a7caf917a 100644
--- a/libstdc++-v3/testsuite/std/time/time_zone/requirements.cc
+++ b/libstdc++-v3/testsuite/std/time/time_zone/requirements.cc
@@ -1,5 +1,5 @@
 // { dg-do compile { target c++20 } }
-// { dg-require-effective-target cxx11_abi }
+// { dg-require-effective-target tzdb }
 
 #include <chrono>
 
diff --git a/libstdc++-v3/testsuite/std/time/traits/is_clock.cc 
b/libstdc++-v3/testsuite/std/time/traits/is_clock.cc
index e52691c6f16d..81b16e9a3961 100644
--- a/libstdc++-v3/testsuite/std/time/traits/is_clock.cc
+++ b/libstdc++-v3/testsuite/std/time/traits/is_clock.cc
@@ -22,6 +22,7 @@
 
 namespace chrono = std::chrono;
 
+#if __cpp_lib_chrono >= 201803L
 static_assert( chrono::is_clock<chrono::system_clock>::value );
 static_assert( chrono::is_clock_v<chrono::system_clock> );
 
@@ -48,6 +49,7 @@ static_assert( 
chrono::is_clock_v<Clock<chrono::steady_clock>> );
 
 static_assert(chrono::is_clock<Clock<chrono::file_clock>>::value);
 static_assert(chrono::is_clock_v<Clock<chrono::file_clock>>);
+#endif
 
 static_assert( chrono::is_clock<__gnu_test::slow_clock>::value );
 static_assert( chrono::is_clock_v<__gnu_test::slow_clock> );
diff --git a/libstdc++-v3/testsuite/std/time/zoned_time/custom.cc 
b/libstdc++-v3/testsuite/std/time/zoned_time/custom.cc
index 83e1f6dca43d..572bed60d4a9 100644
--- a/libstdc++-v3/testsuite/std/time/zoned_time/custom.cc
+++ b/libstdc++-v3/testsuite/std/time/zoned_time/custom.cc
@@ -1,58 +1,94 @@
 // { dg-do run { target c++20 } }
-// { dg-require-effective-target tzdb }
 
 #include <chrono>
 #include <set>
 #include <stdexcept>
 #include <testsuite_hooks.h>
 
+// Get the name of the current zone.
+std::string_view
+current_zone_name()
+{
+#if __cpp_lib_chrono >= 201803L // Full tzdb support
+  return std::chrono::current_zone()->name();
+#else // freestanding or old ABI
+  return "Freestanding/Zone";
+#endif
+}
+
+// Get the canonical name of a zone or link.
+std::string_view
+resolved_zone_name(std::string_view name)
+{
+#if __cpp_lib_chrono >= 201803L // Full tzdb support
+  return std::chrono::locate_zone(name)->name();
+#else // freestanding or old ABI
+  return name;
+#endif
+}
+
 struct local_tz
 {
-  local_tz() : name(std::chrono::current_zone()->name()) { }
+  local_tz() : name(current_zone_name()) { }
 
   explicit local_tz(std::string_view name) : name(name) { }
 
   template<typename Dur>
-    std::chrono::sys_time<Dur> to_sys(const std::chrono::local_time<Dur>& d)
-    { return std::chrono::locate_zone(name)->to_sys(d); }
+    std::chrono::sys_time<Dur> to_sys(const std::chrono::local_time<Dur>& tp)
+    {
+#if __cpp_lib_chrono >= 201803L // Full tzdb support
+      return std::chrono::locate_zone(name)->to_sys(tp);
+#else
+      return { tp.time_since_epoch() };
+#endif
+    }
 
   template<typename Dur>
-    std::chrono::sys_time<Dur> to_local(const std::chrono::sys_time<Dur>& d)
-    { return std::chrono::locate_zone(name)->to_sys(d); }
+    std::chrono::local_time<Dur> to_local(const std::chrono::sys_time<Dur>& tp)
+    {
+#if __cpp_lib_chrono >= 201803L // Full tzdb support
+      return std::chrono::locate_zone(name)->to_local(tp);
+#else
+      return { tp.time_since_epoch() };
+#endif
+    }
 
+#if __cpp_lib_chrono >= 201803L // Full tzdb support
   template<typename Dur>
-    std::chrono::sys_info get_info(const std::chrono::sys_time<Dur>& d)
-    { return std::chrono::locate_zone(name)->get_info(d); }
+    std::chrono::sys_info get_info(const std::chrono::sys_time<Dur>& tp)
+    { return std::chrono::locate_zone(name)->get_info(tp); }
+#endif
 
-  struct indirect_cmp
-  {
-    bool operator()(const local_tz* lhs, const local_tz* rhs) const
-    { return lhs->name < rhs->name; }
-  };
-
-  bool eq(const std::chrono::time_zone* tz) const noexcept
-  { return name == tz->name(); }
+  // Not part of the required API, used for testing below.
+  bool eq(std::string_view s) const { return s == name; }
 
 private:
   std::string_view name;
+
+  friend struct std::chrono::zoned_traits<const local_tz*>;
 };
 
 template<> struct std::chrono::zoned_traits<const local_tz*>
 {
-  static const local_tz* default_zone()
-  {
-    return locate_zone(std::chrono::current_zone()->name());
-  }
+  static const local_tz*
+  default_zone() { return locate_zone(current_zone_name()); }
 
-  static const local_tz* locate_zone(std::string_view name)
+  static const local_tz*
+  locate_zone(std::string_view name)
   {
-    static std::set<const local_tz*, local_tz::indirect_cmp> zones;
-    local_tz tz(name);
-    if (auto z = zones.find(&tz); z != zones.end())
-      return *z;
-    if (std::chrono::locate_zone(name))
-      return *zones.insert(new local_tz(tz)).first;
-    throw std::runtime_error("zone not found");
+#if __cpp_lib_chrono >= 201803L // Full tzdb support
+    if (!std::chrono::locate_zone(name))
+      throw std::runtime_error("zone not found");
+#endif
+
+    struct cmp
+    {
+      bool operator()(const local_tz& lhs, const local_tz& rhs) const
+      { return lhs.name < rhs.name; }
+    };
+    static std::set<local_tz, cmp> zones;
+
+    return &*zones.emplace(name).first;
   }
 };
 
@@ -62,10 +98,10 @@ test_custom_tzptr()
   using namespace std::chrono;
 
   zoned_time<seconds, const local_tz*> z;
-  VERIFY( z.get_time_zone()->eq(std::chrono::current_zone()) );
+  VERIFY( z.get_time_zone()->eq(current_zone_name()) );
 
   zoned_time<seconds, const local_tz*> z2(std::string_view("Europe/London"));
-  VERIFY( z2.get_time_zone()->eq(std::chrono::locate_zone("Europe/London")) );
+  VERIFY( z2.get_time_zone()->eq(resolved_zone_name("Europe/London")) );
 }
 
 int main()
diff --git a/libstdc++-v3/testsuite/std/time/zoned_time/req_neg.cc 
b/libstdc++-v3/testsuite/std/time/zoned_time/req_neg.cc
index 9950a1f8394d..95d95a59c07f 100644
--- a/libstdc++-v3/testsuite/std/time/zoned_time/req_neg.cc
+++ b/libstdc++-v3/testsuite/std/time/zoned_time/req_neg.cc
@@ -1,8 +1,9 @@
 // { dg-do compile { target c++20 } }
-// { dg-require-effective-target tzdb }
 
 #include <chrono>
 
-std::chrono::zoned_time<std::chrono::year> z; // { dg-error "here" }
+struct TZ; // custom zone so this works even for freestanding and old ABI
+
+std::chrono::zoned_time<std::chrono::year, const TZ*> z; // { dg-error "here" }
 // { dg-error "static assertion failed" "" { target *-*-* } 0 }
 // { dg-prune-output "common_type" }
diff --git a/libstdc++-v3/testsuite/util/slow_clock.h 
b/libstdc++-v3/testsuite/util/slow_clock.h
index f11a1a6410fc..a3138374fead 100644
--- a/libstdc++-v3/testsuite/util/slow_clock.h
+++ b/libstdc++-v3/testsuite/util/slow_clock.h
@@ -32,10 +32,14 @@ struct slow_clock
   using time_point = std::chrono::time_point<slow_clock, duration>;
   static constexpr bool is_steady = false;
 
-  static time_point now()
-  {
-    auto real = std::chrono::system_clock::now();
-    return time_point{real.time_since_epoch() / 3};
-  }
+  static time_point now();
 };
+
+#if _GLIBCXX_HOSTED
+inline slow_clock::time_point slow_clock::now()
+{
+  auto real = std::chrono::system_clock::now();
+  return time_point{real.time_since_epoch() / 3};
+}
+#endif
 }
-- 
2.56.0

Reply via email to