Update third_party/base/numerics
Update to the latest numerics code from Chromium. Pick up
https://crrev.com/1008363, https://crrev.com/1040096, and
https://crrev.com/1092231.
Change-Id: I41d4160afd7a209a802b68e0e244eeddd5fe92b7
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/105450
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/third_party/base/numerics/README.pdfium b/third_party/base/numerics/README.pdfium
index 636f2df..8d73ef3 100644
--- a/third_party/base/numerics/README.pdfium
+++ b/third_party/base/numerics/README.pdfium
@@ -4,4 +4,3 @@
Local Modifications:
Namespaced from base:: to pdfium::base:: in all files.
-Remove ostream operators in safe_conversions.h and clamped_math.h
diff --git a/third_party/base/numerics/checked_math.h b/third_party/base/numerics/checked_math.h
index eb0d9a5..9eb5b07 100644
--- a/third_party/base/numerics/checked_math.h
+++ b/third_party/base/numerics/checked_math.h
@@ -34,19 +34,24 @@
constexpr CheckedNumeric(const CheckedNumeric<Src>& rhs)
: state_(rhs.state_.value(), rhs.IsValid()) {}
+ // Strictly speaking, this is not necessary, but declaring this allows class
+ // template argument deduction to be used so that it is possible to simply
+ // write `CheckedNumeric(777)` instead of `CheckedNumeric<int>(777)`.
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr CheckedNumeric(T value) : state_(value) {}
+
// This is not an explicit constructor because we implicitly upgrade regular
// numerics to CheckedNumerics to make them easier to use.
- template <typename Src>
- constexpr CheckedNumeric(Src value) // NOLINT(runtime/explicit)
- : state_(value) {
- static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric.");
- }
+ template <typename Src,
+ typename = std::enable_if_t<std::is_arithmetic<Src>::value>>
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr CheckedNumeric(Src value) : state_(value) {}
// This is not an explicit constructor because we want a seamless conversion
// from StrictNumeric types.
template <typename Src>
- constexpr CheckedNumeric(
- StrictNumeric<Src> value) // NOLINT(runtime/explicit)
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr CheckedNumeric(StrictNumeric<Src> value)
: state_(static_cast<Src>(value)) {}
// IsValid() - The public API to test if a CheckedNumeric is currently valid.
diff --git a/third_party/base/numerics/checked_math_impl.h b/third_party/base/numerics/checked_math_impl.h
index e61053d..47c73d5 100644
--- a/third_party/base/numerics/checked_math_impl.h
+++ b/third_party/base/numerics/checked_math_impl.h
@@ -165,7 +165,7 @@
if (uy > UnsignedDst(!std::is_signed<T>::value || is_negative) &&
ux > (std::numeric_limits<T>::max() + UnsignedDst(is_negative)) / uy)
return false;
- *result = is_negative ? 0 - uresult : uresult;
+ *result = static_cast<T>(is_negative ? 0 - uresult : uresult);
return true;
}
@@ -195,7 +195,10 @@
bool is_valid = true;
if (CheckedMulFastOp<Promotion, Promotion>::is_supported) {
// The fast op may be available with the promoted type.
- is_valid = CheckedMulFastOp<Promotion, Promotion>::Do(x, y, &presult);
+ // The casts here are safe because of the "value in range" conditional
+ // above.
+ is_valid = CheckedMulFastOp<Promotion, Promotion>::Do(
+ static_cast<Promotion>(x), static_cast<Promotion>(y), &presult);
} else if (IsIntegerArithmeticSafe<Promotion, T, U>::value) {
presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
} else {
diff --git a/third_party/base/numerics/clamped_math.h b/third_party/base/numerics/clamped_math.h
index ffa48f0..019bc31 100644
--- a/third_party/base/numerics/clamped_math.h
+++ b/third_party/base/numerics/clamped_math.h
@@ -34,19 +34,25 @@
template <typename Src>
friend class ClampedNumeric;
+ // Strictly speaking, this is not necessary, but declaring this allows class
+ // template argument deduction to be used so that it is possible to simply
+ // write `ClampedNumeric(777)` instead of `ClampedNumeric<int>(777)`.
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr ClampedNumeric(T value) : value_(value) {}
+
// This is not an explicit constructor because we implicitly upgrade regular
// numerics to ClampedNumerics to make them easier to use.
template <typename Src>
- constexpr ClampedNumeric(Src value) // NOLINT(runtime/explicit)
- : value_(saturated_cast<T>(value)) {
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr ClampedNumeric(Src value) : value_(saturated_cast<T>(value)) {
static_assert(UnderlyingType<Src>::is_numeric, "Argument must be numeric.");
}
// This is not an explicit constructor because we want a seamless conversion
// from StrictNumeric types.
template <typename Src>
- constexpr ClampedNumeric(
- StrictNumeric<Src> value) // NOLINT(runtime/explicit)
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr ClampedNumeric(StrictNumeric<Src> value)
: value_(saturated_cast<T>(static_cast<Src>(value))) {}
// Returns a ClampedNumeric of the specified type, cast from the current
diff --git a/third_party/base/numerics/clamped_math_impl.h b/third_party/base/numerics/clamped_math_impl.h
index 10b097f..a49309e 100644
--- a/third_party/base/numerics/clamped_math_impl.h
+++ b/third_party/base/numerics/clamped_math_impl.h
@@ -58,8 +58,9 @@
// special case of numeric_limits<T>::min(), by evaluating the bit pattern as
// a signed integer value. If it is the overflow case, we end up subtracting
// one from the unsigned result, thus saturating to numeric_limits<T>::max().
- return static_cast<T>(SafeUnsignedAbs(value) -
- IsValueNegative<T>(SafeUnsignedAbs(value)));
+ return static_cast<T>(
+ SafeUnsignedAbs(value) -
+ IsValueNegative<T>(static_cast<T>(SafeUnsignedAbs(value))));
}
template <
diff --git a/third_party/base/numerics/safe_conversions.h b/third_party/base/numerics/safe_conversions.h
index bcc7ba8..77ec8ce 100644
--- a/third_party/base/numerics/safe_conversions.h
+++ b/third_party/base/numerics/safe_conversions.h
@@ -20,10 +20,6 @@
#define BASE_HAS_OPTIMIZED_SAFE_CONVERSIONS (0)
#endif
-#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
-#include <ostream>
-#endif
-
namespace pdfium {
namespace base {
namespace internal {
@@ -121,21 +117,27 @@
template <typename T>
struct SaturationDefaultLimits : public std::numeric_limits<T> {
static constexpr T NaN() {
- return std::numeric_limits<T>::has_quiet_NaN
- ? std::numeric_limits<T>::quiet_NaN()
- : T();
+ if constexpr (std::numeric_limits<T>::has_quiet_NaN) {
+ return std::numeric_limits<T>::quiet_NaN();
+ } else {
+ return T();
+ }
}
using std::numeric_limits<T>::max;
static constexpr T Overflow() {
- return std::numeric_limits<T>::has_infinity
- ? std::numeric_limits<T>::infinity()
- : std::numeric_limits<T>::max();
+ if constexpr (std::numeric_limits<T>::has_infinity) {
+ return std::numeric_limits<T>::infinity();
+ } else {
+ return std::numeric_limits<T>::max();
+ }
}
using std::numeric_limits<T>::lowest;
static constexpr T Underflow() {
- return std::numeric_limits<T>::has_infinity
- ? std::numeric_limits<T>::infinity() * -1
- : std::numeric_limits<T>::lowest();
+ if constexpr (std::numeric_limits<T>::has_infinity) {
+ return std::numeric_limits<T>::infinity() * -1;
+ } else {
+ return std::numeric_limits<T>::lowest();
+ }
}
};
@@ -279,11 +281,17 @@
constexpr StrictNumeric(const StrictNumeric<Src>& rhs)
: value_(strict_cast<T>(rhs.value_)) {}
+ // Strictly speaking, this is not necessary, but declaring this allows class
+ // template argument deduction to be used so that it is possible to simply
+ // write `StrictNumeric(777)` instead of `StrictNumeric<int>(777)`.
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr StrictNumeric(T value) : value_(value) {}
+
// This is not an explicit constructor because we implicitly upgrade regular
// numerics to StrictNumerics to make them easier to use.
template <typename Src>
- constexpr StrictNumeric(Src value) // NOLINT(runtime/explicit)
- : value_(strict_cast<T>(value)) {}
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ constexpr StrictNumeric(Src value) : value_(strict_cast<T>(value)) {}
// If you got here from a compiler error, it's because you tried to assign
// from a source type to a destination type that has insufficient range.
diff --git a/third_party/base/numerics/safe_conversions_impl.h b/third_party/base/numerics/safe_conversions_impl.h
index 4d8a7b7..44c921a 100644
--- a/third_party/base/numerics/safe_conversions_impl.h
+++ b/third_party/base/numerics/safe_conversions_impl.h
@@ -72,8 +72,9 @@
static_assert(std::is_integral<T>::value, "Type must be integral");
using SignedT = typename std::make_signed<T>::type;
using UnsignedT = typename std::make_unsigned<T>::type;
- return static_cast<SignedT>(
- (static_cast<UnsignedT>(x) ^ -SignedT(is_negative)) + is_negative);
+ return static_cast<SignedT>((static_cast<UnsignedT>(x) ^
+ static_cast<UnsignedT>(-SignedT(is_negative))) +
+ is_negative);
}
// This performs a safe, absolute value via unsigned overflow.
@@ -245,9 +246,10 @@
static constexpr T Adjust(T value) {
static_assert(std::is_same<T, Dst>::value, "");
static_assert(kShift < DstLimits::digits, "");
- return static_cast<T>(
- ConditionalNegate(SafeUnsignedAbs(value) & ~((T(1) << kShift) - T(1)),
- IsValueNegative(value)));
+ using UnsignedDst = typename std::make_unsigned_t<T>;
+ return static_cast<T>(ConditionalNegate(
+ SafeUnsignedAbs(value) & ~((UnsignedDst{1} << kShift) - UnsignedDst{1}),
+ IsValueNegative(value)));
}
template <typename T,
diff --git a/third_party/base/numerics/safe_math_arm_impl.h b/third_party/base/numerics/safe_math_arm_impl.h
index cea9632..ff97333 100644
--- a/third_party/base/numerics/safe_math_arm_impl.h
+++ b/third_party/base/numerics/safe_math_arm_impl.h
@@ -57,7 +57,7 @@
// This will get promoted to an int, so let the compiler do whatever is
// clever and rely on the saturated cast to bounds check.
if (IsIntegerArithmeticSafe<int, T, U>::value)
- return saturated_cast<V>(x + y);
+ return saturated_cast<V>(static_cast<int>(x) + static_cast<int>(y));
int32_t result;
int32_t x_i32 = checked_cast<int32_t>(x);
@@ -83,7 +83,7 @@
// This will get promoted to an int, so let the compiler do whatever is
// clever and rely on the saturated cast to bounds check.
if (IsIntegerArithmeticSafe<int, T, U>::value)
- return saturated_cast<V>(x - y);
+ return saturated_cast<V>(static_cast<int>(x) - static_cast<int>(y));
int32_t result;
int32_t x_i32 = checked_cast<int32_t>(x);