| Index: base/numerics/safe_math_impl.h
|
| diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h
|
| index 15de619e76fae11ce35d8ecac5b950c4e7ba432b..c6fbf704cc6a75db199db406f6a16a598885ae36 100644
|
| --- a/base/numerics/safe_math_impl.h
|
| +++ b/base/numerics/safe_math_impl.h
|
| @@ -23,78 +23,6 @@ namespace internal {
|
| // but it may not be fast. This code could be split based on
|
| // platform/architecture and replaced with potentially faster implementations.
|
|
|
| -// Integer promotion templates used by the portable checked integer arithmetic.
|
| -template <size_t Size, bool IsSigned>
|
| -struct IntegerForSizeAndSign;
|
| -template <>
|
| -struct IntegerForSizeAndSign<1, true> {
|
| - typedef int8_t type;
|
| -};
|
| -template <>
|
| -struct IntegerForSizeAndSign<1, false> {
|
| - typedef uint8_t type;
|
| -};
|
| -template <>
|
| -struct IntegerForSizeAndSign<2, true> {
|
| - typedef int16_t type;
|
| -};
|
| -template <>
|
| -struct IntegerForSizeAndSign<2, false> {
|
| - typedef uint16_t type;
|
| -};
|
| -template <>
|
| -struct IntegerForSizeAndSign<4, true> {
|
| - typedef int32_t type;
|
| -};
|
| -template <>
|
| -struct IntegerForSizeAndSign<4, false> {
|
| - typedef uint32_t type;
|
| -};
|
| -template <>
|
| -struct IntegerForSizeAndSign<8, true> {
|
| - typedef int64_t type;
|
| -};
|
| -template <>
|
| -struct IntegerForSizeAndSign<8, false> {
|
| - typedef uint64_t type;
|
| - static_assert(sizeof(uintmax_t) == 8,
|
| - "Max integer size not supported for this toolchain.");
|
| -};
|
| -
|
| -// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to
|
| -// support 128-bit math, then the ArithmeticPromotion template below will need
|
| -// to be updated (or more likely replaced with a decltype expression).
|
| -
|
| -template <typename Integer>
|
| -struct UnsignedIntegerForSize {
|
| - typedef typename std::enable_if<
|
| - std::numeric_limits<Integer>::is_integer,
|
| - typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type type;
|
| -};
|
| -
|
| -template <typename Integer>
|
| -struct SignedIntegerForSize {
|
| - typedef typename std::enable_if<
|
| - std::numeric_limits<Integer>::is_integer,
|
| - typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type type;
|
| -};
|
| -
|
| -template <typename Integer>
|
| -struct TwiceWiderInteger {
|
| - typedef typename std::enable_if<
|
| - std::numeric_limits<Integer>::is_integer,
|
| - typename IntegerForSizeAndSign<
|
| - sizeof(Integer) * 2,
|
| - std::numeric_limits<Integer>::is_signed>::type>::type type;
|
| -};
|
| -
|
| -template <typename Integer>
|
| -struct PositionOfSignBit {
|
| - static const typename std::enable_if<std::numeric_limits<Integer>::is_integer,
|
| - size_t>::type value =
|
| - CHAR_BIT * sizeof(Integer) - 1;
|
| -};
|
| -
|
| // This is used for UnsignedAbs, where we need to support floating-point
|
| // template instantiations even though we don't actually support the operations.
|
| // However, there is no corresponding implementation of e.g. SafeUnsignedAbs,
|
| @@ -129,106 +57,6 @@ constexpr T BinaryComplement(T x) {
|
| return static_cast<T>(~x);
|
| }
|
|
|
| -enum ArithmeticPromotionCategory {
|
| - LEFT_PROMOTION, // Use the type of the left-hand argument.
|
| - RIGHT_PROMOTION, // Use the type of the right-hand argument.
|
| - MAX_EXPONENT_PROMOTION, // Use the type supporting the largest exponent.
|
| - BIG_ENOUGH_PROMOTION // Attempt to find a big enough type.
|
| -};
|
| -
|
| -template <ArithmeticPromotionCategory Promotion,
|
| - typename Lhs,
|
| - typename Rhs = Lhs>
|
| -struct ArithmeticPromotion;
|
| -
|
| -template <typename Lhs,
|
| - typename Rhs,
|
| - ArithmeticPromotionCategory Promotion =
|
| - (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value)
|
| - ? LEFT_PROMOTION
|
| - : RIGHT_PROMOTION>
|
| -struct MaxExponentPromotion;
|
| -
|
| -template <typename Lhs, typename Rhs>
|
| -struct MaxExponentPromotion<Lhs, Rhs, LEFT_PROMOTION> {
|
| - using type = Lhs;
|
| -};
|
| -
|
| -template <typename Lhs, typename Rhs>
|
| -struct MaxExponentPromotion<Lhs, Rhs, RIGHT_PROMOTION> {
|
| - using type = Rhs;
|
| -};
|
| -
|
| -template <typename Lhs,
|
| - typename Rhs = Lhs,
|
| - bool is_intmax_type =
|
| - std::is_integral<
|
| - typename MaxExponentPromotion<Lhs, Rhs>::type>::value &&
|
| - sizeof(typename MaxExponentPromotion<Lhs, Rhs>::type) ==
|
| - sizeof(intmax_t),
|
| - bool is_max_exponent =
|
| - StaticDstRangeRelationToSrcRange<
|
| - typename MaxExponentPromotion<Lhs, Rhs>::type,
|
| - Lhs>::value ==
|
| - NUMERIC_RANGE_CONTAINED&& StaticDstRangeRelationToSrcRange<
|
| - typename MaxExponentPromotion<Lhs, Rhs>::type,
|
| - Rhs>::value == NUMERIC_RANGE_CONTAINED>
|
| -struct BigEnoughPromotion;
|
| -
|
| -// The side with the max exponent is big enough.
|
| -template <typename Lhs, typename Rhs, bool is_intmax_type>
|
| -struct BigEnoughPromotion<Lhs, Rhs, is_intmax_type, true> {
|
| - using type = typename MaxExponentPromotion<Lhs, Rhs>::type;
|
| - static const bool is_contained = true;
|
| -};
|
| -
|
| -// We can use a twice wider type to fit.
|
| -template <typename Lhs, typename Rhs>
|
| -struct BigEnoughPromotion<Lhs, Rhs, false, false> {
|
| - using type = typename IntegerForSizeAndSign<
|
| - sizeof(typename MaxExponentPromotion<Lhs, Rhs>::type) * 2,
|
| - std::is_signed<Lhs>::value || std::is_signed<Rhs>::value>::type;
|
| - static const bool is_contained = true;
|
| -};
|
| -
|
| -// No type is large enough.
|
| -template <typename Lhs, typename Rhs>
|
| -struct BigEnoughPromotion<Lhs, Rhs, true, false> {
|
| - using type = typename MaxExponentPromotion<Lhs, Rhs>::type;
|
| - static const bool is_contained = false;
|
| -};
|
| -
|
| -// These are the supported promotion types.
|
| -
|
| -// Use the type supporting the largest exponent.
|
| -template <typename Lhs, typename Rhs>
|
| -struct ArithmeticPromotion<MAX_EXPONENT_PROMOTION, Lhs, Rhs> {
|
| - using type = typename MaxExponentPromotion<Lhs, Rhs>::type;
|
| - static const bool is_contained = true;
|
| -};
|
| -
|
| -// Attempt to find a big enough type.
|
| -template <typename Lhs, typename Rhs>
|
| -struct ArithmeticPromotion<BIG_ENOUGH_PROMOTION, Lhs, Rhs> {
|
| - using type = typename BigEnoughPromotion<Lhs, Rhs>::type;
|
| - static const bool is_contained = BigEnoughPromotion<Lhs, Rhs>::is_contained;
|
| -};
|
| -
|
| -// We can statically check if operations on the provided types can wrap, so we
|
| -// can skip the checked operations if they're not needed. So, for an integer we
|
| -// care if the destination type preserves the sign and is twice the width of
|
| -// the source.
|
| -template <typename T, typename Lhs, typename Rhs>
|
| -struct IsIntegerArithmeticSafe {
|
| - static const bool value = !std::numeric_limits<T>::is_iec559 &&
|
| - StaticDstRangeRelationToSrcRange<T, Lhs>::value ==
|
| - NUMERIC_RANGE_CONTAINED &&
|
| - sizeof(T) >= (2 * sizeof(Lhs)) &&
|
| - StaticDstRangeRelationToSrcRange<T, Rhs>::value !=
|
| - NUMERIC_RANGE_CONTAINED &&
|
| - sizeof(T) >= (2 * sizeof(Rhs));
|
| -};
|
| -
|
| // Probe for builtin math overflow support on Clang and version check on GCC.
|
| #if defined(__has_builtin)
|
| #define USE_OVERFLOW_BUILTINS (__has_builtin(__builtin_add_overflow))
|
| @@ -872,32 +700,6 @@ class CheckedNumericState<T, NUMERIC_FLOATING> {
|
| constexpr T value() const { return value_; }
|
| };
|
|
|
| -// The following are helper templates used in the CheckedNumeric class.
|
| -template <typename T>
|
| -class CheckedNumeric;
|
| -
|
| -// Used to treat CheckedNumeric and arithmetic underlying types the same.
|
| -template <typename T>
|
| -struct UnderlyingType {
|
| - using type = T;
|
| - static const bool is_numeric = std::is_arithmetic<T>::value;
|
| - static const bool is_checked = false;
|
| -};
|
| -
|
| -template <typename T>
|
| -struct UnderlyingType<CheckedNumeric<T>> {
|
| - using type = T;
|
| - static const bool is_numeric = true;
|
| - static const bool is_checked = true;
|
| -};
|
| -
|
| -template <typename L, typename R>
|
| -struct IsCheckedOp {
|
| - static const bool value =
|
| - UnderlyingType<L>::is_numeric && UnderlyingType<R>::is_numeric &&
|
| - (UnderlyingType<L>::is_checked || UnderlyingType<R>::is_checked);
|
| -};
|
| -
|
| template <template <typename, typename, typename> class M,
|
| typename L,
|
| typename R>
|
|
|