From 4cba4fd7270a5d8eade223134464a88382c41d7c Mon Sep 17 00:00:00 2001 From: statementreply Date: Sat, 13 Jul 2024 20:52:09 +0800 Subject: [PATCH 1/2] Add `[[msvc::lifetimebound]]` to more min/max functions --- stl/inc/algorithm | 11 +++++++---- stl/inc/utility | 14 ++++++++------ stl/inc/xutility | 8 ++++---- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index af08dfa626b..c3219e6ad00 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -10723,7 +10723,8 @@ namespace ranges { #endif // _HAS_CXX20 _EXPORT_STD template -_NODISCARD constexpr const _Ty& clamp(const _Ty& _Val, const _Ty& _Min_val, const _Ty& _Max_val, _Pr _Pred) { +_NODISCARD constexpr const _Ty& clamp(const _Ty& _Val _MSVC_LIFETIMEBOUND, const _Ty& _Min_val _MSVC_LIFETIMEBOUND, + const _Ty& _Max_val _MSVC_LIFETIMEBOUND, _Pr _Pred) { // returns _Val constrained to [_Min_val, _Max_val] #if _ITERATOR_DEBUG_LEVEL == 2 if (_DEBUG_LT_PRED(_Pred, _Max_val, _Min_val)) { @@ -10750,7 +10751,8 @@ _NODISCARD constexpr const _Ty& clamp(const _Ty& _Val, const _Ty& _Min_val, cons } _EXPORT_STD template -_NODISCARD constexpr const _Ty& clamp(const _Ty& _Val, const _Ty& _Min_val, const _Ty& _Max_val) { +_NODISCARD constexpr const _Ty& clamp(const _Ty& _Val _MSVC_LIFETIMEBOUND, const _Ty& _Min_val _MSVC_LIFETIMEBOUND, + const _Ty& _Max_val _MSVC_LIFETIMEBOUND) { // returns _Val constrained to [_Min_val, _Max_val] return _STD clamp(_Val, _Min_val, _Max_val, less{}); } @@ -10761,8 +10763,9 @@ namespace ranges { public: template > _Pr = ranges::less> - _NODISCARD _STATIC_CALL_OPERATOR constexpr const _Ty& operator()( - const _Ty& _Val, const _Ty& _Lo, const _Ty& _Hi, _Pr _Pred = {}, _Pj _Proj = {}) _CONST_CALL_OPERATOR { + _NODISCARD _STATIC_CALL_OPERATOR constexpr const _Ty& operator()(const _Ty& _Val _MSVC_LIFETIMEBOUND, + const _Ty& _Lo _MSVC_LIFETIMEBOUND, const _Ty& _Hi _MSVC_LIFETIMEBOUND, _Pr _Pred = {}, + _Pj _Proj = {}) _CONST_CALL_OPERATOR { _STL_ASSERT(!_STD invoke(_Pred, _STD invoke(_Proj, _Hi), _STD invoke(_Proj, _Lo)), "The lower bound cannot be greater than the upper bound in a call to std::ranges::clamp " "(N4950 [alg.clamp]/2)."); diff --git a/stl/inc/utility b/stl/inc/utility index df825320fd6..28f680249b7 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -59,8 +59,8 @@ _EXPORT_STD template using index_sequence_for = make_index_sequence; _EXPORT_STD template -_NODISCARD constexpr const _Ty&(max) (const _Ty& _Left, const _Ty& _Right, _Pr _Pred) noexcept( - noexcept(_Pred(_Left, _Right))) /* strengthened */ { +_NODISCARD constexpr const _Ty&(max) (const _Ty& _Left _MSVC_LIFETIMEBOUND, const _Ty& _Right _MSVC_LIFETIMEBOUND, + _Pr _Pred) noexcept(noexcept(_Pred(_Left, _Right))) /* strengthened */ { // return larger of _Left and _Right return _Pred(_Left, _Right) ? _Right : _Left; } @@ -69,7 +69,8 @@ _NODISCARD constexpr const _Ty&(max) (const _Ty& _Left, const _Ty& _Right, _Pr _ #pragma warning(disable : 28285) // (syntax error in SAL annotation, occurs when _Ty is not an integral type) _EXPORT_STD template _NODISCARD _Post_equal_to_(_Left < _Right ? _Right : _Left) constexpr const _Ty& // - (max) (const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Left < _Right)) /* strengthened */ { + (max) (const _Ty& _Left _MSVC_LIFETIMEBOUND, const _Ty& _Right _MSVC_LIFETIMEBOUND) noexcept( + noexcept(_Left < _Right)) /* strengthened */ { // return larger of _Left and _Right return _Left < _Right ? _Right : _Left; } @@ -82,8 +83,8 @@ _EXPORT_STD template _NODISCARD constexpr _Ty(max)(initializer_list<_Ty>); // implemented in _EXPORT_STD template -_NODISCARD constexpr const _Ty&(min) (const _Ty& _Left, const _Ty& _Right, _Pr _Pred) noexcept( - noexcept(_Pred(_Right, _Left))) /* strengthened */ { +_NODISCARD constexpr const _Ty&(min) (const _Ty& _Left _MSVC_LIFETIMEBOUND, const _Ty& _Right _MSVC_LIFETIMEBOUND, + _Pr _Pred) noexcept(noexcept(_Pred(_Right, _Left))) /* strengthened */ { // return smaller of _Left and _Right return _Pred(_Right, _Left) ? _Right : _Left; } @@ -92,7 +93,8 @@ _NODISCARD constexpr const _Ty&(min) (const _Ty& _Left, const _Ty& _Right, _Pr _ #pragma warning(disable : 28285) // (syntax error in SAL annotation, occurs when _Ty is not an integral type) _EXPORT_STD template _NODISCARD _Post_equal_to_(_Right < _Left ? _Right : _Left) constexpr const _Ty& // - (min) (const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Right < _Left)) /* strengthened */ { + (min) (const _Ty& _Left _MSVC_LIFETIMEBOUND, const _Ty& _Right _MSVC_LIFETIMEBOUND) noexcept( + noexcept(_Right < _Left)) /* strengthened */ { // return smaller of _Left and _Right return _Right < _Left ? _Right : _Left; } diff --git a/stl/inc/xutility b/stl/inc/xutility index fbed6751ec2..5af41cbad90 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -6953,8 +6953,8 @@ namespace ranges { public: template > _Pr = ranges::less> - _NODISCARD _STATIC_CALL_OPERATOR constexpr const _Ty& operator()( - const _Ty& _Left, const _Ty& _Right, _Pr _Pred = {}, _Pj _Proj = {}) _CONST_CALL_OPERATOR { + _NODISCARD _STATIC_CALL_OPERATOR constexpr const _Ty& operator()(const _Ty& _Left _MSVC_LIFETIMEBOUND, + const _Ty& _Right _MSVC_LIFETIMEBOUND, _Pr _Pred = {}, _Pj _Proj = {}) _CONST_CALL_OPERATOR { if (_STD invoke(_Pred, _STD invoke(_Proj, _Left), _STD invoke(_Proj, _Right))) { return _Right; } else { @@ -7171,8 +7171,8 @@ namespace ranges { public: template > _Pr = ranges::less> - _NODISCARD _STATIC_CALL_OPERATOR constexpr const _Ty& operator()( - const _Ty& _Left, const _Ty& _Right, _Pr _Pred = {}, _Pj _Proj = {}) _CONST_CALL_OPERATOR { + _NODISCARD _STATIC_CALL_OPERATOR constexpr const _Ty& operator()(const _Ty& _Left _MSVC_LIFETIMEBOUND, + const _Ty& _Right _MSVC_LIFETIMEBOUND, _Pr _Pred = {}, _Pj _Proj = {}) _CONST_CALL_OPERATOR { if (_STD invoke(_Pred, _STD invoke(_Proj, _Right), _STD invoke(_Proj, _Left))) { return _Right; } else { From 1c6e3837292d10367bc67a66c84585d393fdca4a Mon Sep 17 00:00:00 2001 From: statementreply Date: Sat, 13 Jul 2024 23:02:24 +0800 Subject: [PATCH 2/2] Defend against `#define lifetimebound` --- stl/inc/utility | 3 +++ stl/inc/xutility | 3 +++ 2 files changed, 6 insertions(+) diff --git a/stl/inc/utility b/stl/inc/utility index 28f680249b7..f86e318e398 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -30,9 +30,11 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("msvc") #pragma push_macro("intrinsic") #pragma push_macro("known_semantics") +#pragma push_macro("lifetimebound") #undef msvc #undef intrinsic #undef known_semantics +#undef lifetimebound _STD_BEGIN _EXPORT_STD template @@ -971,6 +973,7 @@ namespace _DEPRECATE_TR1_NAMESPACE tr1 { _STD_END // TRANSITION, non-_Ugly attribute tokens +#pragma pop_macro("lifetimebound") #pragma pop_macro("known_semantics") #pragma pop_macro("intrinsic") #pragma pop_macro("msvc") diff --git a/stl/inc/xutility b/stl/inc/xutility index 5af41cbad90..2fd6e121673 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -23,8 +23,10 @@ _STL_DISABLE_CLANG_WARNINGS // TRANSITION, non-_Ugly attribute tokens #pragma push_macro("msvc") #pragma push_macro("intrinsic") +#pragma push_macro("lifetimebound") #undef msvc #undef intrinsic +#undef lifetimebound #if defined(_CRTBLD) && defined(CRTDLL2) // TRANSITION, ABI: The vector algorithms are compiled into the import lib, so we disable their usage when building @@ -7425,6 +7427,7 @@ _NODISCARD constexpr bool _Mul_overflow(const _Int _Left, const _Int _Right, _In _STD_END // TRANSITION, non-_Ugly attribute tokens +#pragma pop_macro("lifetimebound") #pragma pop_macro("intrinsic") #pragma pop_macro("msvc")