Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(632)

Unified Diff: base/numerics/safe_math_impl.h

Issue 2509233003: Use GCC/Clang builtins for Checked(Add|Sub|Mul) (Closed)
Patch Set: clang compile fix (last time) Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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>
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698