* include/std/chrono (chrono::days, chrono::weeks, chrono::years) (chrono::months, chrono::sys_days, chrono::local_t) (chrono::local_time, chrono::local_seconds, chrono::local_days): Define for C++20. (chrono::time_point): Add missing static assert. * testsuite/20_util/time_point/requirements/duration_neg.cc: New test. * testsuite/std/time/clock/file/overview.cc: New test. * testsuite/std/time/clock/file/members.cc: New test. * testsuite/std/time/syn_c++20.cc: New test.
Tested powerpc64le-linux, committed to master.
commit 16948c54b7576fb4b27c59915eac71a0c6bf94f6 Author: Jonathan Wakely <jwak...@redhat.com> Date: Thu Mar 26 14:00:12 2020 +0000 libstdc++: Add some C++20 additions to <chrono> * include/std/chrono (chrono::days, chrono::weeks, chrono::years) (chrono::months, chrono::sys_days, chrono::local_t) (chrono::local_time, chrono::local_seconds, chrono::local_days): Define for C++20. (chrono::time_point): Add missing static assert. * testsuite/20_util/time_point/requirements/duration_neg.cc: New test. * testsuite/std/time/clock/file/overview.cc: New test. * testsuite/std/time/clock/file/members.cc: New test. * testsuite/std/time/syn_c++20.cc: New test. diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono index b1fa5b83295..514926c5c05 100644 --- a/libstdc++-v3/include/std/chrono +++ b/libstdc++-v3/include/std/chrono @@ -709,22 +709,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif /// nanoseconds - typedef duration<_GLIBCXX_CHRONO_INT64_T, nano> nanoseconds; + using nanoseconds = duration<_GLIBCXX_CHRONO_INT64_T, nano>; /// microseconds - typedef duration<_GLIBCXX_CHRONO_INT64_T, micro> microseconds; + using microseconds = duration<_GLIBCXX_CHRONO_INT64_T, micro>; /// milliseconds - typedef duration<_GLIBCXX_CHRONO_INT64_T, milli> milliseconds; + using milliseconds = duration<_GLIBCXX_CHRONO_INT64_T, milli>; /// seconds - typedef duration<_GLIBCXX_CHRONO_INT64_T> seconds; + using seconds = duration<_GLIBCXX_CHRONO_INT64_T>; /// minutes - typedef duration<_GLIBCXX_CHRONO_INT64_T, ratio< 60>> minutes; + using minutes = duration<_GLIBCXX_CHRONO_INT64_T, ratio< 60>>; /// hours - typedef duration<_GLIBCXX_CHRONO_INT64_T, ratio<3600>> hours; + using hours = duration<_GLIBCXX_CHRONO_INT64_T, ratio<3600>>; + +#if __cplusplus > 201703L + /// days + using days = duration<_GLIBCXX_CHRONO_INT64_T, ratio<86400>>; + + /// weeks + using weeks = duration<_GLIBCXX_CHRONO_INT64_T, ratio<604800>>; + + /// years + using years = duration<_GLIBCXX_CHRONO_INT64_T, ratio<31556952>>; + + /// months + using months = duration<_GLIBCXX_CHRONO_INT64_T, ratio<2629746>>; +#endif // C++20 #undef _GLIBCXX_CHRONO_INT64_T @@ -732,9 +746,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Clock, typename _Dur> struct time_point { - typedef _Clock clock; - typedef _Dur duration; - typedef typename duration::rep rep; + static_assert(__is_duration<_Dur>::value, + "duration must be a specialization of std::chrono::duration"); + + typedef _Clock clock; + typedef _Dur duration; + typedef typename duration::rep rep; typedef typename duration::period period; constexpr time_point() : __d(duration::zero()) @@ -790,7 +807,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION time_point<_Clock, _ToDur>>::type time_point_cast(const time_point<_Clock, _Dur>& __t) { - typedef time_point<_Clock, _ToDur> __time_point; + typedef time_point<_Clock, _ToDur> __time_point; return __time_point(duration_cast<_ToDur>(__t.time_since_epoch())); } @@ -837,7 +854,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef duration<_Rep2, _Period2> __dur2; typedef typename common_type<_Dur1,__dur2>::type __ct; - typedef time_point<_Clock, __ct> __time_point; + typedef time_point<_Clock, __ct> __time_point; return __time_point(__lhs.time_since_epoch() + __rhs); } @@ -851,7 +868,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef duration<_Rep1, _Period1> __dur1; typedef typename common_type<__dur1,_Dur2>::type __ct; - typedef time_point<_Clock, __ct> __time_point; + typedef time_point<_Clock, __ct> __time_point; return __time_point(__rhs.time_since_epoch() + __lhs); } @@ -865,7 +882,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef duration<_Rep2, _Period2> __dur2; typedef typename common_type<_Dur1,__dur2>::type __ct; - typedef time_point<_Clock, __ct> __time_point; + typedef time_point<_Clock, __ct> __time_point; return __time_point(__lhs.time_since_epoch() -__rhs); } @@ -946,9 +963,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ struct system_clock { - typedef chrono::nanoseconds duration; - typedef duration::rep rep; - typedef duration::period period; + typedef chrono::nanoseconds duration; + typedef duration::rep rep; + typedef duration::period period; typedef chrono::time_point<system_clock, duration> time_point; static_assert(system_clock::duration::min() @@ -986,10 +1003,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ struct steady_clock { - typedef chrono::nanoseconds duration; - typedef duration::rep rep; - typedef duration::period period; - typedef chrono::time_point<steady_clock, duration> time_point; + typedef chrono::nanoseconds duration; + typedef duration::rep rep; + typedef duration::period period; + typedef chrono::time_point<steady_clock, duration> time_point; static constexpr bool is_steady = true; @@ -1014,6 +1031,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Duration> using sys_time = time_point<system_clock, _Duration>; using sys_seconds = sys_time<seconds>; + using sys_days = sys_time<days>; using file_clock = ::std::filesystem::__file_clock; @@ -1027,6 +1045,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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; + + struct local_t { }; + template<typename _Duration> + using local_time = time_point<local_t, _Duration>; + using local_seconds = local_time<seconds>; + using local_days = local_time<days>; #endif // C++20 // @} diff --git a/libstdc++-v3/testsuite/20_util/time_point/requirements/duration_neg.cc b/libstdc++-v3/testsuite/20_util/time_point/requirements/duration_neg.cc new file mode 100644 index 00000000000..5e3bc7f1a55 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/time_point/requirements/duration_neg.cc @@ -0,0 +1,32 @@ +// 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-do compile { target c++11 } } + +#include <chrono> + +namespace chrono = std::chrono; + +// A duration-like type +struct durayshun : chrono::seconds +{ + using duration::duration; + durayshun(chrono::seconds); +}; + +chrono::time_point<chrono::system_clock, durayshun> t; // { dg-error "here" } +// { dg-error "specialization of std::chrono::duration" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/std/time/clock/file/members.cc b/libstdc++-v3/testsuite/std/time/clock/file/members.cc new file mode 100644 index 00000000000..44ae717a6ee --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/clock/file/members.cc @@ -0,0 +1,39 @@ +// 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 run { target c++2a } } + +#include <chrono> +#include <testsuite_hooks.h> + +void +test01() +{ + auto sys_now = std::chrono::system_clock::now(); + auto file_now = std::chrono::file_clock::now(); + auto d1 = std::chrono::file_clock::to_sys(file_now) - sys_now; + VERIFY( d1 < std::chrono::seconds(1) ); + auto d2 = file_now - std::chrono::file_clock::from_sys(sys_now); + VERIFY( d2 == d1 ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/std/time/clock/file/overview.cc b/libstdc++-v3/testsuite/std/time/clock/file/overview.cc new file mode 100644 index 00000000000..3ca530dc249 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/clock/file/overview.cc @@ -0,0 +1,43 @@ +// 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> + +using std::chrono::file_clock; + +// Cpp17Clock requirements: + +// New type so that is_clock<file_clock> specialization isn't used. +struct C : file_clock { }; +static_assert( std::chrono::is_clock_v<C> ); + +// Cpp17TrivialClock requirements: + +// A trivial clock's rep must be a numeric type, which is true for +// libstdc++ because we use an integral type. +static_assert( std::is_integral_v<file_clock::rep> ); + +// We meet the recursive Cpp17TrivialClock requirement by using the same clock: +static_assert( std::is_same_v<file_clock::time_point::clock, file_clock> ); + +// chrono::file_clock requirements: + +static_assert( std::is_signed_v<file_clock::rep> ); +static_assert( noexcept(file_clock::now()) ); diff --git a/libstdc++-v3/testsuite/std/time/syn_c++20.cc b/libstdc++-v3/testsuite/std/time/syn_c++20.cc new file mode 100644 index 00000000000..5ea7a0f4280 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/syn_c++20.cc @@ -0,0 +1,199 @@ +// 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> + +#ifndef __cpp_lib_chrono +# error "Feature test macro for chrono is missing in <chrono>" +// FIXME +// #elif __cpp_lib_chrono < 201907L +// # error "Feature test macro for chrono has wrong value in <chrono>" +#endif + +namespace __gnu_test +{ + // Check for the new additions to <chrono> in C++20 + + using std::chrono::is_clock; + using std::chrono::is_clock_v; + + using std::chrono::days; + using std::chrono::weeks; + using std::chrono::years; + using std::chrono::months; + + using std::chrono::sys_time; + using std::chrono::sys_seconds; + using std::chrono::sys_days; + + // FIXME +#if 0 + using std::chrono::utc_clock; + using std::chrono::utc_time; + using std::chrono::utc_seconds; + + using std::chrono::leap_second_info; + using std::chrono::get_leap_second_info; + + using std::chrono::tai_clock; + using std::chrono::tai_time; + using std::chrono::tai_seconds; + + using std::chrono::gps_clock; + using std::chrono::gps_time; + using std::chrono::gps_seconds; +#endif + + using std::chrono::file_clock; + using std::chrono::file_time; + + using std::chrono::local_t; + using std::chrono::local_time; + using std::chrono::local_seconds; + using std::chrono::local_days; + + // FIXME +#if 0 + using std::chrono::clock_time_conversion; + using std::chrono::clock_cast; + + using std::chrono::last_spec; + + using std::chrono::day; + using std::chrono::month; + using std::chrono::year; + using std::chrono::weekday; + using std::chrono::weekday_indexed; + using std::chrono::weekday_last; + using std::chrono::month_day; + using std::chrono::month_day_last; + using std::chrono::month_weekday; + using std::chrono::month_weekday_last; + using std::chrono::year_month; + using std::chrono::year_month_day; + using std::chrono::year_month_day_last; + using std::chrono::year_month_weekday; + using std::chrono::year_month_weekday_last; + using std::chrono::year_month; + using std::chrono::year_month_day; + + using std::chrono::hh_mm_ss; + using std::chrono::is_am; + using std::chrono::is_pm; + using std::chrono::make12; + using std::chrono::make24; + + using std::chrono::tzdb; + using std::chrono::tzdb_list; + using std::chrono::get_tzdb; + using std::chrono::get_tzdb_list; + using std::chrono::locate_zone; + using std::chrono::current_zone; + + using std::chrono::reload_tzdb; + using std::chrono::remote_version; + + using std::chrono::nonexistent_local_time; + using std::chrono::ambiguous_local_time; + + using std::chrono::sys_info; + using std::chrono::local_info; + + using std::chrono::choose; + using std::chrono::time_zone; + + using std::chrono::zoned_traits; + using std::chrono::zoned_time; + using std::chrono::zoned_seconds; + + using std::chrono::leap_second; + + using std::chrono::time_zone_link; + + using std::chrono::local_time_format; + + using std::chrono::parse; + + using std::chrono::last; + using std::chrono::Sunday; + using std::chrono::Monday; + using std::chrono::Tuesday; + using std::chrono::Wednesday; + using std::chrono::Thursday; + using std::chrono::Friday; + using std::chrono::Saturday; + + using std::chrono::January; + using std::chrono::February; + using std::chrono::March; + using std::chrono::April; + using std::chrono::May; + using std::chrono::June; + using std::chrono::July; + using std::chrono::August; + using std::chrono::September; + using std::chrono::October; + using std::chrono::November; + using std::chrono::December; + + using std::chrono_literals::operator""d; + using std::chrono_literals::operator""y; +#endif + + template<typename> + constexpr bool is_duration = false; + template<typename R, typename P> + constexpr bool is_duration<std::chrono::duration<R, P>> = true; + + static_assert( is_duration<days> ); + static_assert( is_duration<weeks> ); + static_assert( is_duration<years> ); + static_assert( is_duration<months> ); + + template<typename D, typename P> + constexpr bool has_period = std::is_same_v<typename D::period, P>; + + using std::ratio; + using std::ratio_multiply; + using std::ratio_divide; + using std::chrono::hours; + static_assert( has_period<days, ratio_multiply<ratio<24>, hours::period>> ); + static_assert( has_period<weeks, ratio_multiply<ratio<7>, days::period>> ); + static_assert( has_period<years, + ratio_multiply<ratio<146097, 400>, days::period>> ); + static_assert( has_period<months, ratio_divide<years::period, ratio<12>>> ); + + template<typename> + constexpr bool is_time_point = false; + template<typename C, typename D> + constexpr bool is_time_point<std::chrono::time_point<C, D>> = true; + + static_assert( is_time_point<sys_time<std::chrono::milliseconds>> ); + static_assert( is_time_point<sys_seconds> ); + static_assert( is_time_point<sys_days> ); + + static_assert( std::is_class_v<local_t> ); + static_assert( is_time_point<local_time<std::chrono::milliseconds>> ); + static_assert( is_time_point<local_seconds> ); + static_assert( is_time_point<local_days> ); + + static_assert( std::is_class_v<file_clock> ); + static_assert( is_time_point<file_time<std::chrono::milliseconds>> ); +} diff --git a/libstdc++-v3/testsuite/std/time/traits/is_clock.cc b/libstdc++-v3/testsuite/std/time/traits/is_clock.cc index 85f118253c3..f5d449cd42a 100644 --- a/libstdc++-v3/testsuite/std/time/traits/is_clock.cc +++ b/libstdc++-v3/testsuite/std/time/traits/is_clock.cc @@ -35,9 +35,26 @@ 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>); +// Clock<xxx_clock> will not use the specialization of is_clock<xxx_clock> +template<typename C> struct Clock : C { }; + +static_assert( chrono::is_clock<Clock<chrono::system_clock>>::value ); +static_assert( chrono::is_clock_v<Clock<chrono::system_clock>> ); + +static_assert( chrono::is_clock<Clock<chrono::high_resolution_clock>>::value ); +static_assert( chrono::is_clock_v<Clock<chrono::high_resolution_clock>> ); + +static_assert( chrono::is_clock<Clock<chrono::steady_clock>>::value ); +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>>); + static_assert( chrono::is_clock<__gnu_test::slow_clock>::value ); static_assert( chrono::is_clock_v<__gnu_test::slow_clock> ); +// Negative tests + static_assert( ! chrono::is_clock<int>::value ); static_assert( ! chrono::is_clock_v<int> );