Chromium Code Reviews| Index: base/numerics/safe_math_impl.h |
| diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h |
| index 679cfa4e5a0e73c84b541128ed9f9e963b3f2262..57497a2abb4139db2ce223cead8fc49457b0c58d 100644 |
| --- a/base/numerics/safe_math_impl.h |
| +++ b/base/numerics/safe_math_impl.h |
| @@ -635,6 +635,19 @@ class CheckedNumericState<T, NUMERIC_INTEGER> { |
| bool is_valid_; |
| T value_; |
| + // Ensures that a type conversion does not trigger undefined behavior. |
| + template <typename Src> |
| + static constexpr T WellDefinedConversionOrZero(const Src value, |
| + const bool is_valid) { |
| + using SrcType = typename internal::UnderlyingType<Src>::type; |
| + return (std::is_integral<Src>::value || |
|
Nico
2016/12/06 14:03:37
Nice!
|
| + StaticDstRangeRelationToSrcRange<T, SrcType>::value == |
| + NUMERIC_RANGE_CONTAINED || |
|
Nico
2016/12/06 14:03:38
Isn't the is_integral check on Src stronger than t
jschuh
2016/12/06 15:07:55
Weird. Somehow I posted this in an incomplete stat
|
| + is_valid) |
| + ? static_cast<T>(value) |
| + : static_cast<T>(0); |
| + } |
| + |
| public: |
| template <typename Src, NumericRepresentation type> |
| friend class CheckedNumericState; |
| @@ -644,7 +657,7 @@ class CheckedNumericState<T, NUMERIC_INTEGER> { |
| template <typename Src> |
| constexpr CheckedNumericState(Src value, bool is_valid) |
| : is_valid_(is_valid && IsValueInRangeForNumericType<T>(value)), |
| - value_(is_valid_ ? static_cast<T>(value) : 0) { |
| + value_(WellDefinedConversionOrZero(value, is_valid_)) { |
| static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric."); |
| } |
| @@ -652,12 +665,12 @@ class CheckedNumericState<T, NUMERIC_INTEGER> { |
| template <typename Src> |
| constexpr CheckedNumericState(const CheckedNumericState<Src>& rhs) |
| : is_valid_(rhs.IsValid()), |
| - value_(is_valid_ ? static_cast<T>(rhs.value()) : 0) {} |
| + value_(WellDefinedConversionOrZero(rhs.value(), is_valid_)) {} |
| template <typename Src> |
| constexpr explicit CheckedNumericState(Src value) |
| : is_valid_(IsValueInRangeForNumericType<T>(value)), |
| - value_(is_valid_ ? static_cast<T>(value) : 0) {} |
| + value_(WellDefinedConversionOrZero(value, is_valid_)) {} |
| constexpr bool is_valid() const { return is_valid_; } |
| constexpr T value() const { return value_; } |