Bug 874764 - Add CheckedInt support for operator%. - r=bjacob,waldo

This commit is contained in:
Jeff Gilbert 2013-06-14 15:19:30 -07:00
Родитель 63eccd6385
Коммит 75ab2ff473
2 изменённых файлов: 84 добавлений и 3 удалений

Просмотреть файл

@ -450,6 +450,44 @@ IsDivValid(T x, T y)
!(IsSigned<T>::value && x == MinValue<T>::value && y == T(-1));
}
template<typename T, bool IsTSigned = IsSigned<T>::value>
struct IsModValidImpl;
template<typename T>
inline bool
IsModValid(T x, T y)
{
return IsModValidImpl<T>::run(x, y);
}
/*
* Mod is pretty simple.
* For now, let's just use the ANSI C definition:
* If x or y are negative, the results are implementation defined.
* Consider these invalid.
* Undefined for y=0.
* The result will never exceed either x or y.
*
* Checking that x>=0 is a warning when T is unsigned.
*/
template<typename T>
struct IsModValidImpl<T, false> {
static inline bool run(T x, T y) {
return y >= 1;
}
};
template<typename T>
struct IsModValidImpl<T, true> {
static inline bool run(T x, T y) {
if (x < 0)
return false;
return y >= 1;
}
};
template<typename T, bool IsSigned = IsSigned<T>::value>
struct NegateImpl;
@ -619,22 +657,31 @@ class CheckedInt
const CheckedInt<U>& rhs);
template<typename U>
CheckedInt& operator +=(U rhs);
template<typename U>
friend CheckedInt<U> operator -(const CheckedInt<U>& lhs,
const CheckedInt<U>& rhs);
template<typename U>
CheckedInt& operator -=(U rhs);
template<typename U>
friend CheckedInt<U> operator *(const CheckedInt<U>& lhs,
const CheckedInt<U>& rhs);
template<typename U>
CheckedInt& operator *=(U rhs);
template<typename U>
friend CheckedInt<U> operator /(const CheckedInt<U>& lhs,
const CheckedInt<U>& rhs);
template<typename U>
CheckedInt& operator /=(U rhs);
template<typename U>
friend CheckedInt<U> operator %(const CheckedInt<U>& lhs,
const CheckedInt<U>& rhs);
template<typename U>
CheckedInt& operator %=(U rhs);
CheckedInt operator -() const
{
return detail::NegateImpl<T>::negate(*this);
@ -726,6 +773,7 @@ MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +)
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -)
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *)
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Div, /)
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mod, %)
#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR
@ -786,6 +834,7 @@ MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=)
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=)
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=)
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=)
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(%, %=)
#undef MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS

Просмотреть файл

@ -190,6 +190,26 @@ void test()
VERIFY_IS_INVALID(one - min + min);
}
/* Modulo checks */
VERIFY_IS_INVALID(zero % zero);
VERIFY_IS_INVALID(one % zero);
VERIFY_IS_VALID(zero % one);
VERIFY_IS_VALID(zero % max);
VERIFY_IS_VALID(one % max);
VERIFY_IS_VALID(max % one);
VERIFY_IS_VALID(max % max);
if (isTSigned) {
const CheckedInt<T> minusOne = zero - one;
VERIFY_IS_INVALID(minusOne % minusOne);
VERIFY_IS_INVALID(zero % minusOne);
VERIFY_IS_INVALID(one % minusOne);
VERIFY_IS_INVALID(minusOne % one);
VERIFY_IS_INVALID(min % min);
VERIFY_IS_INVALID(zero % min);
VERIFY_IS_INVALID(min % one);
}
/* Unary operator- checks */
const CheckedInt<T> negOne = -one;
@ -347,10 +367,15 @@ void test()
VERIFY_IS_INVALID(someInvalid / one);
VERIFY_IS_INVALID(zero / someInvalid);
VERIFY_IS_INVALID(one / someInvalid);
VERIFY_IS_INVALID(someInvalid % zero);
VERIFY_IS_INVALID(someInvalid % one);
VERIFY_IS_INVALID(zero % someInvalid);
VERIFY_IS_INVALID(one % someInvalid);
VERIFY_IS_INVALID(someInvalid + someInvalid);
VERIFY_IS_INVALID(someInvalid - someInvalid);
VERIFY_IS_INVALID(someInvalid * someInvalid);
VERIFY_IS_INVALID(someInvalid / someInvalid);
VERIFY_IS_INVALID(someInvalid % someInvalid);
/* Check that mixing checked integers with plain integers in expressions is allowed */
@ -382,6 +407,13 @@ void test()
x /= 2;
VERIFY(x == two);
}
VERIFY(three % 2 == one);
VERIFY(3 % two == one);
{
CheckedInt<T> x = three;
x %= 2;
VERIFY(x == one);
}
VERIFY(one == 1);
VERIFY(1 == one);