Home | History | Annotate | Download | only in numerics
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
      6 #include <mmintrin.h>
      7 #endif
      8 #include <stdint.h>
      9 
     10 #include <limits>
     11 
     12 #include "base/compiler_specific.h"
     13 #include "base/numerics/safe_conversions.h"
     14 #include "base/numerics/safe_math.h"
     15 #include "base/template_util.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 using std::numeric_limits;
     19 using base::CheckedNumeric;
     20 using base::checked_cast;
     21 using base::saturated_cast;
     22 using base::internal::MaxExponent;
     23 using base::internal::RANGE_VALID;
     24 using base::internal::RANGE_INVALID;
     25 using base::internal::RANGE_OVERFLOW;
     26 using base::internal::RANGE_UNDERFLOW;
     27 using base::enable_if;
     28 
     29 // MSVS 2013 ia32 may not reset the FPU between calculations, and the test
     30 // framework masks the exceptions. So we just force a manual reset after NaN.
     31 inline void ResetFloatingPointUnit() {
     32 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
     33   _mm_empty();
     34 #endif
     35 }
     36 
     37 // These tests deliberately cause arithmetic overflows. If the compiler is
     38 // aggressive enough, it can const fold these overflows. Disable warnings about
     39 // overflows for const expressions.
     40 #if defined(OS_WIN)
     41 #pragma warning(disable:4756)
     42 #endif
     43 
     44 // Helper macros to wrap displaying the conversion types and line numbers.
     45 #define TEST_EXPECTED_VALIDITY(expected, actual)                           \
     46   EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).validity())              \
     47       << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst \
     48       << " on line " << line;
     49 
     50 #define TEST_EXPECTED_VALUE(expected, actual)                                \
     51   EXPECT_EQ(static_cast<Dst>(expected),                                      \
     52             CheckedNumeric<Dst>(actual).ValueUnsafe())                       \
     53       << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst \
     54       << " on line " << line;
     55 
     56 // Signed integer arithmetic.
     57 template <typename Dst>
     58 static void TestSpecializedArithmetic(
     59     const char* dst,
     60     int line,
     61     typename enable_if<
     62         numeric_limits<Dst>::is_integer&& numeric_limits<Dst>::is_signed,
     63         int>::type = 0) {
     64   typedef numeric_limits<Dst> DstLimits;
     65   TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
     66                          -CheckedNumeric<Dst>(DstLimits::min()));
     67   TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
     68                          CheckedNumeric<Dst>(DstLimits::min()).Abs());
     69   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
     70 
     71   TEST_EXPECTED_VALIDITY(RANGE_VALID,
     72                          CheckedNumeric<Dst>(DstLimits::max()) + -1);
     73   TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
     74                          CheckedNumeric<Dst>(DstLimits::min()) + -1);
     75   TEST_EXPECTED_VALIDITY(
     76       RANGE_UNDERFLOW,
     77       CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
     78 
     79   TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
     80                          CheckedNumeric<Dst>(DstLimits::min()) - 1);
     81   TEST_EXPECTED_VALIDITY(RANGE_VALID,
     82                          CheckedNumeric<Dst>(DstLimits::min()) - -1);
     83   TEST_EXPECTED_VALIDITY(
     84       RANGE_OVERFLOW,
     85       CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
     86   TEST_EXPECTED_VALIDITY(
     87       RANGE_UNDERFLOW,
     88       CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
     89 
     90   TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
     91                          CheckedNumeric<Dst>(DstLimits::min()) * 2);
     92 
     93   TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
     94                          CheckedNumeric<Dst>(DstLimits::min()) / -1);
     95   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
     96 
     97   // Modulus is legal only for integers.
     98   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
     99   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
    100   TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
    101   TEST_EXPECTED_VALIDITY(RANGE_INVALID, CheckedNumeric<Dst>(-1) % -2);
    102   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
    103   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
    104   // Test all the different modulus combinations.
    105   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
    106   TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
    107   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
    108   CheckedNumeric<Dst> checked_dst = 1;
    109   TEST_EXPECTED_VALUE(0, checked_dst %= 1);
    110 }
    111 
    112 // Unsigned integer arithmetic.
    113 template <typename Dst>
    114 static void TestSpecializedArithmetic(
    115     const char* dst,
    116     int line,
    117     typename enable_if<
    118         numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed,
    119         int>::type = 0) {
    120   typedef numeric_limits<Dst> DstLimits;
    121   TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min()));
    122   TEST_EXPECTED_VALIDITY(RANGE_VALID,
    123                          CheckedNumeric<Dst>(DstLimits::min()).Abs());
    124   TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
    125                          CheckedNumeric<Dst>(DstLimits::min()) + -1);
    126   TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
    127                          CheckedNumeric<Dst>(DstLimits::min()) - 1);
    128   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2);
    129   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
    130 
    131   // Modulus is legal only for integers.
    132   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
    133   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
    134   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
    135   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
    136   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
    137   // Test all the different modulus combinations.
    138   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
    139   TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
    140   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
    141   CheckedNumeric<Dst> checked_dst = 1;
    142   TEST_EXPECTED_VALUE(0, checked_dst %= 1);
    143 }
    144 
    145 // Floating point arithmetic.
    146 template <typename Dst>
    147 void TestSpecializedArithmetic(
    148     const char* dst,
    149     int line,
    150     typename enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
    151   typedef numeric_limits<Dst> DstLimits;
    152   TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min()));
    153 
    154   TEST_EXPECTED_VALIDITY(RANGE_VALID,
    155                          CheckedNumeric<Dst>(DstLimits::min()).Abs());
    156   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
    157 
    158   TEST_EXPECTED_VALIDITY(RANGE_VALID,
    159                          CheckedNumeric<Dst>(DstLimits::min()) + -1);
    160   TEST_EXPECTED_VALIDITY(RANGE_VALID,
    161                          CheckedNumeric<Dst>(DstLimits::max()) + 1);
    162   TEST_EXPECTED_VALIDITY(
    163       RANGE_UNDERFLOW,
    164       CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
    165 
    166   TEST_EXPECTED_VALIDITY(
    167       RANGE_OVERFLOW,
    168       CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
    169   TEST_EXPECTED_VALIDITY(
    170       RANGE_UNDERFLOW,
    171       CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
    172 
    173   TEST_EXPECTED_VALIDITY(RANGE_VALID,
    174                          CheckedNumeric<Dst>(DstLimits::min()) * 2);
    175 
    176   TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
    177   EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
    178 }
    179 
    180 // Generic arithmetic tests.
    181 template <typename Dst>
    182 static void TestArithmetic(const char* dst, int line) {
    183   typedef numeric_limits<Dst> DstLimits;
    184 
    185   EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
    186   EXPECT_EQ(false,
    187             CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
    188                                 DstLimits::max()).IsValid());
    189   EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
    190   EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
    191   EXPECT_EQ(static_cast<Dst>(1),
    192             CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
    193                                 DstLimits::max()).ValueOrDefault(1));
    194 
    195   // Test the operator combinations.
    196   TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
    197   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
    198   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
    199   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
    200   TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
    201   TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
    202   TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
    203   TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
    204   TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
    205   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
    206   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
    207   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
    208   CheckedNumeric<Dst> checked_dst = 1;
    209   TEST_EXPECTED_VALUE(2, checked_dst += 1);
    210   checked_dst = 1;
    211   TEST_EXPECTED_VALUE(0, checked_dst -= 1);
    212   checked_dst = 1;
    213   TEST_EXPECTED_VALUE(1, checked_dst *= 1);
    214   checked_dst = 1;
    215   TEST_EXPECTED_VALUE(1, checked_dst /= 1);
    216 
    217   // Generic negation.
    218   TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
    219   TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
    220   TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
    221   TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
    222                       -CheckedNumeric<Dst>(DstLimits::max()));
    223 
    224   // Generic absolute value.
    225   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
    226   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
    227   TEST_EXPECTED_VALUE(DstLimits::max(),
    228                       CheckedNumeric<Dst>(DstLimits::max()).Abs());
    229 
    230   // Generic addition.
    231   TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
    232   TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
    233   TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
    234   TEST_EXPECTED_VALIDITY(RANGE_VALID,
    235                          CheckedNumeric<Dst>(DstLimits::min()) + 1);
    236   TEST_EXPECTED_VALIDITY(
    237       RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
    238 
    239   // Generic subtraction.
    240   TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
    241   TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
    242   TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
    243   TEST_EXPECTED_VALIDITY(RANGE_VALID,
    244                          CheckedNumeric<Dst>(DstLimits::max()) - 1);
    245 
    246   // Generic multiplication.
    247   TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
    248   TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
    249   TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
    250   TEST_EXPECTED_VALIDITY(
    251       RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
    252 
    253   // Generic division.
    254   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
    255   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
    256   TEST_EXPECTED_VALUE(DstLimits::min() / 2,
    257                       CheckedNumeric<Dst>(DstLimits::min()) / 2);
    258   TEST_EXPECTED_VALUE(DstLimits::max() / 2,
    259                       CheckedNumeric<Dst>(DstLimits::max()) / 2);
    260 
    261   TestSpecializedArithmetic<Dst>(dst, line);
    262 }
    263 
    264 // Helper macro to wrap displaying the conversion types and line numbers.
    265 #define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
    266 
    267 TEST(SafeNumerics, SignedIntegerMath) {
    268   TEST_ARITHMETIC(int8_t);
    269   TEST_ARITHMETIC(int);
    270   TEST_ARITHMETIC(intptr_t);
    271   TEST_ARITHMETIC(intmax_t);
    272 }
    273 
    274 TEST(SafeNumerics, UnsignedIntegerMath) {
    275   TEST_ARITHMETIC(uint8_t);
    276   TEST_ARITHMETIC(unsigned int);
    277   TEST_ARITHMETIC(uintptr_t);
    278   TEST_ARITHMETIC(uintmax_t);
    279 }
    280 
    281 TEST(SafeNumerics, FloatingPointMath) {
    282   TEST_ARITHMETIC(float);
    283   TEST_ARITHMETIC(double);
    284 }
    285 
    286 // Enumerates the five different conversions types we need to test.
    287 enum NumericConversionType {
    288   SIGN_PRESERVING_VALUE_PRESERVING,
    289   SIGN_PRESERVING_NARROW,
    290   SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
    291   SIGN_TO_UNSIGN_NARROW,
    292   UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
    293 };
    294 
    295 // Template covering the different conversion tests.
    296 template <typename Dst, typename Src, NumericConversionType conversion>
    297 struct TestNumericConversion {};
    298 
    299 // EXPECT_EQ wrappers providing specific detail on test failures.
    300 #define TEST_EXPECTED_RANGE(expected, actual)                                  \
    301   EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
    302       << "Conversion test: " << src << " value " << actual << " to " << dst    \
    303       << " on line " << line;
    304 
    305 template <typename Dst, typename Src>
    306 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
    307   static void Test(const char *dst, const char *src, int line) {
    308     typedef numeric_limits<Src> SrcLimits;
    309     typedef numeric_limits<Dst> DstLimits;
    310                    // Integral to floating.
    311     COMPILE_ASSERT((DstLimits::is_iec559 && SrcLimits::is_integer) ||
    312                    // Not floating to integral and...
    313                    (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
    314                     // Same sign, same numeric, source is narrower or same.
    315                     ((SrcLimits::is_signed == DstLimits::is_signed &&
    316                      sizeof(Dst) >= sizeof(Src)) ||
    317                     // Or signed destination and source is smaller
    318                      (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
    319                    comparison_must_be_sign_preserving_and_value_preserving);
    320 
    321     const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
    322     ;
    323     TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst);
    324     if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
    325       if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
    326         // At least twice larger type.
    327         TEST_EXPECTED_VALIDITY(RANGE_VALID, SrcLimits::max() * checked_dst);
    328 
    329       } else {  // Larger, but not at least twice as large.
    330         TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, SrcLimits::max() * checked_dst);
    331         TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst + 1);
    332       }
    333     } else {  // Same width type.
    334       TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + 1);
    335     }
    336 
    337     TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
    338     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
    339     if (SrcLimits::is_iec559) {
    340       TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
    341       TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
    342       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
    343       TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
    344       ResetFloatingPointUnit();
    345     } else if (numeric_limits<Src>::is_signed) {
    346       TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
    347       TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
    348     }
    349   }
    350 };
    351 
    352 template <typename Dst, typename Src>
    353 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
    354   static void Test(const char *dst, const char *src, int line) {
    355     typedef numeric_limits<Src> SrcLimits;
    356     typedef numeric_limits<Dst> DstLimits;
    357     COMPILE_ASSERT(SrcLimits::is_signed == DstLimits::is_signed,
    358                    destination_and_source_sign_must_be_the_same);
    359     COMPILE_ASSERT(sizeof(Dst) < sizeof(Src) ||
    360                    (DstLimits::is_integer && SrcLimits::is_iec559),
    361                    destination_must_be_narrower_than_source);
    362 
    363     const CheckedNumeric<Dst> checked_dst;
    364     TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
    365     TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
    366     TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst - SrcLimits::max());
    367 
    368     TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
    369     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
    370     if (SrcLimits::is_iec559) {
    371       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
    372       TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
    373       TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
    374       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
    375       TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
    376       ResetFloatingPointUnit();
    377     } else if (SrcLimits::is_signed) {
    378       TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
    379       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
    380       TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
    381     } else {
    382       TEST_EXPECTED_VALIDITY(RANGE_INVALID, checked_dst - static_cast<Src>(1));
    383       TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
    384     }
    385   }
    386 };
    387 
    388 template <typename Dst, typename Src>
    389 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
    390   static void Test(const char *dst, const char *src, int line) {
    391     typedef numeric_limits<Src> SrcLimits;
    392     typedef numeric_limits<Dst> DstLimits;
    393     COMPILE_ASSERT(sizeof(Dst) >= sizeof(Src),
    394                    destination_must_be_equal_or_wider_than_source);
    395     COMPILE_ASSERT(SrcLimits::is_signed, source_must_be_signed);
    396     COMPILE_ASSERT(!DstLimits::is_signed, destination_must_be_unsigned);
    397 
    398     const CheckedNumeric<Dst> checked_dst;
    399     TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
    400     TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1));
    401     TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max());
    402 
    403     TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
    404     TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
    405     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
    406     TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
    407   }
    408 };
    409 
    410 template <typename Dst, typename Src>
    411 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
    412   static void Test(const char *dst, const char *src, int line) {
    413     typedef numeric_limits<Src> SrcLimits;
    414     typedef numeric_limits<Dst> DstLimits;
    415     COMPILE_ASSERT((DstLimits::is_integer && SrcLimits::is_iec559) ||
    416                    (sizeof(Dst) < sizeof(Src)),
    417       destination_must_be_narrower_than_source);
    418     COMPILE_ASSERT(SrcLimits::is_signed, source_must_be_signed);
    419     COMPILE_ASSERT(!DstLimits::is_signed, destination_must_be_unsigned);
    420 
    421     const CheckedNumeric<Dst> checked_dst;
    422     TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
    423     TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
    424     TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1));
    425     TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max());
    426 
    427     TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
    428     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
    429     TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
    430     if (SrcLimits::is_iec559) {
    431       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
    432       TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
    433       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
    434       TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
    435       ResetFloatingPointUnit();
    436     } else {
    437       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
    438     }
    439   }
    440 };
    441 
    442 template <typename Dst, typename Src>
    443 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
    444   static void Test(const char *dst, const char *src, int line) {
    445     typedef numeric_limits<Src> SrcLimits;
    446     typedef numeric_limits<Dst> DstLimits;
    447     COMPILE_ASSERT(sizeof(Dst) <= sizeof(Src),
    448                    destination_must_be_narrower_or_equal_to_source);
    449     COMPILE_ASSERT(!SrcLimits::is_signed, source_must_be_unsigned);
    450     COMPILE_ASSERT(DstLimits::is_signed, destination_must_be_signed);
    451 
    452     const CheckedNumeric<Dst> checked_dst;
    453     TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
    454     TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
    455     TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
    456 
    457     TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
    458     TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
    459     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
    460   }
    461 };
    462 
    463 // Helper macro to wrap displaying the conversion types and line numbers
    464 #define TEST_NUMERIC_CONVERSION(d, s, t) \
    465   TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
    466 
    467 TEST(SafeNumerics, IntMinOperations) {
    468   TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
    469   TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
    470 
    471   TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
    472   TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
    473   TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
    474 
    475   TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
    476 
    477   TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
    478   TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
    479   TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
    480 
    481   TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
    482   TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
    483 }
    484 
    485 TEST(SafeNumerics, IntOperations) {
    486   TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
    487   TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
    488                           SIGN_PRESERVING_VALUE_PRESERVING);
    489   TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
    490   TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
    491                           SIGN_PRESERVING_VALUE_PRESERVING);
    492   TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
    493 
    494   TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
    495   TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
    496   TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
    497   TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
    498 
    499   TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
    500   TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
    501 
    502   TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
    503   TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
    504   TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
    505 
    506   TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
    507   TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
    508 }
    509 
    510 TEST(SafeNumerics, IntMaxOperations) {
    511   TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
    512   TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
    513                           SIGN_PRESERVING_VALUE_PRESERVING);
    514   TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
    515   TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
    516                           SIGN_PRESERVING_VALUE_PRESERVING);
    517   TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
    518                           SIGN_PRESERVING_VALUE_PRESERVING);
    519   TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
    520 
    521   TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
    522   TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
    523 
    524   TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
    525   TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
    526 
    527   TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
    528   TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
    529 
    530   TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
    531 }
    532 
    533 TEST(SafeNumerics, FloatOperations) {
    534   TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
    535   TEST_NUMERIC_CONVERSION(float, uintmax_t,
    536                           SIGN_PRESERVING_VALUE_PRESERVING);
    537   TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
    538   TEST_NUMERIC_CONVERSION(float, unsigned int,
    539                           SIGN_PRESERVING_VALUE_PRESERVING);
    540 
    541   TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
    542 }
    543 
    544 TEST(SafeNumerics, DoubleOperations) {
    545   TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
    546   TEST_NUMERIC_CONVERSION(double, uintmax_t,
    547                           SIGN_PRESERVING_VALUE_PRESERVING);
    548   TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
    549   TEST_NUMERIC_CONVERSION(double, unsigned int,
    550                           SIGN_PRESERVING_VALUE_PRESERVING);
    551 }
    552 
    553 TEST(SafeNumerics, SizeTOperations) {
    554   TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
    555   TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
    556 }
    557 
    558 TEST(SafeNumerics, CastTests) {
    559 // MSVC catches and warns that we're forcing saturation in these tests.
    560 // Since that's intentional, we need to shut this warning off.
    561 #if defined(COMPILER_MSVC)
    562 #pragma warning(disable : 4756)
    563 #endif
    564 
    565   int small_positive = 1;
    566   int small_negative = -1;
    567   double double_small = 1.0;
    568   double double_large = numeric_limits<double>::max();
    569   double double_infinity = numeric_limits<float>::infinity();
    570 
    571   // Just test that the cast compiles, since the other tests cover logic.
    572   EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
    573 
    574   // Test various saturation corner cases.
    575   EXPECT_EQ(saturated_cast<int>(small_negative),
    576             static_cast<int>(small_negative));
    577   EXPECT_EQ(saturated_cast<int>(small_positive),
    578             static_cast<int>(small_positive));
    579   EXPECT_EQ(saturated_cast<unsigned>(small_negative),
    580             static_cast<unsigned>(0));
    581   EXPECT_EQ(saturated_cast<int>(double_small),
    582             static_cast<int>(double_small));
    583   EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
    584   EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
    585   EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
    586 }
    587 
    588