| Index: base/numerics/safe_math_impl.h
|
| diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h
|
| index 71fc278b297c26f7bf51ec695a3baacdb977e961..0e21b6b130b5ae1df5075fd82871a77d2646868c 100644
|
| --- a/base/numerics/safe_math_impl.h
|
| +++ b/base/numerics/safe_math_impl.h
|
| @@ -256,6 +256,15 @@ struct IsIntegerArithmeticSafe {
|
| 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))
|
| +#elif defined(__GNUC__)
|
| +#define USE_OVERFLOW_BUILTINS (__GNUC__ >= 5)
|
| +#else
|
| +#define USE_OVERFLOW_BUILTINS (0)
|
| +#endif
|
| +
|
| // Here are the actual portable checked integer math implementations.
|
| // TODO(jschuh): Break this code out from the enable_if pattern and find a clean
|
| // way to coalesce things into the CheckedNumericState specializations below.
|
| @@ -285,6 +294,9 @@ typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
| std::numeric_limits<V>::is_integer,
|
| bool>::type
|
| CheckedAdd(T x, U y, V* result) {
|
| +#if USE_OVERFLOW_BUILTINS
|
| + return !__builtin_add_overflow(x, y, result);
|
| +#else
|
| using Promotion =
|
| typename ArithmeticPromotion<BIG_ENOUGH_PROMOTION, T, U>::type;
|
| Promotion presult;
|
| @@ -301,6 +313,7 @@ CheckedAdd(T x, U y, V* result) {
|
| }
|
| *result = static_cast<V>(presult);
|
| return is_valid && IsValueInRangeForNumericType<V>(presult);
|
| +#endif
|
| }
|
|
|
| template <typename T>
|
| @@ -327,6 +340,9 @@ typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
| std::numeric_limits<V>::is_integer,
|
| bool>::type
|
| CheckedSub(T x, U y, V* result) {
|
| +#if USE_OVERFLOW_BUILTINS
|
| + return !__builtin_sub_overflow(x, y, result);
|
| +#else
|
| using Promotion =
|
| typename ArithmeticPromotion<BIG_ENOUGH_PROMOTION, T, U>::type;
|
| Promotion presult;
|
| @@ -343,6 +359,7 @@ CheckedSub(T x, U y, V* result) {
|
| }
|
| *result = static_cast<V>(presult);
|
| return is_valid && IsValueInRangeForNumericType<V>(presult);
|
| +#endif
|
| }
|
|
|
| // Integer multiplication is a bit complicated. In the fast case we just
|
| @@ -406,6 +423,20 @@ typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
| std::numeric_limits<V>::is_integer,
|
| bool>::type
|
| CheckedMul(T x, U y, V* result) {
|
| +#if USE_OVERFLOW_BUILTINS
|
| +#if defined(__clang__)
|
| + // TODO(jschuh): Get the Clang runtime library issues sorted out so we can
|
| + // support full-width, mixed-sign multiply builtins. https://crbug.com/613003
|
| + static const bool kUseMaxInt =
|
| + sizeof(__typeof__(x * y)) < sizeof(intptr_t) ||
|
| + (sizeof(__typeof__(x * y)) == sizeof(intptr_t) &&
|
| + std::is_signed<T>::value == std::is_signed<U>::value);
|
| +#else
|
| + static const bool kUseMaxInt = true;
|
| +#endif
|
| + if (kUseMaxInt)
|
| + return !__builtin_mul_overflow(x, y, result);
|
| +#endif
|
| using Promotion =
|
| typename ArithmeticPromotion<BIG_ENOUGH_PROMOTION, T, U>::type;
|
| Promotion presult;
|
| @@ -424,6 +455,9 @@ CheckedMul(T x, U y, V* result) {
|
| return is_valid && IsValueInRangeForNumericType<V>(presult);
|
| }
|
|
|
| +// Avoid poluting the namespace once we're done with the macro.
|
| +#undef USE_OVERFLOW_BUILTINS
|
| +
|
| // Division just requires a check for a zero denominator or an invalid negation
|
| // on signed min/-1.
|
| template <typename T>
|
|
|