diff options
| author | Yuxuan Chen <ych@meta.com> | 2025-09-25 12:02:39 -0700 |
|---|---|---|
| committer | Yuxuan Chen <ych@meta.com> | 2025-09-25 14:16:42 -0700 |
| commit | 8a6adc0a8669719f275a4ff98d3688f6089dbe02 (patch) | |
| tree | 7de7ae9f63729dd251018dd0c199d51a93923d2d | |
| parent | 11329c13affdf825e68735ffaca67d462fbef585 (diff) | |
more strict checksusers/yuxuanchen1997/libcxx-is-clock-strict-checks
| -rw-r--r-- | libcxx/include/__chrono/is_clock.h | 27 | ||||
| -rw-r--r-- | libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp | 111 |
2 files changed, 137 insertions, 1 deletions
diff --git a/libcxx/include/__chrono/is_clock.h b/libcxx/include/__chrono/is_clock.h index da65788af8a3..75626628309e 100644 --- a/libcxx/include/__chrono/is_clock.h +++ b/libcxx/include/__chrono/is_clock.h @@ -12,6 +12,8 @@ #include <__config> #include <__type_traits/integral_constant.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_same.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,14 +25,39 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace chrono { +template <class _Rep, class _Period> +class duration; + +template <class _Clock, class _Duration> +class time_point; + +template <class _TimePoint, class _Clock> +constexpr bool __is_valid_clock_time_point_v = false; + +template <class _Clock, class _Duration, class _ClockType> +constexpr bool __is_valid_clock_time_point_v<time_point<_Clock, _Duration>, _ClockType> = + _IsSame<_Clock, _ClockType>::value || _IsSame<_Duration, typename _ClockType::duration>::value; + +// Check if a clock satisfies the Cpp17Clock requirements as defined in [time.clock.req] template <class _Tp> _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_clock_v = requires { typename _Tp::rep; + requires is_arithmetic_v<typename _Tp::rep>; + typename _Tp::period; + requires __is_ratio_v<typename _Tp::period>; + typename _Tp::duration; + requires _IsSame<typename _Tp::duration, duration<typename _Tp::rep, typename _Tp::period>>::value; + typename _Tp::time_point; + requires __is_valid_clock_time_point_v<typename _Tp::time_point, _Tp>; + _Tp::is_steady; + requires _IsSame<decltype(_Tp::is_steady), const bool>::value; + _Tp::now(); + requires _IsSame<decltype(_Tp::now()), typename _Tp::time_point>::value; }; template <class _Tp> diff --git a/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp b/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp index 78473808a00e..f6e73bd288d0 100644 --- a/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp +++ b/libcxx/test/std/time/time.traits.is.clock/trait.is.clock.compile.pass.cpp @@ -72,7 +72,7 @@ struct ValidSteadyClock { }; struct ValidSystemClock { - using rep = int64_t; + using rep = long long; using period = std::micro; using duration = std::chrono::microseconds; using time_point = std::chrono::time_point<ValidSystemClock>; @@ -80,6 +80,94 @@ struct ValidSystemClock { static time_point now(); }; +// Test clocks with invalid is_steady type +struct WrongIsSteadyType { + using rep = long; + using period = std::ratio<1>; + using duration = std::chrono::seconds; + using time_point = std::chrono::time_point<WrongIsSteadyType>; + static bool is_steady; // Not const bool + static time_point now(); +}; + +struct WrongIsSteadyNonBool { + using rep = long; + using period = std::ratio<1>; + using duration = std::chrono::seconds; + using time_point = std::chrono::time_point<WrongIsSteadyNonBool>; + static constexpr int is_steady = 1; // Not bool + static time_point now(); +}; + +// Test clocks with invalid now() return type +struct WrongNowReturnType { + using rep = long; + using period = std::ratio<1>; + using duration = std::chrono::seconds; + using time_point = std::chrono::time_point<WrongNowReturnType>; + static constexpr bool is_steady = false; + static int now(); // Wrong return type +}; + +// Test clocks with invalid period type +struct WrongPeriodType { + using rep = long; + using period = int; // Not a ratio + using duration = std::chrono::seconds; + using time_point = std::chrono::time_point<WrongPeriodType>; + static constexpr bool is_steady = false; + static time_point now(); +}; + +// Test clocks with invalid rep type (neither arithmetic nor numeric_limits specialized) +struct InvalidRepType { + using rep = EmptyStruct; // Not arithmetic, no numeric_limits specialization + using period = std::ratio<1>; + using duration = std::chrono::duration<EmptyStruct>; + using time_point = std::chrono::time_point<InvalidRepType, duration>; + static constexpr bool is_steady = false; + static time_point now(); +}; + +// Test clocks with wrong duration type +struct WrongDurationType { + using rep = long; + using period = std::ratio<1>; + using duration = std::chrono::milliseconds; // Should be duration<long, ratio<1>> + using time_point = std::chrono::time_point<WrongDurationType>; + static constexpr bool is_steady = false; + static time_point now(); +}; + +// Test clocks with wrong time_point type +struct WrongTimePointType { + using rep = long; + using period = std::ratio<1>; + using duration = std::chrono::duration<long, std::ratio<1>>; + using time_point = int; // Not a time_point + static constexpr bool is_steady = false; + static time_point now(); +}; + +struct WrongTimePointClock { + using rep = long; + using period = std::ratio<1>; + using duration = std::chrono::duration<long, std::ratio<1>>; + using time_point = std::chrono::time_point<ValidSystemClock>; // Wrong clock type + static constexpr bool is_steady = false; + static time_point now(); +}; + +// Valid clock with time_point that has matching duration instead of matching clock +struct ValidClockWithDurationMatch { + using rep = int; + using period = std::milli; + using duration = std::chrono::duration<int, std::milli>; + using time_point = std::chrono::time_point<ValidSystemClock, duration>; // Valid: matches duration + static constexpr bool is_steady = false; + static time_point now(); +}; + int main(int, char**) { // Test both is_clock and is_clock_v static_assert(std::chrono::is_clock<std::chrono::system_clock>::value); @@ -114,6 +202,27 @@ int main(int, char**) { // Test valid custom clocks static_assert(std::chrono::is_clock_v<ValidSteadyClock>); static_assert(std::chrono::is_clock_v<ValidSystemClock>); + static_assert(std::chrono::is_clock_v<ValidClockWithDurationMatch>); + + // Test clocks with invalid is_steady type + static_assert(!std::chrono::is_clock_v<WrongIsSteadyType>); // is_steady not const bool + static_assert(!std::chrono::is_clock_v<WrongIsSteadyNonBool>); // is_steady not bool type + + // Test clocks with invalid now() return type + static_assert(!std::chrono::is_clock_v<WrongNowReturnType>); // now() doesn't return time_point + + // Test clocks with invalid period type + static_assert(!std::chrono::is_clock_v<WrongPeriodType>); // period is not a ratio + + // Test clocks with invalid rep type + static_assert(!std::chrono::is_clock_v<InvalidRepType>); // rep is not arithmetic and no numeric_limits + + // Test clocks with wrong duration type + static_assert(!std::chrono::is_clock_v<WrongDurationType>); // duration doesn't match duration<rep, period> + + // Test clocks with wrong time_point type + static_assert(!std::chrono::is_clock_v<WrongTimePointType>); // time_point is not a time_point + static_assert(!std::chrono::is_clock_v<WrongTimePointClock>); // time_point has wrong clock and wrong duration // cv-qualified and reference types static_assert(std::chrono::is_clock_v<const std::chrono::system_clock>); |
