Loading mfbt/CheckedInt.h +34 −24 Original line number Diff line number Diff line Loading @@ -209,6 +209,8 @@ struct PositionOfSignBit template<typename IntegerType> struct MinValue { static IntegerType value() { // Bitwise ops may return a larger type, that's why we cast explicitly. // In C++, left bit shifts on signed values is undefined by the standard Loading @@ -216,20 +218,23 @@ struct MinValue // Notice that signed-to-unsigned conversions are always well-defined in // the standard as the value congruent to 2**n, as expected. By contrast, // unsigned-to-signed is only well-defined if the value is representable. static const IntegerType value = IsSigned<IntegerType>::value return IsSigned<IntegerType>::value ? IntegerType(typename UnsignedType<IntegerType>::Type(1) << PositionOfSignBit<IntegerType>::value) : IntegerType(0); } }; template<typename IntegerType> struct MaxValue { static IntegerType value() { // Tricksy, but covered by the unit test. // Relies heavily on the type of MinValue<IntegerType>::value // Relies heavily on the return type of MinValue<IntegerType>::value() // being IntegerType. static const IntegerType value = ~MinValue<IntegerType>::value; return ~MinValue<IntegerType>::value(); } }; /* Loading Loading @@ -273,7 +278,8 @@ struct IsInRangeImpl<T, U, true, true> { static bool run(U x) { return x <= MaxValue<T>::value && x >= MinValue<T>::value; return x <= MaxValue<T>::value() && x >= MinValue<T>::value(); } }; Loading @@ -282,7 +288,7 @@ struct IsInRangeImpl<T, U, false, false> { static bool run(U x) { return x <= MaxValue<T>::value; return x <= MaxValue<T>::value(); } }; Loading @@ -291,7 +297,9 @@ struct IsInRangeImpl<T, U, true, false> { static bool run(U x) { return sizeof(T) > sizeof(U) || x <= U(MaxValue<T>::value); return sizeof(T) > sizeof(U) ? true : x <= U(MaxValue<T>::value()); } }; Loading @@ -302,7 +310,7 @@ struct IsInRangeImpl<T, U, false, true> { return sizeof(T) >= sizeof(U) ? x >= 0 : x >= 0 && x <= U(MaxValue<T>::value); : x >= 0 && x <= U(MaxValue<T>::value()); } }; Loading Loading @@ -358,8 +366,8 @@ struct IsMulValidImpl<T, true, false> { static bool run(T x, T y) { const T max = MaxValue<T>::value; const T min = MinValue<T>::value; const T max = MaxValue<T>::value(); const T min = MinValue<T>::value(); if (x == 0 || y == 0) return true; Loading @@ -382,7 +390,8 @@ struct IsMulValidImpl<T, false, false> { static bool run(T x, T y) { return y == 0 || x <= MaxValue<T>::value / y; return y == 0 || x <= MaxValue<T>::value() / y; } }; Loading @@ -398,8 +407,9 @@ inline bool IsDivValid(T x, T y) { // Keep in mind that in the signed case, min/-1 is invalid because abs(min)>max. return y != 0 && !(IsSigned<T>::value && x == MinValue<T>::value && y == T(-1)); return IsSigned<T>::value ? (y != 0) && (x != MinValue<T>::value() || y != T(-1)) : y != 0; } // This is just to shut up msvc warnings about negating unsigned ints. Loading mfbt/tests/TestCheckedInt.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -96,8 +96,8 @@ void test() VERIFY(sizeof(unsignedT) == sizeof(T)); VERIFY(detail::IsSigned<unsignedT>::value == false); const CheckedInt<T> max(detail::MaxValue<T>::value); const CheckedInt<T> min(detail::MinValue<T>::value); const CheckedInt<T> max(detail::MaxValue<T>::value()); const CheckedInt<T> min(detail::MinValue<T>::value()); // Check min() and max(), since they are custom implementations and a mistake there // could potentially NOT be caught by any other tests... while making everything wrong! Loading Loading @@ -394,10 +394,10 @@ void test() if (isUSigned) \ VERIFY_IS_VALID_IF(CheckedInt<T>(U(-1)), isTSigned); \ if (sizeof(U) > sizeof(T)) \ VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value) + 1)); \ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value), \ VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value())+1)); \ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value()), \ (sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (isUSigned || !isTSigned)))); \ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value), \ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value()), \ isUSigned == false ? 1 : \ bool(isTSigned) == false ? 0 : \ sizeof(T) >= sizeof(U)); \ Loading Loading
mfbt/CheckedInt.h +34 −24 Original line number Diff line number Diff line Loading @@ -209,6 +209,8 @@ struct PositionOfSignBit template<typename IntegerType> struct MinValue { static IntegerType value() { // Bitwise ops may return a larger type, that's why we cast explicitly. // In C++, left bit shifts on signed values is undefined by the standard Loading @@ -216,20 +218,23 @@ struct MinValue // Notice that signed-to-unsigned conversions are always well-defined in // the standard as the value congruent to 2**n, as expected. By contrast, // unsigned-to-signed is only well-defined if the value is representable. static const IntegerType value = IsSigned<IntegerType>::value return IsSigned<IntegerType>::value ? IntegerType(typename UnsignedType<IntegerType>::Type(1) << PositionOfSignBit<IntegerType>::value) : IntegerType(0); } }; template<typename IntegerType> struct MaxValue { static IntegerType value() { // Tricksy, but covered by the unit test. // Relies heavily on the type of MinValue<IntegerType>::value // Relies heavily on the return type of MinValue<IntegerType>::value() // being IntegerType. static const IntegerType value = ~MinValue<IntegerType>::value; return ~MinValue<IntegerType>::value(); } }; /* Loading Loading @@ -273,7 +278,8 @@ struct IsInRangeImpl<T, U, true, true> { static bool run(U x) { return x <= MaxValue<T>::value && x >= MinValue<T>::value; return x <= MaxValue<T>::value() && x >= MinValue<T>::value(); } }; Loading @@ -282,7 +288,7 @@ struct IsInRangeImpl<T, U, false, false> { static bool run(U x) { return x <= MaxValue<T>::value; return x <= MaxValue<T>::value(); } }; Loading @@ -291,7 +297,9 @@ struct IsInRangeImpl<T, U, true, false> { static bool run(U x) { return sizeof(T) > sizeof(U) || x <= U(MaxValue<T>::value); return sizeof(T) > sizeof(U) ? true : x <= U(MaxValue<T>::value()); } }; Loading @@ -302,7 +310,7 @@ struct IsInRangeImpl<T, U, false, true> { return sizeof(T) >= sizeof(U) ? x >= 0 : x >= 0 && x <= U(MaxValue<T>::value); : x >= 0 && x <= U(MaxValue<T>::value()); } }; Loading Loading @@ -358,8 +366,8 @@ struct IsMulValidImpl<T, true, false> { static bool run(T x, T y) { const T max = MaxValue<T>::value; const T min = MinValue<T>::value; const T max = MaxValue<T>::value(); const T min = MinValue<T>::value(); if (x == 0 || y == 0) return true; Loading @@ -382,7 +390,8 @@ struct IsMulValidImpl<T, false, false> { static bool run(T x, T y) { return y == 0 || x <= MaxValue<T>::value / y; return y == 0 || x <= MaxValue<T>::value() / y; } }; Loading @@ -398,8 +407,9 @@ inline bool IsDivValid(T x, T y) { // Keep in mind that in the signed case, min/-1 is invalid because abs(min)>max. return y != 0 && !(IsSigned<T>::value && x == MinValue<T>::value && y == T(-1)); return IsSigned<T>::value ? (y != 0) && (x != MinValue<T>::value() || y != T(-1)) : y != 0; } // This is just to shut up msvc warnings about negating unsigned ints. Loading
mfbt/tests/TestCheckedInt.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -96,8 +96,8 @@ void test() VERIFY(sizeof(unsignedT) == sizeof(T)); VERIFY(detail::IsSigned<unsignedT>::value == false); const CheckedInt<T> max(detail::MaxValue<T>::value); const CheckedInt<T> min(detail::MinValue<T>::value); const CheckedInt<T> max(detail::MaxValue<T>::value()); const CheckedInt<T> min(detail::MinValue<T>::value()); // Check min() and max(), since they are custom implementations and a mistake there // could potentially NOT be caught by any other tests... while making everything wrong! Loading Loading @@ -394,10 +394,10 @@ void test() if (isUSigned) \ VERIFY_IS_VALID_IF(CheckedInt<T>(U(-1)), isTSigned); \ if (sizeof(U) > sizeof(T)) \ VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value) + 1)); \ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value), \ VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value())+1)); \ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value()), \ (sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (isUSigned || !isTSigned)))); \ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value), \ VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value()), \ isUSigned == false ? 1 : \ bool(isTSigned) == false ? 0 : \ sizeof(T) >= sizeof(U)); \ Loading