Skip to content

Commit e0441d5

Browse files
authored
[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 #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: #104700
1 parent e0326b6 commit e0441d5

File tree

2 files changed

+69
-63
lines changed

2 files changed

+69
-63
lines changed

libcxx/docs/Status/Cxx2cIssues.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,5 @@
7777
"`LWG4106 <https://wg21.link/LWG4106>`__","``basic_format_args`` should not be default-constructible","2024-06 (St. Louis)","|Complete|","19.0","|format|"
7878
"","","","","",""
7979
"`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",""
80+
"`LWG4139 <https://wg21.link/LWG4139>`__","§[time.zone.leap] recursive constraint in <=>","Not Adopted Yet","|Complete|","20.0",""
8081
"","","","","",""

libcxx/include/__chrono/leap_second.h

Lines changed: 68 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -50,70 +50,75 @@ class leap_second {
5050
private:
5151
sys_seconds __date_;
5252
seconds __value_;
53-
};
5453

55-
_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const leap_second& __x, const leap_second& __y) {
56-
return __x.date() == __y.date();
57-
}
58-
59-
_LIBCPP_HIDE_FROM_ABI inline constexpr strong_ordering operator<=>(const leap_second& __x, const leap_second& __y) {
60-
return __x.date() <=> __y.date();
61-
}
62-
63-
template <class _Duration>
64-
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const leap_second& __x, const sys_time<_Duration>& __y) {
65-
return __x.date() == __y;
66-
}
67-
68-
template <class _Duration>
69-
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const leap_second& __x, const sys_time<_Duration>& __y) {
70-
return __x.date() < __y;
71-
}
72-
73-
template <class _Duration>
74-
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const sys_time<_Duration>& __x, const leap_second& __y) {
75-
return __x < __y.date();
76-
}
77-
78-
template <class _Duration>
79-
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const leap_second& __x, const sys_time<_Duration>& __y) {
80-
return __y < __x;
81-
}
82-
83-
template <class _Duration>
84-
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const sys_time<_Duration>& __x, const leap_second& __y) {
85-
return __y < __x;
86-
}
87-
88-
template <class _Duration>
89-
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const leap_second& __x, const sys_time<_Duration>& __y) {
90-
return !(__y < __x);
91-
}
92-
93-
template <class _Duration>
94-
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const sys_time<_Duration>& __x, const leap_second& __y) {
95-
return !(__y < __x);
96-
}
97-
98-
template <class _Duration>
99-
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const leap_second& __x, const sys_time<_Duration>& __y) {
100-
return !(__x < __y);
101-
}
102-
103-
template <class _Duration>
104-
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const sys_time<_Duration>& __x, const leap_second& __y) {
105-
return !(__x < __y);
106-
}
107-
108-
# ifndef _LIBCPP_COMPILER_GCC
109-
// This requirement cause a compilation loop in GCC-13 and running out of memory.
110-
// TODO TZDB Test whether GCC-14 fixes this.
111-
template <class _Duration>
112-
requires three_way_comparable_with<sys_seconds, sys_time<_Duration>>
113-
_LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const leap_second& __x, const sys_time<_Duration>& __y) {
114-
return __x.date() <=> __y;
115-
}
116-
# endif
54+
// The function
55+
// template<class Duration>
56+
// requires three_way_comparable_with<sys_seconds, sys_time<Duration>>
57+
// constexpr auto operator<=>(const leap_second& x, const sys_time<Duration>& y) noexcept;
58+
//
59+
// Has constraints that are recursive (LWG4139). The proposed resolution is
60+
// to make the funcion a hidden friend. For consistency make this change for
61+
// all comparison functions.
62+
63+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const leap_second& __x, const leap_second& __y) {
64+
return __x.date() == __y.date();
65+
}
66+
67+
_LIBCPP_HIDE_FROM_ABI friend constexpr strong_ordering operator<=>(const leap_second& __x, const leap_second& __y) {
68+
return __x.date() <=> __y.date();
69+
}
70+
71+
template <class _Duration>
72+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const leap_second& __x, const sys_time<_Duration>& __y) {
73+
return __x.date() == __y;
74+
}
75+
76+
template <class _Duration>
77+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const leap_second& __x, const sys_time<_Duration>& __y) {
78+
return __x.date() < __y;
79+
}
80+
81+
template <class _Duration>
82+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const sys_time<_Duration>& __x, const leap_second& __y) {
83+
return __x < __y.date();
84+
}
85+
86+
template <class _Duration>
87+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const leap_second& __x, const sys_time<_Duration>& __y) {
88+
return __y < __x;
89+
}
90+
91+
template <class _Duration>
92+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const sys_time<_Duration>& __x, const leap_second& __y) {
93+
return __y < __x;
94+
}
95+
96+
template <class _Duration>
97+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const leap_second& __x, const sys_time<_Duration>& __y) {
98+
return !(__y < __x);
99+
}
100+
101+
template <class _Duration>
102+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const sys_time<_Duration>& __x, const leap_second& __y) {
103+
return !(__y < __x);
104+
}
105+
106+
template <class _Duration>
107+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const leap_second& __x, const sys_time<_Duration>& __y) {
108+
return !(__x < __y);
109+
}
110+
111+
template <class _Duration>
112+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const sys_time<_Duration>& __x, const leap_second& __y) {
113+
return !(__x < __y);
114+
}
115+
116+
template <class _Duration>
117+
requires three_way_comparable_with<sys_seconds, sys_time<_Duration>>
118+
_LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const leap_second& __x, const sys_time<_Duration>& __y) {
119+
return __x.date() <=> __y;
120+
}
121+
};
117122

118123
} // namespace chrono
119124

0 commit comments

Comments
 (0)