Bug 881980 - Allow casting CheckedInts to other CheckedInt types. - r=bjacob,waldo

This commit is contained in:
Jeff Gilbert 2013-06-14 15:19:40 -07:00
parent bd9cabff89
commit cdca71e188
2 changed files with 47 additions and 11 deletions

View File

@ -566,7 +566,7 @@ struct NegateImpl<T, true>
CheckedInt<int8_t> x(-1);
// 1000 is of type int16_t, is found not to be in range for int8_t,
// x is invalid
CheckedInt<int8_t> x(int16_t(1000));
CheckedInt<int8_t> x(int16_t(1000));
// 3123456789 is of type uint32_t, is found not to be in range for int32_t,
// x is invalid
CheckedInt<int32_t> x(uint32_t(3123456789));
@ -628,6 +628,17 @@ class CheckedInt
"This type is not supported by CheckedInt");
}
template<typename U>
friend class CheckedInt;
template<typename U>
CheckedInt<U> toChecked() const
{
CheckedInt<U> ret(mValue);
ret.mIsValid = ret.mIsValid && mIsValid;
return ret;
}
/** Constructs a valid checked integer with initial value 0 */
CheckedInt() : mValue(0), mIsValid(true)
{

View File

@ -422,25 +422,50 @@ void test()
VERIFY_IS_FALSE(someInvalid == 1);
VERIFY_IS_FALSE(1 == someInvalid);
/* Check that construction of CheckedInt from an integer value of a mismatched type is checked */
// Check simple casting between different signedness and sizes.
{
CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(2).toChecked<uint8_t>();
VERIFY_IS_VALID(foo);
VERIFY(foo == 2);
}
{
CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(255).toChecked<uint8_t>();
VERIFY_IS_VALID(foo);
VERIFY(foo == 255);
}
{
CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(256).toChecked<uint8_t>();
VERIFY_IS_INVALID(foo);
}
{
CheckedInt<uint8_t> foo = CheckedInt<int8_t>(-2).toChecked<uint8_t>();
VERIFY_IS_INVALID(foo);
}
#define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \
// Check that construction of CheckedInt from an integer value of a mismatched type is checked
// Also check casting between all types.
#define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,V,PostVExpr) \
{ \
bool isUSigned = detail::IsSigned<U>::value; \
VERIFY_IS_VALID(CheckedInt<T>(U(0))); \
VERIFY_IS_VALID(CheckedInt<T>(U(1))); \
VERIFY_IS_VALID(CheckedInt<T>(U(100))); \
VERIFY_IS_VALID(CheckedInt<T>(V( 0)PostVExpr)); \
VERIFY_IS_VALID(CheckedInt<T>(V( 1)PostVExpr)); \
VERIFY_IS_VALID(CheckedInt<T>(V(100)PostVExpr)); \
if (isUSigned) \
VERIFY_IS_VALID_IF(CheckedInt<T>(U(-1)), isTSigned); \
VERIFY_IS_VALID_IF(CheckedInt<T>(V(-1)PostVExpr), isTSigned); \
if (sizeof(U) > sizeof(T)) \
VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value) + one.value())); \
VERIFY_IS_INVALID(CheckedInt<T>(V(detail::MaxValue<T>::value)PostVExpr + one.value())); \
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), \
isUSigned == false ? 1 : \
bool(isTSigned) == false ? 0 : \
sizeof(T) >= sizeof(U)); \
isUSigned == false ? 1 \
: bool(isTSigned) == false ? 0 \
: sizeof(T) >= sizeof(U)); \
}
#define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,U,+0) \
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,CheckedInt<U>,.toChecked<T>())
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int8_t)
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint8_t)
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int16_t)