From bf1fc37bb4a3cab851e2acec811427d5243a22e9 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 25 Mar 2020 22:07:02 +0000 Subject: [PATCH] libstdc++: Define and use chrono::is_clock for C++20 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 to , so that chrono::file_clock and chrono::file_time can be defined in 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. --- libstdc++-v3/ChangeLog | 40 +++++ libstdc++-v3/include/bits/fs_fwd.h | 42 ------ libstdc++-v3/include/std/chrono | 142 ++++++++++++++++++ libstdc++-v3/include/std/condition_variable | 3 + libstdc++-v3/include/std/future | 3 + libstdc++-v3/include/std/mutex | 3 + libstdc++-v3/include/std/shared_mutex | 6 + libstdc++-v3/include/std/thread | 3 + .../condition_variable/members/2.cc | 2 + .../condition_variable/members/clock_neg.cc | 61 ++++++++ .../members/clock_neg.cc | 61 ++++++++ .../30_threads/future/members/clock_neg.cc | 59 ++++++++ .../recursive_timed_mutex/try_lock_until/3.cc | 2 +- .../try_lock_until/clock_neg.cc | 57 +++++++ .../shared_future/members/clock_neg.cc | 59 ++++++++ .../shared_lock/locking/clock_neg.cc | 59 ++++++++ .../try_lock_until/clock_neg.cc | 57 +++++++ .../timed_mutex/try_lock_until/3.cc | 2 +- .../timed_mutex/try_lock_until/4.cc | 2 +- .../timed_mutex/try_lock_until/clock_neg.cc | 57 +++++++ .../unique_lock/locking/clock_neg.cc | 59 ++++++++ .../testsuite/std/time/traits/is_clock.cc | 124 +++++++++++++++ libstdc++-v3/testsuite/util/slow_clock.h | 3 + 23 files changed, 861 insertions(+), 45 deletions(-) create mode 100644 libstdc++-v3/testsuite/30_threads/condition_variable/members/clock_neg.cc create mode 100644 libstdc++-v3/testsuite/30_threads/condition_variable_any/members/clock_neg.cc create mode 100644 libstdc++-v3/testsuite/30_threads/future/members/clock_neg.cc create mode 100644 libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/clock_neg.cc create mode 100644 libstdc++-v3/testsuite/30_threads/shared_future/members/clock_neg.cc create mode 100644 libstdc++-v3/testsuite/30_threads/shared_lock/locking/clock_neg.cc create mode 100644 libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc create mode 100644 libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc create mode 100644 libstdc++-v3/testsuite/30_threads/unique_lock/locking/clock_neg.cc create mode 100644 libstdc++-v3/testsuite/std/time/traits/is_clock.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7b9c30e3b64..95ac7c935c4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,43 @@ +2020-03-25 Jonathan Wakely + + * 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 PR libstdc++/93245 diff --git a/libstdc++-v3/include/bits/fs_fwd.h b/libstdc++-v3/include/bits/fs_fwd.h index 1d7495825d6..6363eca867c 100644 --- a/libstdc++-v3/include/bits/fs_fwd.h +++ b/libstdc++-v3/include/bits/fs_fwd.h @@ -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 - 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 - 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 diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono index 477d50854b0..b1fa5b83295 100644 --- a/libstdc++-v3/include/std/chrono +++ b/libstdc++-v3/include/std/chrono @@ -41,11 +41,18 @@ #include #include #include // for literals support. +#if __cplusplus > 201703L +# include +#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 + struct is_clock; + + template + inline constexpr bool is_clock_v = is_clock<_Tp>::value; + +#if __cpp_lib_concepts + template + struct is_clock : false_type + { }; + + template + 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; + { _Tp::now() } -> same_as; + requires same_as>; + requires same_as; + } + struct is_clock<_Tp> : true_type + { }; +#else + template + struct __is_clock_impl : false_type + { }; + + template + struct __is_clock_impl<_Tp, + void_t> + : __and_>, + is_same, + is_same, + is_same>::type + { }; + + template + 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 + using sys_time = time_point; + using sys_seconds = sys_time; + + using file_clock = ::std::filesystem::__file_clock; + + template + using file_time = time_point; + + template<> struct is_clock : true_type { }; + template<> struct is_clock : true_type { }; + template<> struct is_clock : true_type { }; + + template<> inline constexpr bool is_clock_v = true; + template<> inline constexpr bool is_clock_v = true; + template<> inline constexpr bool is_clock_v = 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 + static + chrono::file_time<_Dur> + from_sys(const chrono::sys_time<_Dur>& __t) noexcept + { return _S_from_sys(__t); } + + // For internal use only + template + 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 + 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 + 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 diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable index 5e98d1b0a6c..cc7f99f6921 100644 --- a/libstdc++-v3/include/std/condition_variable +++ b/libstdc++-v3/include/std/condition_variable @@ -131,6 +131,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION wait_until(unique_lock& __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; diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index 59aa981261b..97506a27e37 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -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) diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex index a4a8df07f03..12b7e548d17 100644 --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -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. diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex index 9b597e76299..414dce3a1b7 100644 --- a/libstdc++-v3/include/std/shared_mutex +++ b/libstdc++-v3/include/std/shared_mutex @@ -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. diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index 1f9c13ff7d1..e1bba0cb29b 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -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) { diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc index baa10375cf9..c671804b406 100644 --- a/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc +++ b/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc @@ -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 index 00000000000..11b540f58c8 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/condition_variable/members/clock_neg.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct clok +{ + // no clok::rep or clok::period defined + using duration = std::chrono::milliseconds; + using time_point = std::chrono::time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test01() +{ + std::mutex m; + std::unique_lock 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; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test02() +{ + std::mutex m; + std::unique_lock 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 index 00000000000..4302363f407 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/condition_variable_any/members/clock_neg.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct clok +{ + // no clok::rep or clok::period defined + using duration = std::chrono::milliseconds; + using time_point = std::chrono::time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test01() +{ + std::mutex m; + std::unique_lock 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; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test02() +{ + std::mutex m; + std::unique_lock 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 index 00000000000..a94d770fb62 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/future/members/clock_neg.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct clok +{ + // no clok::rep or clok::period defined + using duration = std::chrono::milliseconds; + using time_point = std::chrono::time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test01() +{ + std::promise p; + std::future 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; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test02() +{ + std::promise p; + std::future 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/recursive_timed_mutex/try_lock_until/3.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/3.cc index b85381de46c..120655ceb65 100644 --- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/3.cc +++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/3.cc @@ -72,5 +72,5 @@ int main() { test(); test(); - test(); + 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 index 00000000000..499e6675545 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/clock_neg.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct clok +{ + // no clok::rep or clok::period defined + using duration = std::chrono::milliseconds; + using time_point = std::chrono::time_point; + 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; + 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 index 00000000000..59f63cc1cf4 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_future/members/clock_neg.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct clok +{ + // no clok::rep or clok::period defined + using duration = std::chrono::milliseconds; + using time_point = std::chrono::time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test01() +{ + std::promise p; + std::shared_future 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; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test02() +{ + std::promise p; + std::shared_future 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 index 00000000000..9a21a88ed60 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_lock/locking/clock_neg.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct clok +{ + // no clok::rep or clok::period defined + using duration = std::chrono::milliseconds; + using time_point = std::chrono::time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test01() +{ + std::shared_timed_mutex m; + std::shared_lock 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; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test02() +{ + std::shared_timed_mutex m; + std::shared_lock 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 index 00000000000..23d4b9d9bbf --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct clok +{ + // no clok::rep or clok::period defined + using duration = std::chrono::milliseconds; + using time_point = std::chrono::time_point; + 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; + 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 } diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/3.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/3.cc index 32c84ef6286..ed5a6b0b8b7 100644 --- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/3.cc +++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/3.cc @@ -72,5 +72,5 @@ int main() { test(); test(); - test(); + test<__gnu_test::slow_clock>(); } diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/4.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/4.cc index 037e4086f97..a7a77d2294d 100644 --- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/4.cc +++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/4.cc @@ -64,5 +64,5 @@ int main() { test(); test(); - test(); + 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 index 00000000000..a9c0132d99b --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct clok +{ + // no clok::rep or clok::period defined + using duration = std::chrono::milliseconds; + using time_point = std::chrono::time_point; + 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; + 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 index 00000000000..c7ac9cdc466 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/clock_neg.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +struct clok +{ + // no clok::rep or clok::period defined + using duration = std::chrono::milliseconds; + using time_point = std::chrono::time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test01() +{ + std::timed_mutex m; + std::unique_lock 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; + static constexpr bool is_steady = false; + static time_point now(); +}; + +void +test02() +{ + std::recursive_timed_mutex m; + std::unique_lock 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 index 00000000000..85f118253c3 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/traits/is_clock.cc @@ -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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include +#include + +namespace chrono = std::chrono; + +static_assert( chrono::is_clock::value ); +static_assert( chrono::is_clock_v ); + +static_assert( chrono::is_clock::value ); +static_assert( chrono::is_clock_v ); + +static_assert( chrono::is_clock::value ); +static_assert( chrono::is_clock_v ); + +static_assert(chrono::is_clock::value); +static_assert(chrono::is_clock_v); + +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::value ); +static_assert( ! chrono::is_clock_v ); + +static_assert( ! chrono::is_clock::value ); +static_assert( ! chrono::is_clock_v ); + +struct not_a_clock_1 +{ + using rep = int; + using period = std::ratio<4, 2>; + using duration = chrono::duration; // different rep + using time_point = chrono::time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +static_assert( ! chrono::is_clock::value ); +static_assert( ! chrono::is_clock_v ); + +struct not_a_clock_2 +{ + using rep = int; + using period = int; // not a std::ratio + using duration = chrono::duration; + using time_point = chrono::time_point; + static constexpr bool is_steady = false; + static time_point now(); +}; + +static_assert( ! chrono::is_clock::value ); +static_assert( ! chrono::is_clock_v ); + +struct not_a_clock_3 +{ + using rep = int; + using period = std::ratio<1>; + using duration = chrono::duration; + // wrong duration: + using time_point = chrono::time_point>; + static constexpr bool is_steady = false; + static time_point now(); +}; + +static_assert( ! chrono::is_clock::value ); +static_assert( ! chrono::is_clock_v ); + +struct not_a_clock_4 +{ + using rep = int; + using period = std::ratio<1>; + using duration = chrono::duration; + using time_point = chrono::time_point; + static constexpr int is_steady = 0; // not a const bool + static time_point now(); +}; + +static_assert( ! chrono::is_clock::value ); +static_assert( ! chrono::is_clock_v ); + +struct not_a_clock_5 +{ + using rep = int; + using period = std::ratio<1>; + using duration = chrono::duration; + using time_point = chrono::time_point; + static constexpr bool is_steady = false; + static int now(); // wrong return type +}; + +static_assert( ! chrono::is_clock::value ); +static_assert( ! chrono::is_clock_v ); + +struct not_a_clock_6 +{ + using rep = int; + using period = std::ratio<1>; + using duration = chrono::duration; + using time_point = chrono::time_point; + const bool is_steady = false; // not static + static time_point now(); +}; + +static_assert( ! chrono::is_clock::value ); +static_assert( ! chrono::is_clock_v ); diff --git a/libstdc++-v3/testsuite/util/slow_clock.h b/libstdc++-v3/testsuite/util/slow_clock.h index bae734f76c8..d1f4bbba851 100644 --- a/libstdc++-v3/testsuite/util/slow_clock.h +++ b/libstdc++-v3/testsuite/util/slow_clock.h @@ -22,6 +22,8 @@ #include +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}; } }; +} -- 2.30.2