From 260a884ee62df7fd3b6b661baf64b99eb516ef29 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Thu, 4 Jul 2024 16:30:53 +0800 Subject: [PATCH] Backport overflow checking of `lcm`/`gcd` to C++17 `_Mul_overflow` is made to only handle non-`bool` integer types in C++17. --- stl/inc/numeric | 11 +++-------- stl/inc/xutility | 14 +++++++++++--- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/stl/inc/numeric b/stl/inc/numeric index ce5e131b11..0dafdfa9e3 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -625,10 +625,9 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) n using _Common = common_type_t<_Mt, _Nt>; using _Common_unsigned = make_unsigned_t<_Common>; -#if _HAS_CXX20 if constexpr (is_signed_v<_Common>) { #ifndef _DEBUG - if (_STD is_constant_evaluated()) + if (_STD _Is_constant_evaluated()) #endif // ^^^ !defined(_DEBUG) ^^ { if (_Mx == _STD _Min_limit<_Common>() || _Nx == _STD _Min_limit<_Common>()) { @@ -637,7 +636,6 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) n } } } -#endif // _HAS_CXX20 return _Select_countr_zero_impl<_Common_unsigned>([=](auto _Countr_zero_impl) { _Common_unsigned _Mx_magnitude = _Abs_u(_Mx); @@ -684,11 +682,10 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> lcm(const _Mt _Mx, const _Nt _Nx) n return 0; } -#if _HAS_CXX20 #ifdef _DEBUG if constexpr (true) #else // ^^^ defined(_DEBUG) / !defined(_DEBUG) vvv - if (_STD is_constant_evaluated()) + if (_STD _Is_constant_evaluated()) #endif // ^^^ !defined(_DEBUG) ^^^ { _Common_unsigned _Result = 0; @@ -700,9 +697,7 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> lcm(const _Mt _Mx, const _Nt _Nx) n } return static_cast<_Common>(_Result); - } else -#endif // _HAS_CXX20 - { + } else { return static_cast<_Common>((_Mx_magnitude / _STD gcd(_Mx_magnitude, _Nx_magnitude)) * _Nx_magnitude); } } diff --git a/stl/inc/xutility b/stl/inc/xutility index eb644e877f..2beb7c6dd2 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -7374,16 +7374,23 @@ _NODISCARD constexpr bool _Add_overflow(const _Int _Left, const _Int _Right, _In } #endif // _HAS_CXX23 +#if _HAS_CXX17 #if _HAS_CXX20 template <_Integer_like _Int> +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv +template , int> = 0> +#endif // ^^^ !_HAS_CXX20 ^^^ _NODISCARD constexpr bool _Mul_overflow(const _Int _Left, const _Int _Right, _Int& _Out) { +#if defined(__clang__) && !_HAS_CXX20 + return __builtin_mul_overflow(_Left, _Right, &_Out); +#else // ^^^ defined(__clang__) && !_HAS_CXX20 / !defined(__clang__) || _HAS_CXX20 vvv #ifdef __clang__ - if constexpr (integral<_Int>) { + if constexpr (is_integral_v<_Int>) { return __builtin_mul_overflow(_Left, _Right, &_Out); } else #endif // defined(__clang__) { - if constexpr (!_Signed_integer_like<_Int>) { + if constexpr (static_cast<_Int>(-1) > static_cast<_Int>(0)) { constexpr auto _UInt_max = _STD _Max_limit<_Int>(); const bool _Overflow = _Left != 0 && _Right > _UInt_max / _Left; if (!_Overflow) { @@ -7422,8 +7429,9 @@ _NODISCARD constexpr bool _Mul_overflow(const _Int _Left, const _Int _Right, _In // ^^^ Based on llvm::MulOverflow ^^^ } } +#endif // ^^^ !defined(__clang__) || _HAS_CXX20 ^^^ } -#endif // _HAS_CXX20 +#endif // _HAS_CXX17 _STD_END