libstdc++: Define and use chrono::is_clock for C++20
authorJonathan Wakely <jwakely@redhat.com>
Wed, 25 Mar 2020 22:07:02 +0000 (22:07 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Wed, 25 Mar 2020 22:07:02 +0000 (22:07 +0000)
For C++20 the wait_until members of mutexes and condition variables are
required to be ill-formed if given a clock that doesn't meet the
requirements for a clock type. To implement that requirement this patch
adds static assertions using the chrono::is_clock trait, and defines
that trait.

To avoid expensive checks for the common cases, the trait (and
associated variable template) are explicitly specialized for the
standard clock types.

This also moves the filesystem::__file_clock type from <filesystem> to
<chrono>, so that chrono::file_clock and chrono::file_time can be
defined in <chrono> as required.

* include/bits/fs_fwd.h (filesystem::__file_clock): Move to ...
* include/std/chrono (filesystem::__file_clock): Here.
(filesystem::__file_clock::from_sys, filesystem::__file_clock::to_sys):
Define public member functions for C++20.
(is_clock, is_clock_v): Define traits for C++20.
* include/std/condition_variable (condition_variable::wait_until): Add
check for valid clock.
* include/std/future (_State_baseV2::wait_until): Likewise.
* include/std/mutex (__timed_mutex_impl::_M_try_lock_until): Likewise.
* include/std/shared_mutex (shared_timed_mutex::try_lock_shared_until):
Likewise.
* include/std/thread (this_thread::sleep_until): Likewise.
* testsuite/30_threads/condition_variable/members/2.cc: Qualify
slow_clock with new namespace.
* testsuite/30_threads/condition_variable/members/clock_neg.cc: New
test.
* testsuite/30_threads/condition_variable_any/members/clock_neg.cc:
New test.
* testsuite/30_threads/future/members/clock_neg.cc: New test.
* testsuite/30_threads/recursive_timed_mutex/try_lock_until/3.cc:
Qualify slow_clock with new namespace.
* testsuite/30_threads/recursive_timed_mutex/try_lock_until/
clock_neg.cc: New test.
* testsuite/30_threads/shared_future/members/clock_neg.cc: New
test.
* testsuite/30_threads/shared_lock/locking/clock_neg.cc: New test.
* testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc:
New test.
* testsuite/30_threads/timed_mutex/try_lock_until/3.cc: Qualify
slow_clock with new namespace.
* testsuite/30_threads/timed_mutex/try_lock_until/4.cc: Likewise.
* testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc: New
test.
* testsuite/30_threads/unique_lock/locking/clock_neg.cc: New test.
* testsuite/std/time/traits/is_clock.cc: New test.
* testsuite/util/slow_clock.h (slow_clock): Move to __gnu_test
namespace.

23 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/fs_fwd.h
libstdc++-v3/include/std/chrono
libstdc++-v3/include/std/condition_variable
libstdc++-v3/include/std/future
libstdc++-v3/include/std/mutex
libstdc++-v3/include/std/shared_mutex
libstdc++-v3/include/std/thread
libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc
libstdc++-v3/testsuite/30_threads/condition_variable/members/clock_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/condition_variable_any/members/clock_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/future/members/clock_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/3.cc
libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/clock_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/shared_future/members/clock_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/shared_lock/locking/clock_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/3.cc
libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/4.cc
libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/30_threads/unique_lock/locking/clock_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/traits/is_clock.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/slow_clock.h

index 7b9c30e3b642985fd8cfce1930c3b504c07df7da..95ac7c935c4a8e12659035b970f7a21c3b6e8ef6 100644 (file)
@@ -1,3 +1,43 @@
+2020-03-25  Jonathan Wakely  <jwakely@redhat.com>
+
+       * include/bits/fs_fwd.h (filesystem::__file_clock): Move to ...
+       * include/std/chrono (filesystem::__file_clock): Here.
+       (filesystem::__file_clock::from_sys, filesystem::__file_clock::to_sys):
+       Define public member functions for C++20.
+       (is_clock, is_clock_v): Define traits for C++20.
+       * include/std/condition_variable (condition_variable::wait_until): Add
+       check for valid clock.
+       * include/std/future (_State_baseV2::wait_until): Likewise.
+       * include/std/mutex (__timed_mutex_impl::_M_try_lock_until): Likewise.
+       * include/std/shared_mutex (shared_timed_mutex::try_lock_shared_until):
+       Likewise.
+       * include/std/thread (this_thread::sleep_until): Likewise.
+       * testsuite/30_threads/condition_variable/members/2.cc: Qualify
+       slow_clock with new namespace.
+       * testsuite/30_threads/condition_variable/members/clock_neg.cc: New
+       test.
+       * testsuite/30_threads/condition_variable_any/members/clock_neg.cc:
+       New test.
+       * testsuite/30_threads/future/members/clock_neg.cc: New test.
+       * testsuite/30_threads/recursive_timed_mutex/try_lock_until/3.cc:
+       Qualify slow_clock with new namespace.
+       * testsuite/30_threads/recursive_timed_mutex/try_lock_until/
+       clock_neg.cc: New test.
+       * testsuite/30_threads/shared_future/members/clock_neg.cc: New
+       test.
+       * testsuite/30_threads/shared_lock/locking/clock_neg.cc: New test.
+       * testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc:
+       New test.
+       * testsuite/30_threads/timed_mutex/try_lock_until/3.cc: Qualify
+       slow_clock with new namespace.
+       * testsuite/30_threads/timed_mutex/try_lock_until/4.cc: Likewise.
+       * testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc: New
+       test.
+       * testsuite/30_threads/unique_lock/locking/clock_neg.cc: New test.
+       * testsuite/std/time/traits/is_clock.cc: New test.
+       * testsuite/util/slow_clock.h (slow_clock): Move to __gnu_test
+       namespace.
+
 2020-03-21  Jonathan Wakely  <jwakely@redhat.com>
 
        PR libstdc++/93245
index 1d7495825d6d2778cda61e53655344776a777699..6363eca867c22355d62ade980051096269afe91d 100644 (file)
@@ -291,48 +291,6 @@ _GLIBCXX_END_NAMESPACE_CXX11
   operator^=(directory_options& __x, directory_options __y) noexcept
   { return __x = __x ^ __y; }
 
-  struct __file_clock
-  {
-    using duration                  = chrono::nanoseconds;
-    using rep                       = duration::rep;
-    using period                    = duration::period;
-    using time_point                = chrono::time_point<__file_clock>;
-    static constexpr bool is_steady = false;
-
-    static time_point
-    now() noexcept
-    { return _S_from_sys(chrono::system_clock::now()); }
-
-  private:
-    using __sys_clock = chrono::system_clock;
-
-    // This clock's (unspecified) epoch is 2174-01-01 00:00:00 UTC.
-    // A signed 64-bit duration with nanosecond resolution gives roughly
-    // +/- 292 years, which covers the 1901-2446 date range for ext4.
-    static constexpr chrono::seconds _S_epoch_diff{6437664000};
-
-  protected:
-    // For internal use only
-    template<typename _Dur>
-      static
-      chrono::time_point<__file_clock, _Dur>
-      _S_from_sys(const chrono::time_point<__sys_clock, _Dur>& __t) noexcept
-      {
-       using __file_time = chrono::time_point<__file_clock, _Dur>;
-       return __file_time{__t.time_since_epoch()} - _S_epoch_diff;
-      }
-
-    // For internal use only
-    template<typename _Dur>
-      static
-      chrono::time_point<__sys_clock, _Dur>
-      _S_to_sys(const chrono::time_point<__file_clock, _Dur>& __t) noexcept
-      {
-       using __sys_time = chrono::time_point<__sys_clock, _Dur>;
-       return __sys_time{__t.time_since_epoch()} + _S_epoch_diff;
-      }
-  };
-
   using file_time_type = __file_clock::time_point;
 
   // operational functions
index 477d50854b06575026bf117ac0b1e633c010b57b..b1fa5b832956d047e399749a6d332368286eaa81 100644 (file)
 #include <limits>
 #include <ctime>
 #include <bits/parse_numbers.h> // for literals support.
+#if __cplusplus > 201703L
+# include <concepts>
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+#if __cplusplus >= 201703L
+  namespace filesystem { struct __file_clock; };
+#endif
+
   /**
    * @defgroup chrono Time
    * @ingroup utilities
@@ -237,6 +244,60 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         treat_as_floating_point<_Rep>::value;
 #endif // C++17
 
+#if __cplusplus > 201703L
+    template<typename _Tp>
+      struct is_clock;
+
+    template<typename _Tp>
+      inline constexpr bool is_clock_v = is_clock<_Tp>::value;
+
+#if __cpp_lib_concepts
+    template<typename _Tp>
+      struct is_clock : false_type
+      { };
+
+    template<typename _Tp>
+      requires requires {
+       typename _Tp::rep;
+       typename _Tp::period;
+       typename _Tp::duration;
+       typename _Tp::time_point::clock;
+       typename _Tp::time_point::duration;
+       { &_Tp::is_steady } -> same_as<const bool*>;
+       { _Tp::now() } -> same_as<typename _Tp::time_point>;
+       requires same_as<typename _Tp::duration,
+                        duration<typename _Tp::rep, typename _Tp::period>>;
+       requires same_as<typename _Tp::time_point::duration,
+                        typename _Tp::duration>;
+      }
+      struct is_clock<_Tp> : true_type
+      { };
+#else
+    template<typename _Tp, typename = void>
+      struct __is_clock_impl : false_type
+      { };
+
+    template<typename _Tp>
+      struct __is_clock_impl<_Tp,
+                            void_t<typename _Tp::rep, typename _Tp::period,
+                                   typename _Tp::duration,
+                                   typename _Tp::time_point::duration,
+                                   decltype(_Tp::is_steady),
+                                   decltype(_Tp::now())>>
+      : __and_<is_same<typename _Tp::duration,
+                      duration<typename _Tp::rep, typename _Tp::period>>,
+              is_same<typename _Tp::time_point::duration,
+                      typename _Tp::duration>,
+              is_same<decltype(&_Tp::is_steady), const bool*>,
+              is_same<decltype(_Tp::now()), typename _Tp::time_point>>::type
+      { };
+
+    template<typename _Tp>
+      struct is_clock : __is_clock_impl<_Tp>::type
+      { };
+#endif
+#endif // C++20
+
 #if __cplusplus >= 201703L
 # define __cpp_lib_chrono 201611
 
@@ -948,6 +1009,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     using high_resolution_clock = system_clock;
 
     } // end inline namespace _V2
+
+#if __cplusplus > 201703L
+    template<typename _Duration>
+      using sys_time = time_point<system_clock, _Duration>;
+    using sys_seconds = sys_time<seconds>;
+
+    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 // C++20
+
     // @}
   } // namespace chrono
 
@@ -1071,6 +1152,67 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     using namespace literals::chrono_literals;
   } // namespace chrono
 
+#if __cplusplus >= 201703L
+  namespace filesystem
+  {
+    struct __file_clock
+    {
+      using duration                  = chrono::nanoseconds;
+      using rep                       = duration::rep;
+      using period                    = duration::period;
+      using time_point                = chrono::time_point<__file_clock>;
+      static constexpr bool is_steady = false;
+
+      static time_point
+      now() noexcept
+      { return _S_from_sys(chrono::system_clock::now()); }
+
+#if __cplusplus > 201703L
+      template<typename _Dur>
+       static
+       chrono::file_time<_Dur>
+       from_sys(const chrono::sys_time<_Dur>& __t) noexcept
+       { return _S_from_sys(__t); }
+
+      // For internal use only
+      template<typename _Dur>
+       static
+       chrono::sys_time<_Dur>
+       to_sys(const chrono::file_time<_Dur>& __t) noexcept
+       { return _S_to_sys(__t); }
+#endif // C++20
+
+    private:
+      using __sys_clock = chrono::system_clock;
+
+      // This clock's (unspecified) epoch is 2174-01-01 00:00:00 UTC.
+      // A signed 64-bit duration with nanosecond resolution gives roughly
+      // +/- 292 years, which covers the 1901-2446 date range for ext4.
+      static constexpr chrono::seconds _S_epoch_diff{6437664000};
+
+    protected:
+      // For internal use only
+      template<typename _Dur>
+       static
+       chrono::time_point<__file_clock, _Dur>
+       _S_from_sys(const chrono::time_point<__sys_clock, _Dur>& __t) noexcept
+       {
+         using __file_time = chrono::time_point<__file_clock, _Dur>;
+         return __file_time{__t.time_since_epoch()} - _S_epoch_diff;
+       }
+
+      // For internal use only
+      template<typename _Dur>
+       static
+       chrono::time_point<__sys_clock, _Dur>
+       _S_to_sys(const chrono::time_point<__file_clock, _Dur>& __t) noexcept
+       {
+         using __sys_time = chrono::time_point<__sys_clock, _Dur>;
+         return __sys_time{__t.time_since_epoch()} + _S_epoch_diff;
+       }
+    };
+  } // namespace filesystem
+#endif // C++17
 #endif // C++14
 
 _GLIBCXX_END_NAMESPACE_VERSION
index 5e98d1b0a6c7ae6f9339c8719b543107e235c23c..cc7f99f6921d216ed6650e65fafcc1cf54e0115d 100644 (file)
@@ -131,6 +131,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       wait_until(unique_lock<mutex>& __lock,
                 const chrono::time_point<_Clock, _Duration>& __atime)
       {
+#if __cplusplus > 201703L
+       static_assert(chrono::is_clock_v<_Clock>);
+#endif
        const typename _Clock::time_point __c_entry = _Clock::now();
        const __clock_t::time_point __s_entry = __clock_t::now();
        const auto __delta = __atime - __c_entry;
index 59aa981261b2e2aa27e5212ebd5953dcadb9aa44..97506a27e37c821134c90de9dbd95d8360aff396 100644 (file)
@@ -371,6 +371,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         future_status
         wait_until(const chrono::time_point<_Clock, _Duration>& __abs)
         {
+#if __cplusplus > 201703L
+         static_assert(chrono::is_clock_v<_Clock>);
+#endif
          // First, check if the future has been made ready.  Use acquire MO
          // to synchronize with the thread that made it ready.
          if (_M_status._M_load(memory_order_acquire) == _Status::__ready)
index a4a8df07f037128bf6f41c0348f5c32139b5ab21..12b7e548d179c3a2cb0ed65b6e113031f11293f6 100644 (file)
@@ -189,6 +189,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        bool
        _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
        {
+#if __cplusplus > 201703L
+         static_assert(chrono::is_clock_v<_Clock>);
+#endif
          // The user-supplied clock may not tick at the same rate as
          // steady_clock, so we must loop in order to guarantee that
          // the timeout has expired before returning false.
index 9b597e762998e9df2190b3419a2c4faa6e8080a6..414dce3a1b7589511ed40275d484d498d1b4662f 100644 (file)
@@ -554,6 +554,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       bool
       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
       {
+#if __cplusplus > 201703L
+       static_assert(chrono::is_clock_v<_Clock>);
+#endif
        // The user-supplied clock may not tick at the same rate as
        // steady_clock, so we must loop in order to guarantee that
        // the timeout has expired before returning false.
@@ -639,6 +642,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       try_lock_shared_until(const chrono::time_point<_Clock,
                                                     _Duration>& __atime)
       {
+#if __cplusplus > 201703L
+       static_assert(chrono::is_clock_v<_Clock>);
+#endif
        // The user-supplied clock may not tick at the same rate as
        // steady_clock, so we must loop in order to guarantee that
        // the timeout has expired before returning false.
index 1f9c13ff7d1a7a7b807c97019ff4ef0f10498a85..e1bba0cb29b321d0d1e5a25861bdf415883005b5 100644 (file)
@@ -414,6 +414,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       inline void
       sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
       {
+#if __cplusplus > 201703L
+       static_assert(chrono::is_clock_v<_Clock>);
+#endif
        auto __now = _Clock::now();
        if (_Clock::is_steady)
          {
index baa10375cf9c916999c5a3a855904f9b960415c4..c671804b4064c50747b69086e37a576a535fc7f1 100644 (file)
@@ -55,6 +55,8 @@ void test01()
 
 void test01_alternate_clock()
 {
+  using __gnu_test::slow_clock;
+
   try
     {
       std::condition_variable c1;
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/members/clock_neg.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/members/clock_neg.cc
new file mode 100644 (file)
index 0000000..11b540f
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <condition_variable>
+
+struct clok
+{
+  // no clok::rep or clok::period defined
+  using duration = std::chrono::milliseconds;
+  using time_point = std::chrono::time_point<clok>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test01()
+{
+  std::mutex m;
+  std::unique_lock<std::mutex> l(m);
+  std::condition_variable cv;
+  cv.wait_until(l, clok::now()); // { dg-error "here" }
+}
+
+struct cloc
+{
+  using duration = std::chrono::milliseconds;
+  using rep = duration::rep;
+  using period = duration::period;
+  // cloc::time_point::duration should be the same as cloc::duration:
+  using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test02()
+{
+  std::mutex m;
+  std::unique_lock<std::mutex> l(m);
+  std::condition_variable cv;
+  cv.wait_until(l, cloc::now()); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/clock_neg.cc b/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/clock_neg.cc
new file mode 100644 (file)
index 0000000..4302363
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <condition_variable>
+
+struct clok
+{
+  // no clok::rep or clok::period defined
+  using duration = std::chrono::milliseconds;
+  using time_point = std::chrono::time_point<clok>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test01()
+{
+  std::mutex m;
+  std::unique_lock<std::mutex> l(m);
+  std::condition_variable_any cv;
+  cv.wait_until(l, clok::now()); // { dg-error "here" }
+}
+
+struct cloc
+{
+  using duration = std::chrono::milliseconds;
+  using rep = duration::rep;
+  using period = duration::period;
+  // cloc::time_point::duration should be the same as cloc::duration:
+  using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test02()
+{
+  std::mutex m;
+  std::unique_lock<std::mutex> l(m);
+  std::condition_variable_any cv;
+  cv.wait_until(l, cloc::now()); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/future/members/clock_neg.cc b/libstdc++-v3/testsuite/30_threads/future/members/clock_neg.cc
new file mode 100644 (file)
index 0000000..a94d770
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <future>
+
+struct clok
+{
+  // no clok::rep or clok::period defined
+  using duration = std::chrono::milliseconds;
+  using time_point = std::chrono::time_point<clok>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test01()
+{
+  std::promise<void> p;
+  std::future<void> f = p.get_future();
+  f.wait_until(clok::now()); // { dg-error "here" }
+}
+
+struct cloc
+{
+  using duration = std::chrono::milliseconds;
+  using rep = duration::rep;
+  using period = duration::period;
+  // cloc::time_point::duration should be the same as cloc::duration:
+  using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test02()
+{
+  std::promise<void> p;
+  std::future<void> f = p.get_future();
+  f.wait_until(cloc::now()); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
index b85381de46c5dd4a8bf3874c6b4d032fa6f01d01..120655ceb65084c771d663f8967421500093ef9f 100644 (file)
@@ -72,5 +72,5 @@ int main()
 {
   test<std::chrono::system_clock>();
   test<std::chrono::steady_clock>();
-  test<slow_clock>();
+  test<__gnu_test::slow_clock>();
 }
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/clock_neg.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/clock_neg.cc
new file mode 100644 (file)
index 0000000..499e667
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <mutex>
+
+struct clok
+{
+  // no clok::rep or clok::period defined
+  using duration = std::chrono::milliseconds;
+  using time_point = std::chrono::time_point<clok>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test01()
+{
+  std::recursive_timed_mutex m;
+  m.try_lock_until(clok::now()); // { dg-error "here" }
+}
+
+struct cloc
+{
+  using duration = std::chrono::milliseconds;
+  using rep = duration::rep;
+  using period = duration::period;
+  // cloc::time_point::duration should be the same as cloc::duration:
+  using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test02()
+{
+  std::recursive_timed_mutex m;
+  m.try_lock_until(cloc::now()); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_future/members/clock_neg.cc b/libstdc++-v3/testsuite/30_threads/shared_future/members/clock_neg.cc
new file mode 100644 (file)
index 0000000..59f63cc
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <future>
+
+struct clok
+{
+  // no clok::rep or clok::period defined
+  using duration = std::chrono::milliseconds;
+  using time_point = std::chrono::time_point<clok>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test01()
+{
+  std::promise<void> p;
+  std::shared_future<void> f = p.get_future();
+  f.wait_until(clok::now()); // { dg-error "here" }
+}
+
+struct cloc
+{
+  using duration = std::chrono::milliseconds;
+  using rep = duration::rep;
+  using period = duration::period;
+  // cloc::time_point::duration should be the same as cloc::duration:
+  using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test02()
+{
+  std::promise<void> p;
+  std::shared_future<void> f = p.get_future();
+  f.wait_until(cloc::now()); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_lock/locking/clock_neg.cc b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/clock_neg.cc
new file mode 100644 (file)
index 0000000..9a21a88
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <shared_mutex>
+
+struct clok
+{
+  // no clok::rep or clok::period defined
+  using duration = std::chrono::milliseconds;
+  using time_point = std::chrono::time_point<clok>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test01()
+{
+  std::shared_timed_mutex m;
+  std::shared_lock<std::shared_timed_mutex> l(m, std::defer_lock);
+  l.try_lock_until(clok::now()); // { dg-error "here" }
+}
+
+struct cloc
+{
+  using duration = std::chrono::milliseconds;
+  using rep = duration::rep;
+  using period = duration::period;
+  // cloc::time_point::duration should be the same as cloc::duration:
+  using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test02()
+{
+  std::shared_timed_mutex m;
+  std::shared_lock<std::shared_timed_mutex> l(m, std::defer_lock);
+  l.try_lock_until(cloc::now()); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc
new file mode 100644 (file)
index 0000000..23d4b9d
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <shared_mutex>
+
+struct clok
+{
+  // no clok::rep or clok::period defined
+  using duration = std::chrono::milliseconds;
+  using time_point = std::chrono::time_point<clok>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test01()
+{
+  std::shared_timed_mutex m;
+  m.try_lock_until(clok::now()); // { dg-error "here" }
+}
+
+struct cloc
+{
+  using duration = std::chrono::milliseconds;
+  using rep = duration::rep;
+  using period = duration::period;
+  // cloc::time_point::duration should be the same as cloc::duration:
+  using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test02()
+{
+  std::shared_timed_mutex m;
+  m.try_lock_shared_until(cloc::now()); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
index 32c84ef62868a76dba6c96f6768126d4db0d5e50..ed5a6b0b8b7f9481fffb554547dee7130607e884 100644 (file)
@@ -72,5 +72,5 @@ int main()
 {
   test<std::chrono::system_clock>();
   test<std::chrono::steady_clock>();
-  test<slow_clock>();
+  test<__gnu_test::slow_clock>();
 }
index 037e4086f975a264dd534844b281462c45fd4c6d..a7a77d2294d48a0eb35b3b20a889d7b7bb639da4 100644 (file)
@@ -64,5 +64,5 @@ int main()
 {
   test<std::chrono::system_clock>();
   test<std::chrono::steady_clock>();
-  test<slow_clock>();
+  test<__gnu_test::slow_clock>();
 }
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc
new file mode 100644 (file)
index 0000000..a9c0132
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <mutex>
+
+struct clok
+{
+  // no clok::rep or clok::period defined
+  using duration = std::chrono::milliseconds;
+  using time_point = std::chrono::time_point<clok>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test01()
+{
+  std::timed_mutex m;
+  m.try_lock_until(clok::now()); // { dg-error "here" }
+}
+
+struct cloc
+{
+  using duration = std::chrono::milliseconds;
+  using rep = duration::rep;
+  using period = duration::period;
+  // cloc::time_point::duration should be the same as cloc::duration:
+  using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test02()
+{
+  std::timed_mutex m;
+  m.try_lock_until(cloc::now()); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/clock_neg.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/clock_neg.cc
new file mode 100644 (file)
index 0000000..c7ac9cd
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <mutex>
+
+struct clok
+{
+  // no clok::rep or clok::period defined
+  using duration = std::chrono::milliseconds;
+  using time_point = std::chrono::time_point<clok>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test01()
+{
+  std::timed_mutex m;
+  std::unique_lock<std::timed_mutex> l(m, std::defer_lock);
+  l.try_lock_until(clok::now()); // { dg-error "here" }
+}
+
+struct cloc
+{
+  using duration = std::chrono::milliseconds;
+  using rep = duration::rep;
+  using period = duration::period;
+  // cloc::time_point::duration should be the same as cloc::duration:
+  using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+void
+test02()
+{
+  std::recursive_timed_mutex m;
+  std::unique_lock<std::recursive_timed_mutex> l(m, std::defer_lock);
+  l.try_lock_until(cloc::now()); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/std/time/traits/is_clock.cc b/libstdc++-v3/testsuite/std/time/traits/is_clock.cc
new file mode 100644 (file)
index 0000000..85f1182
--- /dev/null
@@ -0,0 +1,124 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <chrono>
+#include <slow_clock.h>
+
+namespace chrono = std::chrono;
+
+static_assert( chrono::is_clock<chrono::system_clock>::value );
+static_assert( chrono::is_clock_v<chrono::system_clock> );
+
+static_assert( chrono::is_clock<chrono::high_resolution_clock>::value );
+static_assert( chrono::is_clock_v<chrono::high_resolution_clock> );
+
+static_assert( chrono::is_clock<chrono::steady_clock>::value );
+static_assert( chrono::is_clock_v<chrono::steady_clock> );
+
+static_assert(chrono::is_clock<chrono::file_clock>::value);
+static_assert(chrono::is_clock_v<chrono::file_clock>);
+
+static_assert( chrono::is_clock<__gnu_test::slow_clock>::value );
+static_assert( chrono::is_clock_v<__gnu_test::slow_clock> );
+
+static_assert( ! chrono::is_clock<int>::value );
+static_assert( ! chrono::is_clock_v<int> );
+
+static_assert( ! chrono::is_clock<void>::value );
+static_assert( ! chrono::is_clock_v<void> );
+
+struct not_a_clock_1
+{
+  using rep = int;
+  using period = std::ratio<4, 2>;
+  using duration = chrono::duration<long, period>; // different rep
+  using time_point = chrono::time_point<not_a_clock_1>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+static_assert( ! chrono::is_clock<not_a_clock_1>::value );
+static_assert( ! chrono::is_clock_v<not_a_clock_1> );
+
+struct not_a_clock_2
+{
+  using rep = int;
+  using period = int; // not a std::ratio
+  using duration = chrono::duration<rep>;
+  using time_point = chrono::time_point<not_a_clock_2>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+static_assert( ! chrono::is_clock<not_a_clock_2>::value );
+static_assert( ! chrono::is_clock_v<not_a_clock_2> );
+
+struct not_a_clock_3
+{
+  using rep = int;
+  using period = std::ratio<1>;
+  using duration = chrono::duration<rep>;
+  // wrong duration:
+  using time_point = chrono::time_point<not_a_clock_3, chrono::duration<long>>;
+  static constexpr bool is_steady = false;
+  static time_point now();
+};
+
+static_assert( ! chrono::is_clock<not_a_clock_3>::value );
+static_assert( ! chrono::is_clock_v<not_a_clock_3> );
+
+struct not_a_clock_4
+{
+  using rep = int;
+  using period = std::ratio<1>;
+  using duration = chrono::duration<rep>;
+  using time_point = chrono::time_point<not_a_clock_4>;
+  static constexpr int is_steady = 0; // not a const bool
+  static time_point now();
+};
+
+static_assert( ! chrono::is_clock<not_a_clock_4>::value );
+static_assert( ! chrono::is_clock_v<not_a_clock_4> );
+
+struct not_a_clock_5
+{
+  using rep = int;
+  using period = std::ratio<1>;
+  using duration = chrono::duration<rep>;
+  using time_point = chrono::time_point<not_a_clock_5>;
+  static constexpr bool is_steady = false;
+  static int now(); // wrong return type
+};
+
+static_assert( ! chrono::is_clock<not_a_clock_5>::value );
+static_assert( ! chrono::is_clock_v<not_a_clock_5> );
+
+struct not_a_clock_6
+{
+  using rep = int;
+  using period = std::ratio<1>;
+  using duration = chrono::duration<rep>;
+  using time_point = chrono::time_point<not_a_clock_6>;
+  const bool is_steady = false; // not static
+  static time_point now();
+};
+
+static_assert( ! chrono::is_clock<not_a_clock_6>::value );
+static_assert( ! chrono::is_clock_v<not_a_clock_6> );
index bae734f76c84cdf19eed12d4389b5a4cbacf83f4..d1f4bbba8514c813e4ac3efb31db76f88971cd15 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <chrono>
 
+namespace __gnu_test
+{
 struct slow_clock
 {
   using rep = std::chrono::system_clock::rep;
@@ -36,3 +38,4 @@ struct slow_clock
     return time_point{real.time_since_epoch() / 3};
   }
 };
+}