[libcxx-commits] [libcxx] 80cab52 - [libc++][chrono] Applied `[[nodiscard]]` to `duration` (#174121)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jan 6 00:05:26 PST 2026
Author: Hristo Hristov
Date: 2026-01-06T10:05:22+02:00
New Revision: 80cab521d0b8ec91e1b82b028215f2a6d07fe3aa
URL: https://github.com/llvm/llvm-project/commit/80cab521d0b8ec91e1b82b028215f2a6d07fe3aa
DIFF: https://github.com/llvm/llvm-project/commit/80cab521d0b8ec91e1b82b028215f2a6d07fe3aa.diff
LOG: [libc++][chrono] Applied `[[nodiscard]]` to `duration` (#174121)
`[[nodiscard]]` should be applied to functions where discarding the
return value is most likely a correctness issue.
- https://libcxx.llvm.org/CodingGuidelines.html
- https://wg21.link/time.duration
Towards #172124
Added:
Modified:
libcxx/include/__chrono/duration.h
libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__chrono/duration.h b/libcxx/include/__chrono/duration.h
index 01432bd3fa259..8b8877aa9a175 100644
--- a/libcxx/include/__chrono/duration.h
+++ b/libcxx/include/__chrono/duration.h
@@ -104,7 +104,8 @@ struct __duration_cast<_FromDuration, _ToDuration, _Period, false, false> {
};
template <class _ToDuration, class _Rep, class _Period, __enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration duration_cast(const duration<_Rep, _Period>& __fd) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration
+duration_cast(const duration<_Rep, _Period>& __fd) {
return __duration_cast<duration<_Rep, _Period>, _ToDuration>()(__fd);
}
@@ -119,14 +120,18 @@ inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>:
template <class _Rep>
struct duration_values {
public:
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep zero() _NOEXCEPT { return _Rep(0); }
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep max() _NOEXCEPT { return numeric_limits<_Rep>::max(); }
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep min() _NOEXCEPT { return numeric_limits<_Rep>::lowest(); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep zero() _NOEXCEPT { return _Rep(0); }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep max() _NOEXCEPT {
+ return numeric_limits<_Rep>::max();
+ }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep min() _NOEXCEPT {
+ return numeric_limits<_Rep>::lowest();
+ }
};
#if _LIBCPP_STD_VER >= 17
template <class _ToDuration, class _Rep, class _Period, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration floor(const duration<_Rep, _Period>& __d) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration floor(const duration<_Rep, _Period>& __d) {
_ToDuration __t = chrono::duration_cast<_ToDuration>(__d);
if (__t > __d)
__t = __t - _ToDuration{1};
@@ -134,7 +139,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration floor(const duration<
}
template <class _ToDuration, class _Rep, class _Period, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration ceil(const duration<_Rep, _Period>& __d) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration ceil(const duration<_Rep, _Period>& __d) {
_ToDuration __t = chrono::duration_cast<_ToDuration>(__d);
if (__t < __d)
__t = __t + _ToDuration{1};
@@ -142,7 +147,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration ceil(const duration<_
}
template <class _ToDuration, class _Rep, class _Period, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration round(const duration<_Rep, _Period>& __d) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration round(const duration<_Rep, _Period>& __d) {
_ToDuration __lower = chrono::floor<_ToDuration>(__d);
_ToDuration __upper = __lower + _ToDuration{1};
auto __lower_
diff = __d - __lower;
@@ -222,14 +227,14 @@ class duration {
// observer
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR rep count() const { return __rep_; }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR rep count() const { return __rep_; }
// arithmetic
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<duration>::type operator+() const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<duration>::type operator+() const {
return typename common_type<duration>::type(*this);
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<duration>::type operator-() const {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<duration>::type operator-() const {
return typename common_type<duration>::type(-__rep_);
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 duration& operator++() {
@@ -271,13 +276,13 @@ class duration {
// special values
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration zero() _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration zero() _NOEXCEPT {
return duration(duration_values<rep>::zero());
}
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration min() _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration min() _NOEXCEPT {
return duration(duration_values<rep>::min());
}
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration max() _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR duration max() _NOEXCEPT {
return duration(duration_values<rep>::max());
}
};
@@ -391,7 +396,7 @@ operator<=>(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Perio
// Duration +
template <class _Rep1, class _Period1, class _Rep2, class _Period2>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type
operator+(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
typedef typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type _Cd;
@@ -401,7 +406,7 @@ operator+(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2
// Duration -
template <class _Rep1, class _Period1, class _Rep2, class _Period2>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type
operator-(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
typedef typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type _Cd;
@@ -414,7 +419,8 @@ template <class _Rep1,
class _Period,
class _Rep2,
__enable_if_t<is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
typedef duration<_Cr, _Period> _Cd;
@@ -425,7 +431,8 @@ template <class _Rep1,
class _Period,
class _Rep2,
__enable_if_t<is_convertible<const _Rep1&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) {
return __d * __s;
}
@@ -438,7 +445,8 @@ template <class _Rep1,
__enable_if_t<!__is_duration_v<_Rep2> &&
is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value,
int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
typedef duration<_Cr, _Period> _Cd;
@@ -446,7 +454,7 @@ operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
}
template <class _Rep1, class _Period1, class _Rep2, class _Period2>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<_Rep1, _Rep2>::type
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename common_type<_Rep1, _Rep2>::type
operator/(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
typedef typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type _Ct;
return _Ct(__lhs).count() / _Ct(__rhs).count();
@@ -460,7 +468,8 @@ template <class _Rep1,
__enable_if_t<!__is_duration_v<_Rep2> &&
is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value,
int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
typedef duration<_Cr, _Period> _Cd;
@@ -468,7 +477,7 @@ operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
}
template <class _Rep1, class _Period1, class _Rep2, class _Period2>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
typename common_type<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >::type
operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
@@ -483,51 +492,53 @@ operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2
inline namespace literals {
inline namespace chrono_literals {
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::hours operator""h(unsigned long long __h) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::hours operator""h(unsigned long long __h) {
return chrono::hours(static_cast<chrono::hours::rep>(__h));
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<3600, 1>> operator""h(long double __h) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<3600, 1>>
+operator""h(long double __h) {
return chrono::duration<long double, ratio<3600, 1>>(__h);
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::minutes operator""min(unsigned long long __m) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::minutes operator""min(unsigned long long __m) {
return chrono::minutes(static_cast<chrono::minutes::rep>(__m));
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<60, 1>> operator""min(long double __m) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, ratio<60, 1>>
+operator""min(long double __m) {
return chrono::duration<long double, ratio<60, 1>>(__m);
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::seconds operator""s(unsigned long long __s) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::seconds operator""s(unsigned long long __s) {
return chrono::seconds(static_cast<chrono::seconds::rep>(__s));
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double> operator""s(long double __s) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double> operator""s(long double __s) {
return chrono::duration<long double>(__s);
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::milliseconds operator""ms(unsigned long long __ms) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::milliseconds operator""ms(unsigned long long __ms) {
return chrono::milliseconds(static_cast<chrono::milliseconds::rep>(__ms));
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, milli> operator""ms(long double __ms) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, milli> operator""ms(long double __ms) {
return chrono::duration<long double, milli>(__ms);
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::microseconds operator""us(unsigned long long __us) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::microseconds operator""us(unsigned long long __us) {
return chrono::microseconds(static_cast<chrono::microseconds::rep>(__us));
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, micro> operator""us(long double __us) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, micro> operator""us(long double __us) {
return chrono::duration<long double, micro>(__us);
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::nanoseconds operator""ns(unsigned long long __ns) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::nanoseconds operator""ns(unsigned long long __ns) {
return chrono::nanoseconds(static_cast<chrono::nanoseconds::rep>(__ns));
}
-_LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, nano> operator""ns(long double __ns) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr chrono::duration<long double, nano> operator""ns(long double __ns) {
return chrono::duration<long double, nano>(__ns);
}
diff --git a/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp
index 4e7380b863993..700dcc37c34ef 100644
--- a/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/chrono.nodiscard.verify.cpp
@@ -17,6 +17,7 @@
// <chrono>
#include <chrono>
+#include <ratio>
#include "test_macros.h"
@@ -124,4 +125,91 @@ void test(std::chrono::time_zone tz, std::chrono::time_zone_link link, std::chro
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::chrono::gps_clock::from_utc(std::chrono::utc_seconds{});
}
+
+ { // [time.duration]
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::microseconds(2));
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::duration_values<int>::zero();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::duration_values<int>::max();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::duration_values<int>::min();
+
+ std::chrono::duration<int, std::ratio<1, 30> > dr;
+
+#if TEST_STD_VER >= 17
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::floor<std::chrono::seconds>(dr);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::ceil<std::chrono::seconds>(dr);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::round<std::chrono::seconds>(dr);
+#endif
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ dr.count();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ +dr;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ -dr;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::duration<int, std::ratio<1, 30> >::zero();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::duration<int, std::ratio<1, 30> >::max();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::chrono::duration<int, std::ratio<1, 30> >::min();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ dr + dr;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ dr - dr;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ dr * 94;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 94 * dr;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ dr / 82;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ dr / dr;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ dr % 47;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ dr % dr;
+
+ using namespace std::chrono_literals;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 94h;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 82.5h;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 94min;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 82.5min;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 94s;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 82.5s;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 94ms;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 82.5ms;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 94us;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 82.5us;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 94ns;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 82.5ns;
+ }
}
More information about the libcxx-commits
mailing list