Skip to content

Commit 3049ca7

Browse files
committed
Bug 881980 - Allow casting CheckedInts to other CheckedInt types. - r=bjacob,waldo
1 parent 75ab2ff commit 3049ca7

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

mfbt/CheckedInt.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ struct NegateImpl<T, true>
566566
CheckedInt<int8_t> x(-1);
567567
// 1000 is of type int16_t, is found not to be in range for int8_t,
568568
// x is invalid
569-
CheckedInt<int8_t> x(int16_t(1000));
569+
CheckedInt<int8_t> x(int16_t(1000));
570570
// 3123456789 is of type uint32_t, is found not to be in range for int32_t,
571571
// x is invalid
572572
CheckedInt<int32_t> x(uint32_t(3123456789));
@@ -628,6 +628,17 @@ class CheckedInt
628628
"This type is not supported by CheckedInt");
629629
}
630630

631+
template<typename U>
632+
friend class CheckedInt;
633+
634+
template<typename U>
635+
CheckedInt<U> toChecked() const
636+
{
637+
CheckedInt<U> ret(mValue);
638+
ret.mIsValid = ret.mIsValid && mIsValid;
639+
return ret;
640+
}
641+
631642
/** Constructs a valid checked integer with initial value 0 */
632643
CheckedInt() : mValue(0), mIsValid(true)
633644
{

mfbt/tests/TestCheckedInt.cpp

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -422,25 +422,50 @@ void test()
422422
VERIFY_IS_FALSE(someInvalid == 1);
423423
VERIFY_IS_FALSE(1 == someInvalid);
424424

425-
/* Check that construction of CheckedInt from an integer value of a mismatched type is checked */
425+
// Check simple casting between different signedness and sizes.
426+
{
427+
CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(2).toChecked<uint8_t>();
428+
VERIFY_IS_VALID(foo);
429+
VERIFY(foo == 2);
430+
}
431+
{
432+
CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(255).toChecked<uint8_t>();
433+
VERIFY_IS_VALID(foo);
434+
VERIFY(foo == 255);
435+
}
436+
{
437+
CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(256).toChecked<uint8_t>();
438+
VERIFY_IS_INVALID(foo);
439+
}
440+
{
441+
CheckedInt<uint8_t> foo = CheckedInt<int8_t>(-2).toChecked<uint8_t>();
442+
VERIFY_IS_INVALID(foo);
443+
}
426444

427-
#define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \
445+
// Check that construction of CheckedInt from an integer value of a mismatched type is checked
446+
// Also check casting between all types.
447+
448+
#define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,V,PostVExpr) \
428449
{ \
429450
bool isUSigned = detail::IsSigned<U>::value; \
430-
VERIFY_IS_VALID(CheckedInt<T>(U(0))); \
431-
VERIFY_IS_VALID(CheckedInt<T>(U(1))); \
432-
VERIFY_IS_VALID(CheckedInt<T>(U(100))); \
451+
VERIFY_IS_VALID(CheckedInt<T>(V( 0)PostVExpr)); \
452+
VERIFY_IS_VALID(CheckedInt<T>(V( 1)PostVExpr)); \
453+
VERIFY_IS_VALID(CheckedInt<T>(V(100)PostVExpr)); \
433454
if (isUSigned) \
434-
VERIFY_IS_VALID_IF(CheckedInt<T>(U(-1)), isTSigned); \
455+
VERIFY_IS_VALID_IF(CheckedInt<T>(V(-1)PostVExpr), isTSigned); \
435456
if (sizeof(U) > sizeof(T)) \
436-
VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value) + one.value())); \
457+
VERIFY_IS_INVALID(CheckedInt<T>(V(detail::MaxValue<T>::value)PostVExpr + one.value())); \
437458
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value), \
438459
(sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (isUSigned || !isTSigned)))); \
439460
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value), \
440-
isUSigned == false ? 1 : \
441-
bool(isTSigned) == false ? 0 : \
442-
sizeof(T) >= sizeof(U)); \
461+
isUSigned == false ? 1 \
462+
: bool(isTSigned) == false ? 0 \
463+
: sizeof(T) >= sizeof(U)); \
443464
}
465+
#define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \
466+
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,U,+0) \
467+
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,CheckedInt<U>,.toChecked<T>())
468+
444469
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int8_t)
445470
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint8_t)
446471
VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int16_t)

0 commit comments

Comments
 (0)