| Index: base/numerics/safe_math_impl.h | 
| diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h | 
| index 7aab62dc52221b79d3959b682b0271a118915aa1..4b9877a386965cceda85a5c5c2a6f2b62186f235 100644 | 
| --- a/base/numerics/safe_math_impl.h | 
| +++ b/base/numerics/safe_math_impl.h | 
| @@ -474,6 +474,46 @@ struct CheckedXorOp<T, | 
| } | 
| }; | 
|  | 
| +// Max doesn't really need to be implemented this way because it can't fail, | 
| +// but it makes the code much cleaner to use the MathOp wrappers. | 
| +template <typename T, typename U, class Enable = void> | 
| +struct CheckedMaxOp {}; | 
| + | 
| +template <typename T, typename U> | 
| +struct CheckedMaxOp< | 
| +    T, | 
| +    U, | 
| +    typename std::enable_if<std::is_arithmetic<T>::value && | 
| +                            std::is_arithmetic<U>::value>::type> { | 
| +  using result_type = typename MaxExponentPromotion<T, U>::type; | 
| +  template <typename V = result_type> | 
| +  static bool Do(T x, U y, V* result) { | 
| +    *result = IsGreater<T, U>::Test(x, y) ? static_cast<result_type>(x) | 
| +                                          : static_cast<result_type>(y); | 
| +    return true; | 
| +  } | 
| +}; | 
| + | 
| +// Min doesn't really need to be implemented this way because it can't fail, | 
| +// but it makes the code much cleaner to use the MathOp wrappers. | 
| +template <typename T, typename U, class Enable = void> | 
| +struct CheckedMinOp {}; | 
| + | 
| +template <typename T, typename U> | 
| +struct CheckedMinOp< | 
| +    T, | 
| +    U, | 
| +    typename std::enable_if<std::is_arithmetic<T>::value && | 
| +                            std::is_arithmetic<U>::value>::type> { | 
| +  using result_type = typename LowestValuePromotion<T, U>::type; | 
| +  template <typename V = result_type> | 
| +  static bool Do(T x, U y, V* result) { | 
| +    *result = IsLess<T, U>::Test(x, y) ? static_cast<result_type>(x) | 
| +                                       : static_cast<result_type>(y); | 
| +    return true; | 
| +  } | 
| +}; | 
| + | 
| template <typename T> | 
| typename std::enable_if<std::numeric_limits<T>::is_integer && | 
| std::numeric_limits<T>::is_signed, | 
| @@ -688,7 +728,12 @@ class CheckedNumericState<T, NUMERIC_FLOATING> { | 
| constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs) | 
| : value_(static_cast<T>(rhs.value())) {} | 
|  | 
| -  constexpr bool is_valid() const { return std::isfinite(value_); } | 
| +  constexpr bool is_valid() const { | 
| +    // Written this way because std::isfinite is not reliably constexpr. | 
| +    // TODO(jschuh): Fix this if the libraries ever get fixed. | 
| +    return value_ <= std::numeric_limits<T>::max() && | 
| +           value_ >= std::numeric_limits<T>::lowest(); | 
| +  } | 
| constexpr T value() const { return value_; } | 
| }; | 
|  | 
|  |