| Index: base/numerics/safe_conversions_impl.h
|
| diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h
|
| index fca2e87eaf4f4f2f91e2da5afbf345d08759069a..24357fd6a5744341bd274630959ff35de85f009e 100644
|
| --- a/base/numerics/safe_conversions_impl.h
|
| +++ b/base/numerics/safe_conversions_impl.h
|
| @@ -136,18 +136,11 @@ struct StaticDstRangeRelationToSrcRange<Dst,
|
| static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
|
| };
|
|
|
| -enum RangeConstraint {
|
| - RANGE_VALID = 0x0, // Value can be represented by the destination type.
|
| - RANGE_UNDERFLOW = 0x1, // Value would underflow.
|
| - RANGE_OVERFLOW = 0x2, // Value would overflow.
|
| - RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
|
| -};
|
| -
|
| // This class wraps the range constraints as separate booleans so the compiler
|
| // can identify constants and eliminate unused code paths.
|
| class RangeCheck {
|
| public:
|
| - constexpr RangeCheck(bool is_in_upper_bound, bool is_in_lower_bound)
|
| + constexpr RangeCheck(bool is_in_lower_bound, bool is_in_upper_bound)
|
| : is_underflow_(!is_in_lower_bound), is_overflow_(!is_in_upper_bound) {}
|
| constexpr RangeCheck() : is_underflow_(0), is_overflow_(0) {}
|
| constexpr bool IsValid() const { return !is_overflow_ && !is_underflow_; }
|
| @@ -156,21 +149,19 @@ class RangeCheck {
|
| constexpr bool IsUnderflow() const { return !is_overflow_ && is_underflow_; }
|
| constexpr bool IsOverflowFlagSet() const { return is_overflow_; }
|
| constexpr bool IsUnderflowFlagSet() const { return is_underflow_; }
|
| -
|
| - // These are some wrappers to make the tests a bit cleaner.
|
| - constexpr operator RangeConstraint() const {
|
| - return static_cast<RangeConstraint>(static_cast<int>(is_overflow_) << 1 |
|
| - static_cast<int>(is_underflow_));
|
| + constexpr bool operator==(const RangeCheck rhs) const {
|
| + return is_underflow_ == rhs.is_underflow_ &&
|
| + is_overflow_ == rhs.is_overflow_;
|
| }
|
| - constexpr bool operator==(const RangeConstraint rhs) const {
|
| - return rhs == static_cast<RangeConstraint>(*this);
|
| + constexpr bool operator!=(const RangeCheck rhs) const {
|
| + return !(*this == rhs);
|
| }
|
|
|
| private:
|
| // Do not change the order of these member variables. The integral conversion
|
| // optimization depends on this exact order.
|
| - const bool is_underflow_ : 1;
|
| - const bool is_overflow_ : 1;
|
| + const bool is_underflow_;
|
| + const bool is_overflow_;
|
| };
|
|
|
| // The following helper template addresses a corner case in range checks for
|
| @@ -265,10 +256,10 @@ struct DstRangeRelationToSrcRangeImpl<Dst,
|
| using SrcLimits = std::numeric_limits<Src>;
|
| using DstLimits = NarrowingRange<Dst, Src, Bounds>;
|
| return RangeCheck(
|
| - static_cast<Dst>(SrcLimits::max()) <= DstLimits::max() ||
|
| - static_cast<Dst>(value) <= DstLimits::max(),
|
| static_cast<Dst>(SrcLimits::lowest()) >= DstLimits::lowest() ||
|
| - static_cast<Dst>(value) >= DstLimits::lowest());
|
| + static_cast<Dst>(value) >= DstLimits::lowest(),
|
| + static_cast<Dst>(SrcLimits::max()) <= DstLimits::max() ||
|
| + static_cast<Dst>(value) <= DstLimits::max());
|
| }
|
| };
|
|
|
| @@ -283,7 +274,7 @@ struct DstRangeRelationToSrcRangeImpl<Dst,
|
| NUMERIC_RANGE_NOT_CONTAINED> {
|
| static constexpr RangeCheck Check(Src value) {
|
| using DstLimits = NarrowingRange<Dst, Src, Bounds>;
|
| - return RangeCheck(value <= DstLimits::max(), value >= DstLimits::lowest());
|
| + return RangeCheck(value >= DstLimits::lowest(), value <= DstLimits::max());
|
| }
|
| };
|
|
|
| @@ -299,8 +290,8 @@ struct DstRangeRelationToSrcRangeImpl<Dst,
|
| static constexpr RangeCheck Check(Src value) {
|
| using DstLimits = NarrowingRange<Dst, Src, Bounds>;
|
| return RangeCheck(
|
| - value <= DstLimits::max(),
|
| - DstLimits::lowest() == Dst(0) || value >= DstLimits::lowest());
|
| + DstLimits::lowest() == Dst(0) || value >= DstLimits::lowest(),
|
| + value <= DstLimits::max());
|
| }
|
| };
|
|
|
| @@ -315,11 +306,11 @@ struct DstRangeRelationToSrcRangeImpl<Dst,
|
| static constexpr RangeCheck Check(Src value) {
|
| using DstLimits = NarrowingRange<Dst, Src, Bounds>;
|
| using Promotion = decltype(Src() + Dst());
|
| - return RangeCheck(static_cast<Promotion>(value) <=
|
| - static_cast<Promotion>(DstLimits::max()),
|
| - DstLimits::lowest() <= Dst(0) ||
|
| + return RangeCheck(DstLimits::lowest() <= Dst(0) ||
|
| static_cast<Promotion>(value) >=
|
| - static_cast<Promotion>(DstLimits::lowest()));
|
| + static_cast<Promotion>(DstLimits::lowest()),
|
| + static_cast<Promotion>(value) <=
|
| + static_cast<Promotion>(DstLimits::max()));
|
| }
|
| };
|
|
|
| @@ -337,12 +328,12 @@ struct DstRangeRelationToSrcRangeImpl<Dst,
|
| using DstLimits = NarrowingRange<Dst, Src, Bounds>;
|
| using Promotion = decltype(Src() + Dst());
|
| return RangeCheck(
|
| + value >= Src(0) && (DstLimits::lowest() == 0 ||
|
| + static_cast<Dst>(value) >= DstLimits::lowest()),
|
| static_cast<Promotion>(SrcLimits::max()) <=
|
| static_cast<Promotion>(DstLimits::max()) ||
|
| static_cast<Promotion>(value) <=
|
| - static_cast<Promotion>(DstLimits::max()),
|
| - value >= Src(0) && (DstLimits::lowest() == 0 ||
|
| - static_cast<Dst>(value) >= DstLimits::lowest()));
|
| + static_cast<Promotion>(DstLimits::max()));
|
| }
|
| };
|
|
|
| @@ -615,7 +606,7 @@ constexpr bool IsLessImpl(const L lhs,
|
| const R rhs,
|
| const RangeCheck l_range,
|
| const RangeCheck r_range) {
|
| - return l_range == RANGE_UNDERFLOW || r_range == RANGE_OVERFLOW ||
|
| + return l_range.IsUnderflow() || r_range.IsOverflow() ||
|
| (l_range == r_range &&
|
| static_cast<decltype(lhs + rhs)>(lhs) <
|
| static_cast<decltype(lhs + rhs)>(rhs));
|
| @@ -636,7 +627,7 @@ constexpr bool IsLessOrEqualImpl(const L lhs,
|
| const R rhs,
|
| const RangeCheck l_range,
|
| const RangeCheck r_range) {
|
| - return l_range == RANGE_UNDERFLOW || r_range == RANGE_OVERFLOW ||
|
| + return l_range.IsUnderflow() || r_range.IsOverflow() ||
|
| (l_range == r_range &&
|
| static_cast<decltype(lhs + rhs)>(lhs) <=
|
| static_cast<decltype(lhs + rhs)>(rhs));
|
| @@ -657,7 +648,7 @@ constexpr bool IsGreaterImpl(const L lhs,
|
| const R rhs,
|
| const RangeCheck l_range,
|
| const RangeCheck r_range) {
|
| - return l_range == RANGE_OVERFLOW || r_range == RANGE_UNDERFLOW ||
|
| + return l_range.IsOverflow() || r_range.IsUnderflow() ||
|
| (l_range == r_range &&
|
| static_cast<decltype(lhs + rhs)>(lhs) >
|
| static_cast<decltype(lhs + rhs)>(rhs));
|
| @@ -678,7 +669,7 @@ constexpr bool IsGreaterOrEqualImpl(const L lhs,
|
| const R rhs,
|
| const RangeCheck l_range,
|
| const RangeCheck r_range) {
|
| - return l_range == RANGE_OVERFLOW || r_range == RANGE_UNDERFLOW ||
|
| + return l_range.IsOverflow() || r_range.IsUnderflow() ||
|
| (l_range == r_range &&
|
| static_cast<decltype(lhs + rhs)>(lhs) >=
|
| static_cast<decltype(lhs + rhs)>(rhs));
|
|
|