Skip to content

Commit d88ddfe

Browse files
author
Benoit Jacob
committed
Bug 732875 - Further CheckedInt tweaks - r=Ms2ger,jwalden
1 parent 18deb8a commit d88ddfe

File tree

2 files changed

+29
-39
lines changed

2 files changed

+29
-39
lines changed

mfbt/CheckedInt.h

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -210,31 +210,26 @@ struct PositionOfSignBit
210210
template<typename IntegerType>
211211
struct MinValue
212212
{
213-
static IntegerType value()
214-
{
215-
// Bitwise ops may return a larger type, that's why we cast explicitly.
216-
// In C++, left bit shifts on signed values is undefined by the standard
217-
// unless the shifted value is representable.
218-
// Notice that signed-to-unsigned conversions are always well-defined in
219-
// the standard as the value congruent to 2**n, as expected. By contrast,
220-
// unsigned-to-signed is only well-defined if the value is representable.
221-
return IsSigned<IntegerType>::value
222-
? IntegerType(typename UnsignedType<IntegerType>::Type(1)
223-
<< PositionOfSignBit<IntegerType>::value)
224-
: IntegerType(0);
225-
}
213+
// Bitwise ops may return a larger type, that's why we cast explicitly.
214+
// In C++, left bit shifts on signed values is undefined by the standard
215+
// unless the shifted value is representable.
216+
// Notice that signed-to-unsigned conversions are always well-defined in
217+
// the standard as the value congruent to 2**n, as expected. By contrast,
218+
// unsigned-to-signed is only well-defined if the value is representable.
219+
static const IntegerType value =
220+
IsSigned<IntegerType>::value
221+
? IntegerType(typename UnsignedType<IntegerType>::Type(1)
222+
<< PositionOfSignBit<IntegerType>::value)
223+
: IntegerType(0);
226224
};
227225

228226
template<typename IntegerType>
229227
struct MaxValue
230228
{
231-
static IntegerType value()
232-
{
233-
// Tricksy, but covered by the unit test.
234-
// Relies heavily on the return type of MinValue<IntegerType>::value()
235-
// being IntegerType.
236-
return ~MinValue<IntegerType>::value();
237-
}
229+
// Tricksy, but covered by the unit test.
230+
// Relies heavily on the type of MinValue<IntegerType>::value
231+
// being IntegerType.
232+
static const IntegerType value = ~MinValue<IntegerType>::value;
238233
};
239234

240235
/*
@@ -278,8 +273,7 @@ struct IsInRangeImpl<T, U, true, true>
278273
{
279274
static bool run(U x)
280275
{
281-
return x <= MaxValue<T>::value() &&
282-
x >= MinValue<T>::value();
276+
return x <= MaxValue<T>::value && x >= MinValue<T>::value;
283277
}
284278
};
285279

@@ -288,7 +282,7 @@ struct IsInRangeImpl<T, U, false, false>
288282
{
289283
static bool run(U x)
290284
{
291-
return x <= MaxValue<T>::value();
285+
return x <= MaxValue<T>::value;
292286
}
293287
};
294288

@@ -297,9 +291,7 @@ struct IsInRangeImpl<T, U, true, false>
297291
{
298292
static bool run(U x)
299293
{
300-
return sizeof(T) > sizeof(U)
301-
? true
302-
: x <= U(MaxValue<T>::value());
294+
return sizeof(T) > sizeof(U) || x <= U(MaxValue<T>::value);
303295
}
304296
};
305297

@@ -310,7 +302,7 @@ struct IsInRangeImpl<T, U, false, true>
310302
{
311303
return sizeof(T) >= sizeof(U)
312304
? x >= 0
313-
: x >= 0 && x <= U(MaxValue<T>::value());
305+
: x >= 0 && x <= U(MaxValue<T>::value);
314306
}
315307
};
316308

@@ -366,8 +358,8 @@ struct IsMulValidImpl<T, true, false>
366358
{
367359
static bool run(T x, T y)
368360
{
369-
const T max = MaxValue<T>::value();
370-
const T min = MinValue<T>::value();
361+
const T max = MaxValue<T>::value;
362+
const T min = MinValue<T>::value;
371363

372364
if (x == 0 || y == 0)
373365
return true;
@@ -390,8 +382,7 @@ struct IsMulValidImpl<T, false, false>
390382
{
391383
static bool run(T x, T y)
392384
{
393-
return y == 0 ||
394-
x <= MaxValue<T>::value() / y;
385+
return y == 0 || x <= MaxValue<T>::value / y;
395386
}
396387
};
397388

@@ -407,9 +398,8 @@ inline bool
407398
IsDivValid(T x, T y)
408399
{
409400
// Keep in mind that in the signed case, min/-1 is invalid because abs(min)>max.
410-
return IsSigned<T>::value
411-
? (y != 0) && (x != MinValue<T>::value() || y != T(-1))
412-
: y != 0;
401+
return y != 0 &&
402+
!(IsSigned<T>::value && x == MinValue<T>::value && y == T(-1));
413403
}
414404

415405
// This is just to shut up msvc warnings about negating unsigned ints.

mfbt/tests/TestCheckedInt.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ void test()
9696
VERIFY(sizeof(unsignedT) == sizeof(T));
9797
VERIFY(detail::IsSigned<unsignedT>::value == false);
9898

99-
const CheckedInt<T> max(detail::MaxValue<T>::value());
100-
const CheckedInt<T> min(detail::MinValue<T>::value());
99+
const CheckedInt<T> max(detail::MaxValue<T>::value);
100+
const CheckedInt<T> min(detail::MinValue<T>::value);
101101

102102
// Check min() and max(), since they are custom implementations and a mistake there
103103
// could potentially NOT be caught by any other tests... while making everything wrong!
@@ -394,10 +394,10 @@ void test()
394394
if (isUSigned) \
395395
VERIFY_IS_VALID_IF(CheckedInt<T>(U(-1)), isTSigned); \
396396
if (sizeof(U) > sizeof(T)) \
397-
VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value())+1)); \
398-
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value()), \
397+
VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value) + 1)); \
398+
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value), \
399399
(sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (isUSigned || !isTSigned)))); \
400-
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value()), \
400+
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value), \
401401
isUSigned == false ? 1 : \
402402
bool(isTSigned) == false ? 0 : \
403403
sizeof(T) >= sizeof(U)); \

0 commit comments

Comments
 (0)