[libcxx-commits] [libcxx] ec7b637 - [libc++][chrono] P2592R3: Hashing for chrono (#165132)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 2 18:32:18 PST 2026


Author: Rafail Shakhin ogly
Date: 2026-01-03T10:32:14+08:00
New Revision: ec7b63771ca7ee74566156a075a5388a3b6fc7c2

URL: https://github.com/llvm/llvm-project/commit/ec7b63771ca7ee74566156a075a5388a3b6fc7c2
DIFF: https://github.com/llvm/llvm-project/commit/ec7b63771ca7ee74566156a075a5388a3b6fc7c2.diff

LOG: [libc++][chrono] P2592R3: Hashing for chrono (#165132)

Added: 
    libcxx/test/std/time/time.hash/time.hash_enabled.pass.cpp

Modified: 
    libcxx/docs/ReleaseNotes/22.rst
    libcxx/docs/Status/Cxx2cPapers.csv
    libcxx/include/__chrono/day.h
    libcxx/include/__chrono/duration.h
    libcxx/include/__chrono/leap_second.h
    libcxx/include/__chrono/month.h
    libcxx/include/__chrono/month_weekday.h
    libcxx/include/__chrono/monthday.h
    libcxx/include/__chrono/time_point.h
    libcxx/include/__chrono/weekday.h
    libcxx/include/__chrono/year.h
    libcxx/include/__chrono/year_month.h
    libcxx/include/__chrono/year_month_day.h
    libcxx/include/__chrono/year_month_weekday.h
    libcxx/include/__chrono/zoned_time.h
    libcxx/include/chrono
    libcxx/modules/std/chrono.inc
    libcxx/test/libcxx/transitive_includes/cxx23.csv
    libcxx/test/libcxx/transitive_includes/cxx26.csv

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 0d1a1fbc00f2c..3e2b3e6633bb1 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -38,6 +38,7 @@ What's New in Libc++ 22.0.0?
 Implemented Papers
 ------------------
 
+- P2592R3: Hashing support for ``std::chrono`` value classes (`Github <https://llvm.org/PR105358>`__)
 - P2321R2: ``zip`` (`Github <https://llvm.org/PR105169>`__) (The paper is partially implemented. ``zip_transform_view``,
   ``adjacent_view``, and ``adjacent_transform_view`` are implemented in this release)
 - P2988R12: ``std::optional<T&>`` (`Github <https://llvm.org/PR148131>`__)

diff  --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 9bb5d2bda3d4d..29642fc53cac6 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -1,6 +1,6 @@
 "Paper #","Paper Name","Meeting","Status","First released version","GitHub issue","Notes"
 "`P2497R0 <https://wg21.link/P2497R0>`__","Testing for success or failure of ``<charconv>`` functions","2023-06 (Varna)","|Complete|","18","`#105357 <https://github.com/llvm/llvm-project/issues/105357>`__",""
-"`P2592R3 <https://wg21.link/P2592R3>`__","Hashing support for ``std::chrono`` value classes","2023-06 (Varna)","","","`#105358 <https://github.com/llvm/llvm-project/issues/105358>`__",""
+"`P2592R3 <https://wg21.link/P2592R3>`__","Hashing support for ``std::chrono`` value classes","2023-06 (Varna)","|Complete|","22","`#105358 <https://github.com/llvm/llvm-project/issues/105358>`__",""
 "`P2587R3 <https://wg21.link/P2587R3>`__","``to_string`` or not ``to_string``","2023-06 (Varna)","","","`#105359 <https://github.com/llvm/llvm-project/issues/105359>`__",""
 "`P2562R1 <https://wg21.link/P2562R1>`__","``constexpr`` Stable Sorting","2023-06 (Varna)","|Complete|","21","`#105360 <https://github.com/llvm/llvm-project/issues/105360>`__",""
 "`P2545R4 <https://wg21.link/P2545R4>`__","Read-Copy Update (RCU)","2023-06 (Varna)","","","`#105361 <https://github.com/llvm/llvm-project/issues/105361>`__",""

diff  --git a/libcxx/include/__chrono/day.h b/libcxx/include/__chrono/day.h
index f5b14689a78ac..46822c599192d 100644
--- a/libcxx/include/__chrono/day.h
+++ b/libcxx/include/__chrono/day.h
@@ -13,6 +13,8 @@
 #include <__chrono/duration.h>
 #include <__compare/ordering.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -92,6 +94,15 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr day& day::operator-=(const days& __dd) no
 
 } // namespace chrono
 
+#  if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::day> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::day& __d) noexcept { return static_cast<unsigned>(__d); }
+};
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/include/__chrono/duration.h b/libcxx/include/__chrono/duration.h
index 57fa64d650068..01432bd3fa259 100644
--- a/libcxx/include/__chrono/duration.h
+++ b/libcxx/include/__chrono/duration.h
@@ -13,6 +13,8 @@
 #include <__compare/ordering.h>
 #include <__compare/three_way_comparable.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 #include <__type_traits/common_type.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_convertible.h>
