diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h index 70a03db4350..b1d5f291306 100644 --- a/src/corelib/global/qnumeric.h +++ b/src/corelib/global/qnumeric.h @@ -488,6 +488,28 @@ constexpr inline auto qUnsignedAbs(T t) return (t >= 0) ? U(t) : U(~U(t) + U(1)); } +template , bool> = true, + typename std::enable_if_t, bool> = true> +constexpr inline Result qCheckedFPConversionToInteger(FP value) +{ + // GCC always has constexpr cmath +#if !defined(__cpp_lib_constexpr_cmath) && !defined(Q_CC_GNU_ONLY) +# ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED + if (!q20::is_constant_evaluated()) +# else + if (false) +# endif +#endif + { + const FP truncatedValue = std::trunc(value); + Q_ASSERT(truncatedValue >= FP((std::numeric_limits::min)())); + Q_ASSERT(truncatedValue <= FP((std::numeric_limits::max)())); + } + return Result(value); +} + namespace QRoundImpl { // gcc < 10 doesn't have __has_builtin #if defined(Q_PROCESSOR_ARM_64) && (__has_builtin(__builtin_round) || defined(Q_CC_GNU)) && !defined(Q_CC_CLANG) @@ -530,22 +552,22 @@ constexpr inline int qSaturateRound(FP value) constexpr inline int qRound(double d) { - return int(QtPrivate::QRoundImpl::qRound(d)); + return QtPrivate::qCheckedFPConversionToInteger(QtPrivate::QRoundImpl::qRound(d)); } constexpr inline int qRound(float f) { - return int(QtPrivate::QRoundImpl::qRound(f)); + return QtPrivate::qCheckedFPConversionToInteger(QtPrivate::QRoundImpl::qRound(f)); } constexpr inline qint64 qRound64(double d) { - return qint64(QtPrivate::QRoundImpl::qRound(d)); + return QtPrivate::qCheckedFPConversionToInteger(QtPrivate::QRoundImpl::qRound(d)); } constexpr inline qint64 qRound64(float f) { - return qint64(QtPrivate::QRoundImpl::qRound(f)); + return QtPrivate::qCheckedFPConversionToInteger(QtPrivate::QRoundImpl::qRound(f)); } namespace QtPrivate { diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h index daaf2d411ad..42cbe9bc606 100644 --- a/src/corelib/kernel/qmath.h +++ b/src/corelib/kernel/qmath.h @@ -27,13 +27,13 @@ extern Q_CORE_EXPORT const qreal qt_sine_table[QT_SINE_TABLE_SIZE]; template int qCeil(T v) { using std::ceil; - return int(ceil(v)); + return QtPrivate::qCheckedFPConversionToInteger(ceil(v)); } template int qFloor(T v) { using std::floor; - return int(floor(v)); + return QtPrivate::qCheckedFPConversionToInteger(floor(v)); } template auto qFabs(T v)