[libcxx-commits] [libcxx] e0441d5 - [libc++][chono] Use hidden friends for leap_second comparison. (#104713)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Aug 20 10:13:32 PDT 2024


Author: Mark de Wever
Date: 2024-08-20T19:13:27+02:00
New Revision: e0441d587b3c5c5d11b08cbcfbbbb66ea8185510

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

LOG: [libc++][chono] Use hidden friends for leap_second comparison. (#104713)

The function

    template<class Duration>
requires three_way_comparable_with<sys_seconds, sys_time<Duration>>
constexpr auto operator<=>(const leap_second& x, const
sys_time<Duration>& y) noexcept;

Has a recursive constrained. This caused an infinite loop in GCC and is
now hit by https://github.com/llvm/llvm-project/pull/102857.

A fix would be to make this function a hidden friend, this solution is
propsed in LWG4139.

For consistency all comparisons are made hidden friends. Since the issue
causes compilation failures no additional test are needed.

Fixes: https://github.com/llvm/llvm-project/issues/104700

Added: 
    

Modified: 
    libcxx/docs/Status/Cxx2cIssues.csv
    libcxx/include/__chrono/leap_second.h

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 60c6dc532dc719..be0621caaa9c69 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -77,4 +77,5 @@
 "`LWG4106 <https://wg21.link/LWG4106>`__","``basic_format_args`` should not be default-constructible","2024-06 (St. Louis)","|Complete|","19.0","|format|"
 "","","","","",""
 "`LWG3343 <https://wg21.link/LWG3343>`__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Adopted Yet","|Complete|","16.0",""
+"`LWG4139 <https://wg21.link/LWG4139>`__","ยง[time.zone.leap] recursive constraint in <=>","Not Adopted Yet","|Complete|","20.0",""
 "","","","","",""

diff  --git a/libcxx/include/__chrono/leap_second.h b/libcxx/include/__chrono/leap_second.h
index 1a0e7f3107de81..d79111ed8eecfc 100644
--- a/libcxx/include/__chrono/leap_second.h
+++ b/libcxx/include/__chrono/leap_second.h
@@ -50,70 +50,75 @@ class leap_second {
 private:
   sys_seconds __date_;
   seconds __value_;
-};
 
-_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const leap_second& __x, const leap_second& __y) {
-  return __x.date() == __y.date();
-}
-
-_LIBCPP_HIDE_FROM_ABI inline constexpr strong_ordering operator<=>(const leap_second& __x, const leap_second& __y) {
-  return __x.date() <=> __y.date();
-}
-
-template <class _Duration>
-_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const leap_second& __x, const sys_time<_Duration>& __y) {
-  return __x.date() == __y;
-}
-
-template <class _Duration>
-_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const leap_second& __x, const sys_time<_Duration>& __y) {
-  return __x.date() < __y;
-}
-
-template <class _Duration>
-_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const sys_time<_Duration>& __x, const leap_second& __y) {
-  return __x < __y.date();
-}
-
-template <class _Duration>
-_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const leap_second& __x, const sys_time<_Duration>& __y) {
-  return __y < __x;
-}
-
-template <class _Duration>
-_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const sys_time<_Duration>& __x, const leap_second& __y) {
-  return __y < __x;
-}
-
-template <class _Duration>
-_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const leap_second& __x, const sys_time<_Duration>& __y) {
-  return !(__y < __x);
-}
-
-template <class _Duration>
-_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const sys_time<_Duration>& __x, const leap_second& __y) {
-  return !(__y < __x);
-}
-
-template <class _Duration>
-_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const leap_second& __x, const sys_time<_Duration>& __y) {
-  return !(__x < __y);
-}
-
-template <class _Duration>
-_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const sys_time<_Duration>& __x, const leap_second& __y) {
-  return !(__x < __y);
-}
-
-#    ifndef _LIBCPP_COMPILER_GCC
-// This requirement cause a compilation loop in GCC-13 and running out of memory.
-// TODO TZDB Test whether GCC-14 fixes this.
-template <class _Duration>
-  requires three_way_comparable_with<sys_seconds, sys_time<_Duration>>
-_LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const leap_second& __x, const sys_time<_Duration>& __y) {
-  return __x.date() <=> __y;
-}
-#    endif
+  // The function
+  //   template<class Duration>
+  //    requires three_way_comparable_with<sys_seconds, sys_time<Duration>>
+  //    constexpr auto operator<=>(const leap_second& x, const sys_time<Duration>& y) noexcept;
+  //
+  // Has constraints that are recursive (LWG4139). The proposed resolution is
+  // to make the funcion a hidden friend. For consistency make this change for
+  // all comparison functions.
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const leap_second& __x, const leap_second& __y) {
+    return __x.date() == __y.date();
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering operator<=>(const leap_second& __x, const leap_second& __y) {
+    return __x.date() <=> __y.date();
+  }
+
+  template <class _Duration>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const leap_second& __x, const sys_time<_Duration>& __y) {
+    return __x.date() == __y;
+  }
+
+  template <class _Duration>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const leap_second& __x, const sys_time<_Duration>& __y) {
+    return __x.date() < __y;
+  }
+
+  template <class _Duration>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const sys_time<_Duration>& __x, const leap_second& __y) {
+    return __x < __y.date();
+  }
+
+  template <class _Duration>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const leap_second& __x, const sys_time<_Duration>& __y) {
+    return __y < __x;
+  }
+
+  template <class _Duration>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const sys_time<_Duration>& __x, const leap_second& __y) {
+    return __y < __x;
+  }
+
+  template <class _Duration>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const leap_second& __x, const sys_time<_Duration>& __y) {
+    return !(__y < __x);
+  }
+
+  template <class _Duration>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const sys_time<_Duration>& __x, const leap_second& __y) {
+    return !(__y < __x);
+  }
+
+  template <class _Duration>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const leap_second& __x, const sys_time<_Duration>& __y) {
+    return !(__x < __y);
+  }
+
+  template <class _Duration>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const sys_time<_Duration>& __x, const leap_second& __y) {
+    return !(__x < __y);
+  }
+
+  template <class _Duration>
+    requires three_way_comparable_with<sys_seconds, sys_time<_Duration>>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const leap_second& __x, const sys_time<_Duration>& __y) {
+    return __x.date() <=> __y;
+  }
+};
 
 } // namespace chrono
 


        


More information about the libcxx-commits mailing list