| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <type_traits> | 9 #include <type_traits> |
| 10 | 10 |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/numerics/safe_conversions.h" | 13 #include "base/numerics/safe_conversions.h" |
| 14 #include "base/numerics/safe_math.h" | 14 #include "base/numerics/safe_math.h" |
| 15 #include "base/test/gtest_util.h" | 15 #include "base/test/gtest_util.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 18 |
| 19 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) | 19 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) |
| 20 #include <mmintrin.h> | 20 #include <mmintrin.h> |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 using std::numeric_limits; | 23 using std::numeric_limits; |
| 24 using base::CheckedNumeric; | 24 using base::CheckedNumeric; |
| 25 using base::IsValidForType; |
| 26 using base::ValueOrDieForType; |
| 27 using base::ValueOrDefaultForType; |
| 25 using base::CheckNum; | 28 using base::CheckNum; |
| 26 using base::CheckAdd; | 29 using base::CheckAdd; |
| 27 using base::CheckSub; | 30 using base::CheckSub; |
| 28 using base::CheckMul; | 31 using base::CheckMul; |
| 29 using base::CheckDiv; | 32 using base::CheckDiv; |
| 30 using base::CheckMod; | 33 using base::CheckMod; |
| 31 using base::CheckLsh; | 34 using base::CheckLsh; |
| 32 using base::CheckRsh; | 35 using base::CheckRsh; |
| 33 using base::checked_cast; | 36 using base::checked_cast; |
| 34 using base::IsValueInRangeForNumericType; | 37 using base::IsValueInRangeForNumericType; |
| 35 using base::IsValueNegative; | 38 using base::IsValueNegative; |
| 36 using base::SizeT; | 39 using base::SizeT; |
| 37 using base::StrictNumeric; | 40 using base::StrictNumeric; |
| 38 using base::saturated_cast; | 41 using base::saturated_cast; |
| 39 using base::strict_cast; | 42 using base::strict_cast; |
| 43 using base::StrictNumeric; |
| 40 using base::internal::MaxExponent; | 44 using base::internal::MaxExponent; |
| 41 using base::internal::RANGE_VALID; | 45 using base::internal::RANGE_VALID; |
| 42 using base::internal::RANGE_INVALID; | 46 using base::internal::RANGE_INVALID; |
| 43 using base::internal::RANGE_OVERFLOW; | 47 using base::internal::RANGE_OVERFLOW; |
| 44 using base::internal::RANGE_UNDERFLOW; | 48 using base::internal::RANGE_UNDERFLOW; |
| 45 using base::internal::SignedIntegerForSize; | 49 using base::internal::SignedIntegerForSize; |
| 46 | 50 |
| 47 // These tests deliberately cause arithmetic boundary errors. If the compiler is | 51 // These tests deliberately cause arithmetic boundary errors. If the compiler is |
| 48 // aggressive enough, it can const detect these errors, so we disable warnings. | 52 // aggressive enough, it can const detect these errors, so we disable warnings. |
| 49 #if defined(OS_WIN) | 53 #if defined(OS_WIN) |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 #define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual) | 105 #define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual) |
| 102 | 106 |
| 103 #define TEST_EXPECTED_VALUE(expected, actual) \ | 107 #define TEST_EXPECTED_VALUE(expected, actual) \ |
| 104 EXPECT_EQ(static_cast<Dst>(expected), \ | 108 EXPECT_EQ(static_cast<Dst>(expected), \ |
| 105 ((actual) \ | 109 ((actual) \ |
| 106 .template Cast<Dst>() \ | 110 .template Cast<Dst>() \ |
| 107 .template ValueOrDie<Dst, LogOnFailure>())) \ | 111 .template ValueOrDie<Dst, LogOnFailure>())) \ |
| 108 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \ | 112 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \ |
| 109 << dst << " on line " << line | 113 << dst << " on line " << line |
| 110 | 114 |
| 115 // Test the simple pointer arithmetic overrides. |
| 116 template <typename Dst> |
| 117 void TestStrictPointerMath() { |
| 118 Dst dummy_value = 0; |
| 119 Dst* dummy_ptr = &dummy_value; |
| 120 static const Dst kDummyOffset = 2; // Don't want to go too far. |
| 121 EXPECT_EQ(dummy_ptr + kDummyOffset, |
| 122 dummy_ptr + StrictNumeric<Dst>(kDummyOffset)); |
| 123 EXPECT_EQ(dummy_ptr - kDummyOffset, |
| 124 dummy_ptr - StrictNumeric<Dst>(kDummyOffset)); |
| 125 EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset)); |
| 126 EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset)); |
| 127 EXPECT_DEATH_IF_SUPPORTED( |
| 128 dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()), |
| 129 ""); |
| 130 } |
| 131 |
| 111 // Signed integer arithmetic. | 132 // Signed integer arithmetic. |
| 112 template <typename Dst> | 133 template <typename Dst> |
| 113 static void TestSpecializedArithmetic( | 134 static void TestSpecializedArithmetic( |
| 114 const char* dst, | 135 const char* dst, |
| 115 int line, | 136 int line, |
| 116 typename std::enable_if<numeric_limits<Dst>::is_integer && | 137 typename std::enable_if<numeric_limits<Dst>::is_integer && |
| 117 numeric_limits<Dst>::is_signed, | 138 numeric_limits<Dst>::is_signed, |
| 118 int>::type = 0) { | 139 int>::type = 0) { |
| 119 typedef numeric_limits<Dst> DstLimits; | 140 typedef numeric_limits<Dst> DstLimits; |
| 120 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min())); | 141 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min())); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 TEST_EXPECTED_VALUE(static_cast<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2), | 184 TEST_EXPECTED_VALUE(static_cast<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2), |
| 164 CheckedNumeric<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2)); | 185 CheckedNumeric<Dst>(1) << (sizeof(Dst) * CHAR_BIT - 2)); |
| 165 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 186 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) |
| 166 << (sizeof(Dst) * CHAR_BIT - 1)); | 187 << (sizeof(Dst) * CHAR_BIT - 1)); |
| 167 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0); | 188 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0); |
| 168 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1); | 189 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1); |
| 169 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT)); | 190 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT)); |
| 170 TEST_EXPECTED_VALUE(0, | 191 TEST_EXPECTED_VALUE(0, |
| 171 CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT - 1)); | 192 CheckedNumeric<Dst>(1) >> (sizeof(Dst) * CHAR_BIT - 1)); |
| 172 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one); | 193 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one); |
| 194 |
| 195 TestStrictPointerMath<Dst>(); |
| 173 } | 196 } |
| 174 | 197 |
| 175 // Unsigned integer arithmetic. | 198 // Unsigned integer arithmetic. |
| 176 template <typename Dst> | 199 template <typename Dst> |
| 177 static void TestSpecializedArithmetic( | 200 static void TestSpecializedArithmetic( |
| 178 const char* dst, | 201 const char* dst, |
| 179 int line, | 202 int line, |
| 180 typename std::enable_if<numeric_limits<Dst>::is_integer && | 203 typename std::enable_if<numeric_limits<Dst>::is_integer && |
| 181 !numeric_limits<Dst>::is_signed, | 204 !numeric_limits<Dst>::is_signed, |
| 182 int>::type = 0) { | 205 int>::type = 0) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0); | 257 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0); |
| 235 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), | 258 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), |
| 236 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1)); | 259 CheckedNumeric<Dst>(0) | static_cast<Dst>(-1)); |
| 237 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1); | 260 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1); |
| 238 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0); | 261 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0); |
| 239 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1); | 262 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1); |
| 240 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0); | 263 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0); |
| 241 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), | 264 TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(), |
| 242 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1)); | 265 CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1)); |
| 243 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0)); | 266 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0)); |
| 267 |
| 268 TestStrictPointerMath<Dst>(); |
| 244 } | 269 } |
| 245 | 270 |
| 246 // Floating point arithmetic. | 271 // Floating point arithmetic. |
| 247 template <typename Dst> | 272 template <typename Dst> |
| 248 void TestSpecializedArithmetic( | 273 void TestSpecializedArithmetic( |
| 249 const char* dst, | 274 const char* dst, |
| 250 int line, | 275 int line, |
| 251 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) { | 276 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) { |
| 252 typedef numeric_limits<Dst> DstLimits; | 277 typedef numeric_limits<Dst> DstLimits; |
| 253 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min())); | 278 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min())); |
| 254 | 279 |
| 255 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs()); | 280 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs()); |
| 256 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs()); | 281 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs()); |
| 257 | 282 |
| 258 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1); | 283 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1); |
| 259 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1); | 284 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1); |
| 260 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + | 285 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + |
| 261 -DstLimits::max()); | 286 -DstLimits::max()); |
| 262 | 287 |
| 263 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - | 288 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - |
| 264 -DstLimits::max()); | 289 -DstLimits::max()); |
| 265 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - | 290 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - |
| 266 DstLimits::max()); | 291 DstLimits::max()); |
| 267 | 292 |
| 268 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2); | 293 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2); |
| 269 | 294 |
| 270 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2); | 295 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2); |
| 271 EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating()); | |
| 272 } | 296 } |
| 273 | 297 |
| 274 // Generic arithmetic tests. | 298 // Generic arithmetic tests. |
| 275 template <typename Dst> | 299 template <typename Dst> |
| 276 static void TestArithmetic(const char* dst, int line) { | 300 static void TestArithmetic(const char* dst, int line) { |
| 277 typedef numeric_limits<Dst> DstLimits; | 301 typedef numeric_limits<Dst> DstLimits; |
| 278 | 302 |
| 279 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid()); | 303 EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid()); |
| 280 EXPECT_EQ(false, | 304 EXPECT_EQ(false, |
| 281 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * | 305 CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 template <typename Dst, typename Src, NumericConversionType conversion> | 428 template <typename Dst, typename Src, NumericConversionType conversion> |
| 405 struct TestNumericConversion {}; | 429 struct TestNumericConversion {}; |
| 406 | 430 |
| 407 // EXPECT_EQ wrappers providing specific detail on test failures. | 431 // EXPECT_EQ wrappers providing specific detail on test failures. |
| 408 #define TEST_EXPECTED_RANGE(expected, actual) \ | 432 #define TEST_EXPECTED_RANGE(expected, actual) \ |
| 409 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \ | 433 EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \ |
| 410 << "Conversion test: " << src << " value " << actual << " to " << dst \ | 434 << "Conversion test: " << src << " value " << actual << " to " << dst \ |
| 411 << " on line " << line | 435 << " on line " << line |
| 412 | 436 |
| 413 template <typename Dst, typename Src> | 437 template <typename Dst, typename Src> |
| 438 void TestStrictComparison() { |
| 439 typedef numeric_limits<Dst> DstLimits; |
| 440 typedef numeric_limits<Src> SrcLimits; |
| 441 static_assert(StrictNumeric<Src>(SrcLimits::min()) < DstLimits::max(), ""); |
| 442 static_assert(StrictNumeric<Src>(SrcLimits::min()) < SrcLimits::max(), ""); |
| 443 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) >= DstLimits::max()), |
| 444 ""); |
| 445 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) >= SrcLimits::max()), |
| 446 ""); |
| 447 static_assert(StrictNumeric<Src>(SrcLimits::min()) <= DstLimits::max(), ""); |
| 448 static_assert(StrictNumeric<Src>(SrcLimits::min()) <= SrcLimits::max(), ""); |
| 449 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) > DstLimits::max()), ""); |
| 450 static_assert(!(StrictNumeric<Src>(SrcLimits::min()) > SrcLimits::max()), ""); |
| 451 static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::min(), ""); |
| 452 static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::min(), ""); |
| 453 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::min()), |
| 454 ""); |
| 455 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::min()), |
| 456 ""); |
| 457 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::min(), ""); |
| 458 static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::min(), ""); |
| 459 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::min()), ""); |
| 460 static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::min()), ""); |
| 461 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1), |
| 462 ""); |
| 463 static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0), |
| 464 ""); |
| 465 static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0), |
| 466 ""); |
| 467 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::min(), ""); |
| 468 static_assert( |
| 469 !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), ""); |
| 470 static_assert( |
| 471 !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), ""); |
| 472 } |
| 473 |
| 474 template <typename Dst, typename Src> |
| 414 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> { | 475 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> { |
| 415 static void Test(const char *dst, const char *src, int line) { | 476 static void Test(const char *dst, const char *src, int line) { |
| 416 typedef numeric_limits<Src> SrcLimits; | 477 typedef numeric_limits<Src> SrcLimits; |
| 417 typedef numeric_limits<Dst> DstLimits; | 478 typedef numeric_limits<Dst> DstLimits; |
| 418 // Integral to floating. | 479 // Integral to floating. |
| 419 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) || | 480 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) || |
| 420 // Not floating to integral and... | 481 // Not floating to integral and... |
| 421 (!(DstLimits::is_integer && SrcLimits::is_iec559) && | 482 (!(DstLimits::is_integer && SrcLimits::is_iec559) && |
| 422 // Same sign, same numeric, source is narrower or same. | 483 // Same sign, same numeric, source is narrower or same. |
| 423 ((SrcLimits::is_signed == DstLimits::is_signed && | 484 ((SrcLimits::is_signed == DstLimits::is_signed && |
| 424 sizeof(Dst) >= sizeof(Src)) || | 485 sizeof(Dst) >= sizeof(Src)) || |
| 425 // Or signed destination and source is smaller | 486 // Or signed destination and source is smaller |
| 426 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))), | 487 (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))), |
| 427 "Comparison must be sign preserving and value preserving"); | 488 "Comparison must be sign preserving and value preserving"); |
| 428 | 489 |
| 490 TestStrictComparison<Dst, Src>(); |
| 491 |
| 429 const CheckedNumeric<Dst> checked_dst = SrcLimits::max(); | 492 const CheckedNumeric<Dst> checked_dst = SrcLimits::max(); |
| 430 TEST_EXPECTED_SUCCESS(checked_dst); | 493 TEST_EXPECTED_SUCCESS(checked_dst); |
| 431 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) { | 494 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) { |
| 432 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) { | 495 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) { |
| 433 // At least twice larger type. | 496 // At least twice larger type. |
| 434 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst); | 497 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst); |
| 435 | 498 |
| 436 } else { // Larger, but not at least twice as large. | 499 } else { // Larger, but not at least twice as large. |
| 437 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst); | 500 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst); |
| 438 TEST_EXPECTED_SUCCESS(checked_dst + 1); | 501 TEST_EXPECTED_SUCCESS(checked_dst + 1); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 459 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> { | 522 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> { |
| 460 static void Test(const char *dst, const char *src, int line) { | 523 static void Test(const char *dst, const char *src, int line) { |
| 461 typedef numeric_limits<Src> SrcLimits; | 524 typedef numeric_limits<Src> SrcLimits; |
| 462 typedef numeric_limits<Dst> DstLimits; | 525 typedef numeric_limits<Dst> DstLimits; |
| 463 static_assert(SrcLimits::is_signed == DstLimits::is_signed, | 526 static_assert(SrcLimits::is_signed == DstLimits::is_signed, |
| 464 "Destination and source sign must be the same"); | 527 "Destination and source sign must be the same"); |
| 465 static_assert(sizeof(Dst) < sizeof(Src) || | 528 static_assert(sizeof(Dst) < sizeof(Src) || |
| 466 (DstLimits::is_integer && SrcLimits::is_iec559), | 529 (DstLimits::is_integer && SrcLimits::is_iec559), |
| 467 "Destination must be narrower than source"); | 530 "Destination must be narrower than source"); |
| 468 | 531 |
| 532 TestStrictComparison<Dst, Src>(); |
| 533 |
| 469 const CheckedNumeric<Dst> checked_dst; | 534 const CheckedNumeric<Dst> checked_dst; |
| 470 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); | 535 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); |
| 471 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); | 536 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); |
| 472 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max()); | 537 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max()); |
| 473 | 538 |
| 474 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); | 539 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); |
| 475 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | 540 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); |
| 476 if (SrcLimits::is_iec559) { | 541 if (SrcLimits::is_iec559) { |
| 477 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1); | 542 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1); |
| 478 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); | 543 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 505 template <typename Dst, typename Src> | 570 template <typename Dst, typename Src> |
| 506 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> { | 571 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> { |
| 507 static void Test(const char *dst, const char *src, int line) { | 572 static void Test(const char *dst, const char *src, int line) { |
| 508 typedef numeric_limits<Src> SrcLimits; | 573 typedef numeric_limits<Src> SrcLimits; |
| 509 typedef numeric_limits<Dst> DstLimits; | 574 typedef numeric_limits<Dst> DstLimits; |
| 510 static_assert(sizeof(Dst) >= sizeof(Src), | 575 static_assert(sizeof(Dst) >= sizeof(Src), |
| 511 "Destination must be equal or wider than source."); | 576 "Destination must be equal or wider than source."); |
| 512 static_assert(SrcLimits::is_signed, "Source must be signed"); | 577 static_assert(SrcLimits::is_signed, "Source must be signed"); |
| 513 static_assert(!DstLimits::is_signed, "Destination must be unsigned"); | 578 static_assert(!DstLimits::is_signed, "Destination must be unsigned"); |
| 514 | 579 |
| 580 TestStrictComparison<Dst, Src>(); |
| 581 |
| 515 const CheckedNumeric<Dst> checked_dst; | 582 const CheckedNumeric<Dst> checked_dst; |
| 516 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max()); | 583 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max()); |
| 517 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); | 584 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); |
| 518 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); | 585 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); |
| 519 | 586 |
| 520 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); | 587 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); |
| 521 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max()); | 588 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max()); |
| 522 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | 589 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); |
| 523 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); | 590 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); |
| 524 } | 591 } |
| 525 }; | 592 }; |
| 526 | 593 |
| 527 template <typename Dst, typename Src> | 594 template <typename Dst, typename Src> |
| 528 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> { | 595 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> { |
| 529 static void Test(const char *dst, const char *src, int line) { | 596 static void Test(const char *dst, const char *src, int line) { |
| 530 typedef numeric_limits<Src> SrcLimits; | 597 typedef numeric_limits<Src> SrcLimits; |
| 531 typedef numeric_limits<Dst> DstLimits; | 598 typedef numeric_limits<Dst> DstLimits; |
| 532 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) || | 599 static_assert((DstLimits::is_integer && SrcLimits::is_iec559) || |
| 533 (sizeof(Dst) < sizeof(Src)), | 600 (sizeof(Dst) < sizeof(Src)), |
| 534 "Destination must be narrower than source."); | 601 "Destination must be narrower than source."); |
| 535 static_assert(SrcLimits::is_signed, "Source must be signed."); | 602 static_assert(SrcLimits::is_signed, "Source must be signed."); |
| 536 static_assert(!DstLimits::is_signed, "Destination must be unsigned."); | 603 static_assert(!DstLimits::is_signed, "Destination must be unsigned."); |
| 537 | 604 |
| 605 TestStrictComparison<Dst, Src>(); |
| 606 |
| 538 const CheckedNumeric<Dst> checked_dst; | 607 const CheckedNumeric<Dst> checked_dst; |
| 539 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); | 608 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); |
| 540 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); | 609 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); |
| 541 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); | 610 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); |
| 542 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); | 611 TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); |
| 543 | 612 |
| 544 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); | 613 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); |
| 545 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | 614 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); |
| 546 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); | 615 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); |
| 547 if (SrcLimits::is_iec559) { | 616 if (SrcLimits::is_iec559) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 570 template <typename Dst, typename Src> | 639 template <typename Dst, typename Src> |
| 571 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> { | 640 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> { |
| 572 static void Test(const char *dst, const char *src, int line) { | 641 static void Test(const char *dst, const char *src, int line) { |
| 573 typedef numeric_limits<Src> SrcLimits; | 642 typedef numeric_limits<Src> SrcLimits; |
| 574 typedef numeric_limits<Dst> DstLimits; | 643 typedef numeric_limits<Dst> DstLimits; |
| 575 static_assert(sizeof(Dst) <= sizeof(Src), | 644 static_assert(sizeof(Dst) <= sizeof(Src), |
| 576 "Destination must be narrower or equal to source."); | 645 "Destination must be narrower or equal to source."); |
| 577 static_assert(!SrcLimits::is_signed, "Source must be unsigned."); | 646 static_assert(!SrcLimits::is_signed, "Source must be unsigned."); |
| 578 static_assert(DstLimits::is_signed, "Destination must be signed."); | 647 static_assert(DstLimits::is_signed, "Destination must be signed."); |
| 579 | 648 |
| 649 TestStrictComparison<Dst, Src>(); |
| 650 |
| 580 const CheckedNumeric<Dst> checked_dst; | 651 const CheckedNumeric<Dst> checked_dst; |
| 581 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); | 652 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); |
| 582 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); | 653 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); |
| 583 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min()); | 654 TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min()); |
| 584 | 655 |
| 585 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); | 656 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); |
| 586 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); | 657 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); |
| 587 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); | 658 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); |
| 588 } | 659 } |
| 589 }; | 660 }; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING); | 747 TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING); |
| 677 TEST_NUMERIC_CONVERSION(double, unsigned int, | 748 TEST_NUMERIC_CONVERSION(double, unsigned int, |
| 678 SIGN_PRESERVING_VALUE_PRESERVING); | 749 SIGN_PRESERVING_VALUE_PRESERVING); |
| 679 } | 750 } |
| 680 | 751 |
| 681 TEST(SafeNumerics, SizeTOperations) { | 752 TEST(SafeNumerics, SizeTOperations) { |
| 682 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); | 753 TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); |
| 683 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); | 754 TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); |
| 684 } | 755 } |
| 685 | 756 |
| 757 // A one-off test to ensure StrictNumeric won't resolve to an incorrect type. |
| 758 // If this fails we'll just get a compiler error on an ambiguous overload. |
| 759 int TestOverload(int) { // Overload fails. |
| 760 return 0; |
| 761 } |
| 762 uint8_t TestOverload(uint8_t) { // Overload fails. |
| 763 return 0; |
| 764 } |
| 765 size_t TestOverload(size_t) { // Overload succeeds. |
| 766 return 0; |
| 767 } |
| 768 |
| 769 static_assert( |
| 770 std::is_same<decltype(TestOverload(StrictNumeric<int>())), int>::value, |
| 771 ""); |
| 772 static_assert(std::is_same<decltype(TestOverload(StrictNumeric<size_t>())), |
| 773 size_t>::value, |
| 774 ""); |
| 775 |
| 686 TEST(SafeNumerics, CastTests) { | 776 TEST(SafeNumerics, CastTests) { |
| 687 // MSVC catches and warns that we're forcing saturation in these tests. | 777 // MSVC catches and warns that we're forcing saturation in these tests. |
| 688 // Since that's intentional, we need to shut this warning off. | 778 // Since that's intentional, we need to shut this warning off. |
| 689 #if defined(COMPILER_MSVC) | 779 #if defined(COMPILER_MSVC) |
| 690 #pragma warning(disable : 4756) | 780 #pragma warning(disable : 4756) |
| 691 #endif | 781 #endif |
| 692 | 782 |
| 693 int small_positive = 1; | 783 int small_positive = 1; |
| 694 int small_negative = -1; | 784 int small_negative = -1; |
| 695 double double_small = 1.0; | 785 double double_small = 1.0; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 float not_a_number = std::numeric_limits<float>::infinity() - | 837 float not_a_number = std::numeric_limits<float>::infinity() - |
| 748 std::numeric_limits<float>::infinity(); | 838 std::numeric_limits<float>::infinity(); |
| 749 EXPECT_TRUE(std::isnan(not_a_number)); | 839 EXPECT_TRUE(std::isnan(not_a_number)); |
| 750 EXPECT_EQ(0, saturated_cast<int>(not_a_number)); | 840 EXPECT_EQ(0, saturated_cast<int>(not_a_number)); |
| 751 | 841 |
| 752 // Test the CheckedNumeric value extractions functions. | 842 // Test the CheckedNumeric value extractions functions. |
| 753 auto int8_min = CheckNum(numeric_limits<int8_t>::min()); | 843 auto int8_min = CheckNum(numeric_limits<int8_t>::min()); |
| 754 auto int8_max = CheckNum(numeric_limits<int8_t>::max()); | 844 auto int8_max = CheckNum(numeric_limits<int8_t>::max()); |
| 755 auto double_max = CheckNum(numeric_limits<double>::max()); | 845 auto double_max = CheckNum(numeric_limits<double>::max()); |
| 756 static_assert( | 846 static_assert( |
| 757 std::is_same<int16_t, decltype(int8_min.ValueOrDie<int16_t>())>::value, | 847 std::is_same<int16_t, |
| 848 decltype(int8_min.ValueOrDie<int16_t>())::type>::value, |
| 758 "ValueOrDie returning incorrect type."); | 849 "ValueOrDie returning incorrect type."); |
| 759 static_assert( | 850 static_assert( |
| 760 std::is_same<int16_t, | 851 std::is_same<int16_t, |
| 761 decltype(int8_min.ValueOrDefault<int16_t>(0))>::value, | 852 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value, |
| 762 "ValueOrDefault returning incorrect type."); | 853 "ValueOrDefault returning incorrect type."); |
| 763 static_assert( | 854 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min)); |
| 764 std::is_same<float, decltype(double_max.ValueFloating<float>())>::value, | 855 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max)); |
| 765 "ValueFloating returning incorrect type."); | |
| 766 EXPECT_FALSE(int8_min.template IsValid<uint8_t>()); | |
| 767 EXPECT_TRUE(int8_max.template IsValid<uint8_t>()); | |
| 768 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::min()), | 856 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::min()), |
| 769 int8_min.template ValueOrDie<int>()); | 857 ValueOrDieForType<int>(int8_min)); |
| 770 EXPECT_TRUE(int8_max.template IsValid<uint32_t>()); | 858 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max)); |
| 771 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()), | 859 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()), |
| 772 int8_max.template ValueOrDie<int>()); | 860 ValueOrDieForType<int>(int8_max)); |
| 861 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0)); |
| 773 uint8_t uint8_dest = 0; | 862 uint8_t uint8_dest = 0; |
| 774 int16_t int16_dest = 0; | 863 int16_t int16_dest = 0; |
| 775 double double_dest = 0; | 864 double double_dest = 0; |
| 776 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest)); | 865 EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest)); |
| 777 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest); | 866 EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest); |
| 778 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest)); | 867 EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest)); |
| 779 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest)); | 868 EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest)); |
| 780 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest); | 869 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest); |
| 781 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest)); | 870 EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest)); |
| 782 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::min()), int16_dest); | 871 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::min()), int16_dest); |
| 783 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest)); | 872 EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest)); |
| 784 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest)); | 873 EXPECT_FALSE(double_max.AssignIfValid(&int16_dest)); |
| 785 EXPECT_TRUE(double_max.AssignIfValid(&double_dest)); | 874 EXPECT_TRUE(double_max.AssignIfValid(&double_dest)); |
| 786 EXPECT_EQ(numeric_limits<double>::max(), double_dest); | 875 EXPECT_EQ(numeric_limits<double>::max(), double_dest); |
| 876 EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1))); |
| 877 EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1))); |
| 878 EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1))); |
| 787 } | 879 } |
| 788 | 880 |
| 789 TEST(SafeNumerics, SaturatedCastChecks) { | 881 TEST(SafeNumerics, SaturatedCastChecks) { |
| 790 float not_a_number = std::numeric_limits<float>::infinity() - | 882 float not_a_number = std::numeric_limits<float>::infinity() - |
| 791 std::numeric_limits<float>::infinity(); | 883 std::numeric_limits<float>::infinity(); |
| 792 EXPECT_TRUE(std::isnan(not_a_number)); | 884 EXPECT_TRUE(std::isnan(not_a_number)); |
| 793 EXPECT_DEATH_IF_SUPPORTED( | 885 EXPECT_DEATH_IF_SUPPORTED( |
| 794 (saturated_cast<int, base::CheckOnFailure>(not_a_number)), | 886 (saturated_cast<int, base::CheckOnFailure>(not_a_number)), |
| 795 ""); | 887 ""); |
| 796 } | 888 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 889 too_large += d; | 981 too_large += d; |
| 890 EXPECT_FALSE(too_large.IsValid()); | 982 EXPECT_FALSE(too_large.IsValid()); |
| 891 too_large -= d; | 983 too_large -= d; |
| 892 EXPECT_FALSE(too_large.IsValid()); | 984 EXPECT_FALSE(too_large.IsValid()); |
| 893 too_large /= d; | 985 too_large /= d; |
| 894 EXPECT_FALSE(too_large.IsValid()); | 986 EXPECT_FALSE(too_large.IsValid()); |
| 895 } | 987 } |
| 896 | 988 |
| 897 TEST(SafeNumerics, VariadicNumericOperations) { | 989 TEST(SafeNumerics, VariadicNumericOperations) { |
| 898 auto a = CheckAdd(1, 2UL, CheckNum(3LL), 4).ValueOrDie(); | 990 auto a = CheckAdd(1, 2UL, CheckNum(3LL), 4).ValueOrDie(); |
| 899 EXPECT_EQ(static_cast<decltype(a)>(10), a); | 991 EXPECT_EQ(static_cast<decltype(a)::type>(10), a); |
| 900 auto b = CheckSub(CheckNum(20.0), 2UL, 4).ValueOrDie(); | 992 auto b = CheckSub(CheckNum(20.0), 2UL, 4).ValueOrDie(); |
| 901 EXPECT_EQ(static_cast<decltype(b)>(14.0), b); | 993 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b); |
| 902 auto c = CheckMul(20.0, CheckNum(1), 5, 3UL).ValueOrDie(); | 994 auto c = CheckMul(20.0, CheckNum(1), 5, 3UL).ValueOrDie(); |
| 903 EXPECT_EQ(static_cast<decltype(c)>(300.0), c); | 995 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c); |
| 904 auto d = CheckDiv(20.0, 2.0, CheckNum(5LL), -4).ValueOrDie(); | 996 auto d = CheckDiv(20.0, 2.0, CheckNum(5LL), -4).ValueOrDie(); |
| 905 EXPECT_EQ(static_cast<decltype(d)>(-.5), d); | 997 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d); |
| 906 auto e = CheckMod(CheckNum(20), 3).ValueOrDie(); | 998 auto e = CheckMod(CheckNum(20), 3).ValueOrDie(); |
| 907 EXPECT_EQ(static_cast<decltype(e)>(2), e); | 999 EXPECT_EQ(static_cast<decltype(e)::type>(2), e); |
| 908 auto f = CheckLsh(1, CheckNum(2)).ValueOrDie(); | 1000 auto f = CheckLsh(1, CheckNum(2)).ValueOrDie(); |
| 909 EXPECT_EQ(static_cast<decltype(f)>(4), f); | 1001 EXPECT_EQ(static_cast<decltype(f)::type>(4), f); |
| 910 auto g = CheckRsh(4, CheckNum(2)).ValueOrDie(); | 1002 auto g = CheckRsh(4, CheckNum(2)).ValueOrDie(); |
| 911 EXPECT_EQ(static_cast<decltype(g)>(1), g); | 1003 EXPECT_EQ(static_cast<decltype(g)::type>(1), g); |
| 912 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie(); | 1004 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie(); |
| 913 EXPECT_EQ(static_cast<decltype(h)>(1), h); | 1005 EXPECT_EQ(static_cast<decltype(h)::type>(1), h); |
| 914 } | 1006 } |
| OLD | NEW |