@@ -538,6 +540,18 @@ using namespace literals::chrono_literals;
 
 #endif // _LIBCPP_STD_VER >= 14
 
+#if _LIBCPP_STD_VER >= 26
+
+template <class _Rep, class _Period>
+  requires __has_enabled_hash<_Rep>::value
+struct hash<chrono::duration<_Rep, _Period>> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::duration<_Rep, _Period>& __d) {
+    return hash<_Rep>{}(__d.count());
+  }
+};
+
+#endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS

diff  --git a/libcxx/include/__chrono/leap_second.h b/libcxx/include/__chrono/leap_second.h
index 1857bef80376e..665056e5a963e 100644
--- a/libcxx/include/__chrono/leap_second.h
+++ b/libcxx/include/__chrono/leap_second.h
@@ -22,6 +22,8 @@
 #  include <__compare/ordering.h>
 #  include <__compare/three_way_comparable.h>
 #  include <__config>
+#  include <__cstddef/size_t.h>
+#  include <__functional/hash.h>
 #  include <__utility/private_constructor_tag.h>
 
 #  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -122,6 +124,17 @@ class leap_second {
 
 } // namespace chrono
 
+#    if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::leap_second> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::leap_second& __lp) noexcept {
+    return std::__hash_combine(hash<chrono::sys_seconds>{}(__lp.date()), hash<chrono::seconds>{}(__lp.value()));
+  }
+};
+
+#    endif // _LIBCPP_STD_VER >= 26
+
 #  endif // _LIBCPP_STD_VER >= 20
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/__chrono/month.h b/libcxx/include/__chrono/month.h
index 77c67d0954efa..669ac66360ab6 100644
--- a/libcxx/include/__chrono/month.h
+++ b/libcxx/include/__chrono/month.h
@@ -13,6 +13,8 @@
 #include <__chrono/duration.h>
 #include <__compare/ordering.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -108,6 +110,17 @@ inline constexpr month December{12};
 
 } // namespace chrono
 
+#  if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::month> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month& __m) noexcept {
+    return static_cast<unsigned>(__m);
+  }
+};
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/include/__chrono/month_weekday.h b/libcxx/include/__chrono/month_weekday.h
index 7919879655214..edb7d386067d8 100644
--- a/libcxx/include/__chrono/month_weekday.h
+++ b/libcxx/include/__chrono/month_weekday.h
@@ -13,6 +13,8 @@
 #include <__chrono/month.h>
 #include <__chrono/weekday.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -98,6 +100,26 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr month_weekday_last operator/(const weekda
 }
 } // namespace chrono
 
+#  if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::month_weekday> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month_weekday& __mw) noexcept {
+    return std::__hash_combine(
+        hash<chrono::month>{}(__mw.month()), hash<chrono::weekday_indexed>{}(__mw.weekday_indexed()));
+  }
+};
+
+template <>
+struct hash<chrono::month_weekday_last> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month_weekday_last& __mwl) noexcept {
+    return std::__hash_combine(
+        hash<chrono::month>{}(__mwl.month()), hash<chrono::weekday_last>{}(__mwl.weekday_last()));
+  }
+};
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/include/__chrono/monthday.h b/libcxx/include/__chrono/monthday.h
index 57712cf0b65a8..2a7262be09dc6 100644
--- a/libcxx/include/__chrono/monthday.h
+++ b/libcxx/include/__chrono/monthday.h
@@ -15,6 +15,8 @@
 #include <__chrono/month.h>
 #include <__compare/ordering.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -126,6 +128,24 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr month_day_last operator/(last_spec, int _
 
 } // namespace chrono
 
