diff --git a/libcxx/include/__algorithm/clamp.h b/libcxx/include/__algorithm/clamp.h --- a/libcxx/include/__algorithm/clamp.h +++ b/libcxx/include/__algorithm/clamp.h @@ -20,24 +20,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 -template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY constexpr -const _Tp& -clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) -{ - _LIBCPP_ASSERT_UNCATEGORIZED(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); - return __comp(__v, __lo) ? __lo : __comp(__hi, __v) ? __hi : __v; - +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY constexpr const _Tp& +clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, + _LIBCPP_LIFETIMEBOUND const _Tp& __lo, + _LIBCPP_LIFETIMEBOUND const _Tp& __hi, + _Compare __comp) { + _LIBCPP_ASSERT_UNCATEGORIZED(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); + return __comp(__v, __lo) ? __lo : __comp(__hi, __v) ? __hi : __v; } -template -_LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY constexpr -const _Tp& -clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) -{ - return _VSTD::clamp(__v, __lo, __hi, __less<>()); +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY constexpr const _Tp& +clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, + _LIBCPP_LIFETIMEBOUND const _Tp& __lo, + _LIBCPP_LIFETIMEBOUND const _Tp& __hi) { + return _VSTD::clamp(__v, __lo, __hi, __less<>()); } #endif diff --git a/libcxx/test/libcxx/algorithms/lifetimebound.verify.cpp b/libcxx/test/libcxx/algorithms/lifetimebound.verify.cpp --- a/libcxx/test/libcxx/algorithms/lifetimebound.verify.cpp +++ b/libcxx/test/libcxx/algorithms/lifetimebound.verify.cpp @@ -44,6 +44,16 @@ auto v7 = std::minmax(0, i, Comp{}); // expected-warning {{temporary whose address is used as value of local variable 'v7' will be destroyed at the end of the full-expression}} auto v8 = std::minmax(i, 0, Comp{}); // expected-warning {{temporary whose address is used as value of local variable 'v8' will be destroyed at the end of the full-expression}} } +#if TEST_STD_VER >= 17 + { + auto&& v1 = std::clamp(1, i, i); // expected-warning {{temporary bound to local reference 'v1' will be destroyed at the end of the full-expression}} + auto&& v2 = std::clamp(i, 1, i); // expected-warning {{temporary bound to local reference 'v2' will be destroyed at the end of the full-expression}} + auto&& v3 = std::clamp(i, i, 1); // expected-warning {{temporary bound to local reference 'v3' will be destroyed at the end of the full-expression}} + auto&& v4 = std::clamp(1, i, i, Comp{}); // expected-warning {{temporary bound to local reference 'v4' will be destroyed at the end of the full-expression}} + auto&& v5 = std::clamp(i, 1, i, Comp{}); // expected-warning {{temporary bound to local reference 'v5' will be destroyed at the end of the full-expression}} + auto&& v6 = std::clamp(i, i, 1, Comp{}); // expected-warning {{temporary bound to local reference 'v6' will be destroyed at the end of the full-expression}} + } +#endif #if TEST_STD_VER >= 20 { auto&& v1 = std::ranges::min(0, i); // expected-warning {{temporary bound to local reference 'v1' will be destroyed at the end of the full-expression}}