summaryrefslogtreecommitdiffstats
path: root/base/numerics
diff options
context:
space:
mode:
authorvmpstr <vmpstr@chromium.org>2015-12-14 12:09:42 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-14 20:10:22 +0000
commitedf1e180c3141e77b6528a00b38b37c84de962fa (patch)
tree9080a805bd36e2b2090f289e64f09f1831d00810 /base/numerics
parent2ba07d1f31f04391c83a53a2e49387de58b1ac2d (diff)
downloadchromium_src-edf1e180c3141e77b6528a00b38b37c84de962fa.zip
chromium_src-edf1e180c3141e77b6528a00b38b37c84de962fa.tar.gz
chromium_src-edf1e180c3141e77b6528a00b38b37c84de962fa.tar.bz2
base: Make saturated_cast behavior for NaNs configurable.
This patch makes the behavior for saturated_cast when encountering a NaN to integral type conversion configurable. By default, we would return 0. However, we can specify that we would like to CHECK(false) instead. R=jschuh@chromium.org BUG=552104 Review URL: https://codereview.chromium.org/1512803003 Cr-Commit-Position: refs/heads/master@{#365080}
Diffstat (limited to 'base/numerics')
-rw-r--r--base/numerics/safe_conversions.h27
-rw-r--r--base/numerics/safe_numerics_unittest.cc17
2 files changed, 40 insertions, 4 deletions
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
index 5e5ed77..db2ff84 100644
--- a/base/numerics/safe_conversions.h
+++ b/base/numerics/safe_conversions.h
@@ -48,10 +48,30 @@ inline Dst checked_cast(Src value) {
return static_cast<Dst>(value);
}
+// HandleNaN will cause this class to CHECK(false).
+struct SaturatedCastNaNBehaviorCheck {
+ template <typename T>
+ static T HandleNaN() {
+ CHECK(false);
+ return T();
+ }
+};
+
+// HandleNaN will return 0 in this case.
+struct SaturatedCastNaNBehaviorReturnZero {
+ template <typename T>
+ static T HandleNaN() {
+ return T();
+ }
+};
+
// saturated_cast<> is analogous to static_cast<> for numeric types, except
// that the specified numeric conversion will saturate rather than overflow or
-// underflow. NaN assignment to an integral will trigger a CHECK condition.
-template <typename Dst, typename Src>
+// underflow. NaN assignment to an integral will defer the behavior to a
+// specified class. By default, it will return 0.
+template <typename Dst,
+ class NaNHandler = SaturatedCastNaNBehaviorReturnZero,
+ typename Src>
inline Dst saturated_cast(Src value) {
// Optimization for floating point values, which already saturate.
if (std::numeric_limits<Dst>::is_iec559)
@@ -69,8 +89,7 @@ inline Dst saturated_cast(Src value) {
// Should fail only on attempting to assign NaN to a saturated integer.
case internal::RANGE_INVALID:
- CHECK(false);
- return std::numeric_limits<Dst>::max();
+ return NaNHandler::template HandleNaN<Dst>();
}
NOTREACHED();
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc
index aaf2779..6de2980 100644
--- a/base/numerics/safe_numerics_unittest.cc
+++ b/base/numerics/safe_numerics_unittest.cc
@@ -664,8 +664,25 @@ TEST(SafeNumerics, CastTests) {
EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int));
EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
+
+ float not_a_number = std::numeric_limits<float>::infinity() -
+ std::numeric_limits<float>::infinity();
+ EXPECT_TRUE(std::isnan(not_a_number));
+ EXPECT_EQ(0, saturated_cast<int>(not_a_number));
}
+#if GTEST_HAS_DEATH_TEST
+
+TEST(SafeNumerics, SaturatedCastChecks) {
+ float not_a_number = std::numeric_limits<float>::infinity() -
+ std::numeric_limits<float>::infinity();
+ EXPECT_TRUE(std::isnan(not_a_number));
+ EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>(
+ not_a_number)), "");
+}
+
+#endif // GTEST_HAS_DEATH_TEST
+
TEST(SafeNumerics, IsValueInRangeForNumericType) {
EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));