+#  if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::month_day> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month_day& __md) noexcept {
+    return std::__hash_combine(hash<chrono::month>{}(__md.month()), hash<chrono::day>{}(__md.day()));
+  }
+};
+
+template <>
+struct hash<chrono::month_day_last> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::month_day_last& __mdl) noexcept {
+    return hash<chrono::month>{}(__mdl.month());
+  }
+};
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/include/__chrono/time_point.h b/libcxx/include/__chrono/time_point.h
index bc2c7798a630b..438f065c1d99d 100644
--- a/libcxx/include/__chrono/time_point.h
+++ b/libcxx/include/__chrono/time_point.h
@@ -14,6 +14,8 @@
 #include <__compare/ordering.h>
 #include <__compare/three_way_comparable.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 #include <__type_traits/common_type.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_convertible.h>
@@ -224,6 +226,18 @@ operator-(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock,
 
 } // namespace chrono
 
+#if _LIBCPP_STD_VER >= 26
+
+template <class _Clock, class _Duration>
+  requires __has_enabled_hash<_Duration>::value
+struct hash<chrono::time_point<_Clock, _Duration>> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::time_point<_Clock, _Duration>& __tp) {
+    return hash<_Duration>{}(__tp.time_since_epoch());
+  }
+};
+
+#endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS

diff  --git a/libcxx/include/__chrono/weekday.h b/libcxx/include/__chrono/weekday.h
index 728cbb844633f..143803495dac8 100644
--- a/libcxx/include/__chrono/weekday.h
+++ b/libcxx/include/__chrono/weekday.h
@@ -15,6 +15,8 @@
 #include <__chrono/system_clock.h>
 #include <__chrono/time_point.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -160,6 +162,29 @@ inline constexpr weekday Saturday{6};
 
 } // namespace chrono
 
+#  if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::weekday> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::weekday& __w) noexcept { return __w.c_encoding(); }
+};
+
+template <>
+struct hash<chrono::weekday_indexed> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::weekday_indexed& __wi) noexcept {
+    return std::__hash_combine(hash<chrono::weekday>{}(__wi.weekday()), __wi.index());
+  }
+};
+
+template <>
+struct hash<chrono::weekday_last> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::weekday_last& __wl) noexcept {
+    return hash<chrono::weekday>{}(__wl.weekday());
+  }
+};
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/include/__chrono/year.h b/libcxx/include/__chrono/year.h
index 2ae5180cb8fc9..aaef38acd92f2 100644
--- a/libcxx/include/__chrono/year.h
+++ b/libcxx/include/__chrono/year.h
@@ -13,6 +13,8 @@
 #include <__chrono/duration.h>
 #include <__compare/ordering.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 #include <limits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -109,6 +111,15 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool year::ok() const noexcept {
 
 } // namespace chrono
 
+#  if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::year> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year& __y) noexcept { return static_cast<int>(__y); }
+};
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/include/__chrono/year_month.h b/libcxx/include/__chrono/year_month.h
index cf9234bdb4625..e36091c02161b 100644
--- a/libcxx/include/__chrono/year_month.h
+++ b/libcxx/include/__chrono/year_month.h
@@ -15,6 +15,8 @@
 #include <__chrono/year.h>
 #include <__compare/ordering.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -116,6 +118,17 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr year_month& year_month::operator-=(const
 
 } // namespace chrono
 
+#  if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::year_month> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month& __ym) noexcept {
+    return std::__hash_combine(hash<chrono::year>{}(__ym.year()), hash<chrono::month>{}(__ym.month()));
+  }
+};
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/include/__chrono/year_month_day.h b/libcxx/include/__chrono/year_month_day.h
index a0510a14f4ede..0a2aaedd60505 100644
--- a/libcxx/include/__chrono/year_month_day.h
+++ b/libcxx/include/__chrono/year_month_day.h
@@ -21,6 +21,8 @@
 #include <__chrono/year_month.h>
 #include <__compare/ordering.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 #include <limits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -330,6 +332,27 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool year_month_day::ok() const noexcept
 
 } // namespace chrono
 
