diff --git a/rpcs3/util/types.hpp b/rpcs3/util/types.hpp index 690f51c0e7..80486a6e1a 100644 --- a/rpcs3/util/types.hpp +++ b/rpcs3/util/types.hpp @@ -999,17 +999,18 @@ template requires (std::is_integral_v; constexpr bool is_to_signed = std::is_signed_v; + // For unsigned/signed mismatch, create an "unsigned" compatible mask constexpr auto from_mask = (is_from_signed && !is_to_signed) ? UnFrom{umax} >> 1 : UnFrom{umax}; constexpr auto to_mask = (is_to_signed && !is_from_signed) ? UnTo{umax} >> 1 : UnTo{umax}; - constexpr auto mask = ~(from_mask & to_mask); + constexpr auto mask = static_cast(~(from_mask & to_mask)); - // Signed to unsigned always require test - // Otherwise, this is bit-wise narrowing or conversion between types of different signedness of the same size - if constexpr ((is_from_signed && !is_to_signed) || to_mask < from_mask) + // If destination ("unsigned" compatible) mask is smaller than source ("unsigned" compatible) mask + // It requires narrowing. + if constexpr (!!mask) { // Try to optimize test if both are of the same signedness - if (is_from_signed != is_to_signed ? !!(value & mask) : static_cast(value) != value) [[unlikely]] + if (is_from_signed != is_to_signed ? !!(value & mask) : static_cast(value) != static_cast(value)) [[unlikely]] { fmt::raw_verify_error(src_loc, u8"Narrowing error", +value); }