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

Unified Diff: base/numerics/checked_math_impl.h

Issue 2945433003: Add ClampedNumeric templates (Closed)
Patch Set: final Created 3 years, 5 months 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 | « base/numerics/checked_math.h ('k') | base/numerics/clamped_math.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/numerics/checked_math_impl.h
diff --git a/base/numerics/checked_math_impl.h b/base/numerics/checked_math_impl.h
index 0492d1dbb5540e4f7a90a51bf4217a0a07388b27..bf3a3077efb75341285c7a480f757839238f8d83 100644
--- a/base/numerics/checked_math_impl.h
+++ b/base/numerics/checked_math_impl.h
@@ -182,17 +182,19 @@ struct CheckedMulOp<T,
return !__builtin_mul_overflow(x, y, result);
#endif
using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
+ // Verify the destination type can hold the result (always true for 0).
+ if (!(IsValueInRangeForNumericType<Promotion>(x) &&
+ IsValueInRangeForNumericType<Promotion>(y)) &&
+ x && y) {
+ return false;
+ }
Promotion presult;
- // Fail if either operand is out of range for the promoted type.
- // TODO(jschuh): This could be made to work for a broader range of values.
- bool is_valid = IsValueInRangeForNumericType<Promotion>(x) &&
- IsValueInRangeForNumericType<Promotion>(y);
-
+ bool is_valid = true;
if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
} else {
- is_valid &= CheckedMulImpl(static_cast<Promotion>(x),
- static_cast<Promotion>(y), &presult);
+ is_valid = CheckedMulImpl(static_cast<Promotion>(x),
+ static_cast<Promotion>(y), &presult);
}
*result = static_cast<V>(presult);
return is_valid && IsValueInRangeForNumericType<V>(presult);
@@ -242,7 +244,7 @@ struct CheckedDivOp<T,
template <typename T>
bool CheckedModImpl(T x, T y, T* result) {
static_assert(std::is_integral<T>::value, "Type must be integral");
- if (y > 0) {
+ if (y) {
*result = static_cast<T>(x % y);
return true;
}
@@ -283,15 +285,15 @@ struct CheckedLshOp<T,
using result_type = T;
template <typename V>
static bool Do(T x, U shift, V* result) {
- using ShiftType = typename std::make_unsigned<T>::type;
- static const ShiftType kBitWidth = IntegerBitsPlusSign<T>::value;
- const ShiftType real_shift = static_cast<ShiftType>(shift);
// Signed shift is not legal on negative values.
- if (!IsValueNegative(x) && real_shift < kBitWidth) {
+ if (!IsValueNegative(x) &&
+ as_unsigned(shift) < IntegerBitsPlusSign<T>::value) {
// Just use a multiplication because it's easy.
// TODO(jschuh): This could probably be made more efficient.
- if (!std::is_signed<T>::value || real_shift != kBitWidth - 1)
- return CheckedMulOp<T, T>::Do(x, static_cast<T>(1) << shift, result);
+ if (!std::is_signed<T>::value ||
+ as_unsigned(shift) < std::numeric_limits<T>::digits)
+ return CheckedMulOp<T, T>::Do(x, T(1) << shift, result);
+ *result = 0;
return !x; // Special case zero for a full width signed shift.
}
return false;
@@ -313,8 +315,7 @@ struct CheckedRshOp<T,
template <typename V>
static bool Do(T x, U shift, V* result) {
// Use the type conversion push negative values out of range.
- using ShiftType = typename std::make_unsigned<T>::type;
- if (static_cast<ShiftType>(shift) < IntegerBitsPlusSign<T>::value) {
+ if (as_unsigned(shift) < IntegerBitsPlusSign<T>::value) {
T tmp = x >> shift;
*result = static_cast<V>(tmp);
return IsValueInRangeForNumericType<V>(tmp);
« no previous file with comments | « base/numerics/checked_math.h ('k') | base/numerics/clamped_math.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698