+#  if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::year_month_day> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month_day& __ymd) noexcept {
+    return std::__hash_combine(
+        hash<chrono::year>{}(__ymd.year()),
+        std::__hash_combine(hash<chrono::month>{}(__ymd.month()), hash<chrono::day>{}(__ymd.day())));
+  }
+};
+
+template <>
+struct hash<chrono::year_month_day_last> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month_day_last& __ymdl) noexcept {
+    return std::__hash_combine(
+        hash<chrono::year>{}(__ymdl.year()), hash<chrono::month_day_last>{}(__ymdl.month_day_last()));
+  }
+};
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/include/__chrono/year_month_weekday.h b/libcxx/include/__chrono/year_month_weekday.h
index 0c3dd494c8787..6ed1e21fe97e5 100644
--- a/libcxx/include/__chrono/year_month_weekday.h
+++ b/libcxx/include/__chrono/year_month_weekday.h
@@ -22,6 +22,8 @@
 #include <__chrono/year_month.h>
 #include <__chrono/year_month_day.h>
 #include <__config>
+#include <__cstddef/size_t.h>
+#include <__functional/hash.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -280,6 +282,30 @@ year_month_weekday_last::operator-=(const years& __dy) noexcept {
 
 } // namespace chrono
 
+#  if _LIBCPP_STD_VER >= 26
+
+template <>
+struct hash<chrono::year_month_weekday> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month_weekday& __ymw) noexcept {
+    return std::__hash_combine(
+        hash<chrono::year>{}(__ymw.year()),
+        std::__hash_combine(
+            hash<chrono::month>{}(__ymw.month()), hash<chrono::weekday_indexed>{}(__ymw.weekday_indexed())));
+  }
+};
+
+template <>
+struct hash<chrono::year_month_weekday_last> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::year_month_weekday_last& __ymwl) noexcept {
+    return std::__hash_combine(
+        hash<chrono::year>{}(__ymwl.year()),
+        std::__hash_combine(
+            hash<chrono::month>{}(__ymwl.month()), hash<chrono::weekday_last>{}(__ymwl.weekday_last())));
+  }
+};
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 20

diff  --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h
index 8db687a422ab1..b8d33bb7f3ac7 100644
--- a/libcxx/include/__chrono/zoned_time.h
+++ b/libcxx/include/__chrono/zoned_time.h
@@ -24,6 +24,8 @@
 #  include <__chrono/tzdb_list.h>
 #  include <__concepts/constructible.h>
 #  include <__config>
+#  include <__cstddef/size_t.h>
+#  include <__functional/hash.h>
 #  include <__type_traits/common_type.h>
 #  include <__type_traits/conditional.h>
 #  include <__type_traits/remove_cvref.h>
@@ -216,6 +218,19 @@ operator==(const zoned_time<_Duration1, _TimeZonePtr>& __lhs, const zoned_time<_
 
 } // namespace chrono
 
+#    if _LIBCPP_STD_VER >= 26
+
+template <class _Duration, class _TimeZonePtr>
+  requires __has_enabled_hash<_Duration>::value && __has_enabled_hash<_TimeZonePtr>::value
+struct hash<chrono::zoned_time<_Duration, _TimeZonePtr>> {
+  _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::zoned_time<_Duration, _TimeZonePtr>& __zt) {
+    return std::__hash_combine(
+        hash<chrono::sys_time<_Duration>>{}(__zt.get_sys_time()), hash<_TimeZonePtr>{}(__zt.get_time_zone()));
+  }
+};
+
+#    endif // _LIBCPP_STD_VER >= 26
+
 #  endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM &&
          // _LIBCPP_HAS_LOCALIZATION
 

diff  --git a/libcxx/include/chrono b/libcxx/include/chrono
index aa4fc6218f962..abb678e111c73 100644
--- a/libcxx/include/chrono
+++ b/libcxx/include/chrono
@@ -1038,6 +1038,49 @@ constexpr chrono::year                                  operator ""y(unsigned lo
 }  // chrono_literals
 }  // literals
 
+namespace std {
+  template<class T>
+    struct hash;                                            // C++26
+  template<class Rep, class Period>
+    struct hash<chrono::duration<Rep, Period>>;             // C++26
+  template<class Clock, class Duration>
+    struct hash<chrono::time_point<Clock, Duration>>;       // C++26
+  template<>
+    struct hash<chrono::day>;                               // C++26
+  template<>
+    struct hash<chrono::month>;                             // C++26
+  template<>
+    struct hash<chrono::year>;                              // C++26
+  template<>
+    struct hash<chrono::weekday>;                           // C++26
+  template<>
+    struct hash<chrono::weekday_indexed>;                   // C++26
+  template<>
+    struct hash<chrono::weekday_last>;                      // C++26
+  template<>
+    struct hash<chrono::month_day>;                         // C++26
+  template<>
+    struct hash<chrono::month_day_last>;                    // C++26
+  template<>
+    struct hash<chrono::month_weekday>;                     // C++26
+  template<>
+    struct hash<chrono::month_weekday_last>;                // C++26
+  template<>
+    struct hash<chrono::year_month>;                        // C++26
+  template<>
+    struct hash<chrono::year_month_day>;                    // C++26
+  template<>
+    struct hash<chrono::year_month_day_last>;               // C++26
+  template<>
+    struct hash<chrono::year_month_weekday>;                // C++26
+  template<>
+    struct hash<chrono::year_month_weekday_last>;           // C++26
+  template<class Duration, class TimeZonePtr>
+    struct hash<chrono::zoned_time<Duration, TimeZonePtr>>; // C++26
+  template<>
+    struct hash<chrono::leap_second>;                       // C++26
+} // namespace std
+
 }  // std
 */
 

diff  --git a/libcxx/modules/std/chrono.inc b/libcxx/modules/std/chrono.inc
index db405d482bf9e..d771559d15107 100644
--- a/libcxx/modules/std/chrono.inc
+++ b/libcxx/modules/std/chrono.inc
@@ -284,6 +284,10 @@ export namespace std {
 
   } // namespace chrono
 
+#if _LIBCPP_STD_VER >= 26
+  using std::hash;
+#endif
+
 } // namespace std
 export namespace std::inline literals::inline chrono_literals {
   // [time.duration.literals], suffixes for duration literals

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index 506a020e03345..c5cc61f06678c 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -669,6 +669,7 @@ memory_resource cerrno
 memory_resource climits
 memory_resource compare
 memory_resource cstdint
+memory_resource cstring
 memory_resource ctime
 memory_resource limits
 memory_resource ratio
@@ -678,6 +679,7 @@ mutex cerrno
 mutex climits
 mutex compare
 mutex cstdint
+mutex cstring
 mutex ctime
 mutex limits
 mutex ratio
@@ -877,6 +879,7 @@ set version
 shared_mutex cerrno
 shared_mutex climits
 shared_mutex cstdint
+shared_mutex cstring
 shared_mutex ctime
 shared_mutex limits
 shared_mutex ratio

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index 0ee20d390b5d1..c11fb5ac10016 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -653,6 +653,7 @@ memory_resource cerrno
 memory_resource climits
 memory_resource compare
 memory_resource cstdint
+memory_resource cstring
 memory_resource ctime
 memory_resource limits
 memory_resource ratio
@@ -662,6 +663,7 @@ mutex cerrno
 mutex climits
 mutex compare
 mutex cstdint
+mutex cstring
 mutex ctime
 mutex limits
 mutex ratio
@@ -859,6 +861,7 @@ set version
 shared_mutex cerrno
 shared_mutex climits
 shared_mutex cstdint
+shared_mutex cstring
 shared_mutex ctime
 shared_mutex limits
 shared_mutex ratio

diff  --git a/libcxx/test/std/time/time.hash/time.hash_enabled.pass.cpp b/libcxx/test/std/time/time.hash/time.hash_enabled.pass.cpp
new file mode 100644
index 0000000000000..cac7fbda0fbb3
--- /dev/null
+++ b/libcxx/test/std/time/time.hash/time.hash_enabled.pass.cpp
@@ -0,0 +1,95 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <chrono>
+
+// Test that <chrono> provides all of the hash specializations.
+
+#include <chrono>
+#include <type_traits>
+#include "poisoned_hash_helper.h"
+#include "test_macros.h"
+
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::day>, std::chrono::day>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::month>, std::chrono::month>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::year>, std::chrono::year>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::weekday>, std::chrono::weekday>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::weekday_indexed>, std::chrono::weekday_indexed>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::weekday_last>, std::chrono::weekday_last>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::month_day>, std::chrono::month_day>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::month_day_last>, std::chrono::month_day_last>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::month_weekday>, std::chrono::month_weekday>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::month_weekday_last>, std::chrono::month_weekday_last>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::year_month>, std::chrono::year_month>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::year_month_day>, std::chrono::year_month_day>);
+static_assert(
+    std::is_nothrow_invocable_v<std::hash<std::chrono::year_month_day_last>, std::chrono::year_month_day_last>);
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::year_month_weekday>, std::chrono::year_month_weekday>);
+static_assert(
+    std::is_nothrow_invocable_v<std::hash<std::chrono::year_month_weekday_last>, std::chrono::year_month_weekday_last>);
+#ifndef TEST_HAS_NO_EXPERIMENTAL_TZDB
+static_assert(std::is_nothrow_invocable_v<std::hash<std::chrono::leap_second>, std::chrono::leap_second>);
+#endif // TEST_HAS_NO_EXPERIMENTAL_TZDB
+
+int main(int, char**) {
+  test_hash_enabled<std::chrono::nanoseconds>();
+  test_hash_enabled<std::chrono::microseconds>();
+  test_hash_enabled<std::chrono::milliseconds>();
+  test_hash_enabled<std::chrono::seconds>();
+  test_hash_enabled<std::chrono::minutes>();
+  test_hash_enabled<std::chrono::hours>();
+  test_hash_enabled<std::chrono::days>();
+  test_hash_enabled<std::chrono::weeks>();
+  test_hash_enabled<std::chrono::months>();
+  test_hash_enabled<std::chrono::years>();
+
+  test_hash_enabled<std::chrono::day>();
+  test_hash_enabled<std::chrono::month>();
+  test_hash_enabled<std::chrono::year>();
+
+  test_hash_enabled<std::chrono::weekday>();
+  test_hash_enabled<std::chrono::weekday_indexed>();
+  test_hash_enabled(std::chrono::weekday_last(std::chrono::weekday{}));
+
+  test_hash_enabled<std::chrono::month_day>();
+  test_hash_enabled(std::chrono::month_day_last(std::chrono::month{}));
+
+  test_hash_enabled(std::chrono::month_weekday(std::chrono::month{}, std::chrono::weekday_indexed{}));
+
+  test_hash_enabled(
+      std::chrono::month_weekday_last(std::chrono::month{}, std::chrono::weekday_last(std::chrono::weekday{})));
+
+  test_hash_enabled<std::chrono::year_month>();
+
+  test_hash_enabled<std::chrono::year_month_day>();
+
+  test_hash_enabled(
+      std::chrono::year_month_day_last(std::chrono::year{}, std::chrono::month_day_last(std::chrono::month{})));
+
+  test_hash_enabled<std::chrono::year_month_weekday>();
+
+  test_hash_enabled(std::chrono::year_month_weekday_last(
+      std::chrono::year{}, std::chrono::month{}, std::chrono::weekday_last(std::chrono::weekday{})));
+
+#ifndef TEST_HAS_NO_EXPERIMENTAL_TZDB
+
+  test_hash_enabled(std::chrono::leap_second({}, std::chrono::sys_seconds{}, std::chrono::seconds{}));
+
+#  if !defined(TEST_HAS_NO_LOCALIZATION) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) && !defined(TEST_HAS_NO_FILESYSTEM)
+
+  test_hash_enabled<std::chrono::zoned_time<std::chrono::milliseconds>>();
+
+#  endif // !defined(TEST_HAS_NO_LOCALIZATION) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) &&
+         // !defined(TEST_HAS_NO_FILESYSTEM)
+
+#endif // TEST_HAS_NO_EXPERIMENTAL_TZDB
+
+  return 0;
+}


        


More information about the libcxx-commits mailing list