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 #include <stddef.h>
6 #include <stdint.h>
7 
8 #include <limits>
9 #include <type_traits>
10 
11 #include "base/compiler_specific.h"
12 #include "base/logging.h"
13 #include "base/numerics/safe_conversions.h"
14 #include "base/numerics/safe_math.h"
15 #include "base/test/gtest_util.h"
16 #include "build/build_config.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 #if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
20 #include <mmintrin.h>
21 #endif
22 
23 using std::numeric_limits;
24 using base::CheckedNumeric;
25 using base::IsValidForType;
26 using base::ValueOrDieForType;
27 using base::ValueOrDefaultForType;
28 using base::MakeCheckedNum;
29 using base::CheckMax;
30 using base::CheckMin;
31 using base::CheckAdd;
32 using base::CheckSub;
33 using base::CheckMul;
34 using base::CheckDiv;
35 using base::CheckMod;
36 using base::CheckLsh;
37 using base::CheckRsh;
38 using base::checked_cast;
39 using base::IsValueInRangeForNumericType;
40 using base::IsValueNegative;
41 using base::SizeT;
42 using base::StrictNumeric;
43 using base::MakeStrictNum;
44 using base::saturated_cast;
45 using base::strict_cast;
46 using base::internal::MaxExponent;
47 using base::internal::IntegerBitsPlusSign;
48 using base::internal::RangeCheck;
49 
50 // These tests deliberately cause arithmetic boundary errors. If the compiler is
51 // aggressive enough, it can const detect these errors, so we disable warnings.
52 #if defined(OS_WIN)
53 #pragma warning(disable : 4756)  // Arithmetic overflow.
54 #pragma warning(disable : 4293)  // Invalid shift.
55 #endif
56 
57 // This is a helper function for finding the maximum value in Src that can be
58 // wholy represented as the destination floating-point type.
59 template <typename Dst, typename Src>
GetMaxConvertibleToFloat()60 Dst GetMaxConvertibleToFloat() {
61   using DstLimits = numeric_limits<Dst>;
62   using SrcLimits = numeric_limits<Src>;
63   static_assert(SrcLimits::is_specialized, "Source must be numeric.");
64   static_assert(DstLimits::is_specialized, "Destination must be numeric.");
65   CHECK(DstLimits::is_iec559);
66 
67   if (SrcLimits::digits <= DstLimits::digits &&
68       MaxExponent<Src>::value <= MaxExponent<Dst>::value)
69     return SrcLimits::max();
70   Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
71   while (max != static_cast<Src>(static_cast<Dst>(max))) {
72     max /= 2;
73   }
74   return static_cast<Dst>(max);
75 }
76 
77 namespace base {
78 namespace internal {
79 
80 // Test corner case promotions used
81 static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int8_t>::value, "");
82 static_assert(IsIntegerArithmeticSafe<int32_t, int16_t, int8_t>::value, "");
83 static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int16_t>::value, "");
84 static_assert(!IsIntegerArithmeticSafe<int32_t, int32_t, int8_t>::value, "");
85 static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
86 static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
87 static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
88 static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
89 static_assert(
90     std::is_same<BigEnoughPromotion<int16_t, int8_t>::type, int16_t>::value,
91     "");
92 static_assert(
93     std::is_same<BigEnoughPromotion<int32_t, uint32_t>::type, int64_t>::value,
94     "");
95 static_assert(
96     std::is_same<BigEnoughPromotion<intmax_t, int8_t>::type, intmax_t>::value,
97     "");
98 static_assert(
99     std::is_same<BigEnoughPromotion<uintmax_t, int8_t>::type, uintmax_t>::value,
100     "");
101 static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
102 static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
103 static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
104 static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
105 static_assert(
106     std::is_same<FastIntegerArithmeticPromotion<int16_t, int8_t>::type,
107                  int32_t>::value,
108     "");
109 static_assert(
110     std::is_same<FastIntegerArithmeticPromotion<int32_t, uint32_t>::type,
111                  int64_t>::value,
112     "");
113 static_assert(
114     std::is_same<FastIntegerArithmeticPromotion<intmax_t, int8_t>::type,
115                  intmax_t>::value,
116     "");
117 static_assert(
118     std::is_same<FastIntegerArithmeticPromotion<uintmax_t, int8_t>::type,
119                  uintmax_t>::value,
120     "");
121 static_assert(FastIntegerArithmeticPromotion<int16_t, int8_t>::is_contained,
122               "");
123 static_assert(FastIntegerArithmeticPromotion<int32_t, uint32_t>::is_contained,
124               "");
125 static_assert(!FastIntegerArithmeticPromotion<intmax_t, int8_t>::is_contained,
126               "");
127 static_assert(!FastIntegerArithmeticPromotion<uintmax_t, int8_t>::is_contained,
128               "");
129 
130 template <typename U>
GetNumericValueForTest(const CheckedNumeric<U> & src)131 U GetNumericValueForTest(const CheckedNumeric<U>& src) {
132   return src.state_.value();
133 }
134 }  // namespace internal.
135 }  // namespace base.
136 
137 using base::internal::GetNumericValueForTest;
138 
139 // Logs the ValueOrDie() failure instead of crashing.
140 struct LogOnFailure {
141   template <typename T>
HandleFailureLogOnFailure142   static T HandleFailure() {
143     LOG(WARNING) << "ValueOrDie() failed unexpectedly.";
144     return T();
145   }
146 };
147 
148 // Helper macros to wrap displaying the conversion types and line numbers.
149 #define TEST_EXPECTED_VALIDITY(expected, actual)                           \
150   EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid())             \
151       << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
152       << dst << " on line " << line
153 
154 #define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
155 #define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
156 
157 // We have to handle promotions, so infer the underlying type below from actual.
158 #define TEST_EXPECTED_VALUE(expected, actual)                               \
159   EXPECT_EQ(static_cast<typename std::decay<decltype(actual)>::type::type>( \
160                 expected),                                                  \
161             ((actual)                                                       \
162                  .template ValueOrDie<                                      \
163                      typename std::decay<decltype(actual)>::type::type,     \
164                      LogOnFailure>()))                                      \
165       << "Result test: Value " << GetNumericValueForTest(actual) << " as "  \
166       << dst << " on line " << line
167 
168 // Test the simple pointer arithmetic overrides.
169 template <typename Dst>
TestStrictPointerMath()170 void TestStrictPointerMath() {
171   Dst dummy_value = 0;
172   Dst* dummy_ptr = &dummy_value;
173   static const Dst kDummyOffset = 2;  // Don't want to go too far.
174   EXPECT_EQ(dummy_ptr + kDummyOffset,
175             dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
176   EXPECT_EQ(dummy_ptr - kDummyOffset,
177             dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
178   EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
179   EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
180   EXPECT_DEATH_IF_SUPPORTED(
181       dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()),
182       "");
183 }
184 
185 // Signed integer arithmetic.
186 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,typename std::enable_if<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed,int>::type=0)187 static void TestSpecializedArithmetic(
188     const char* dst,
189     int line,
190     typename std::enable_if<numeric_limits<Dst>::is_integer &&
191                                 numeric_limits<Dst>::is_signed,
192                             int>::type = 0) {
193   using DstLimits = numeric_limits<Dst>;
194   TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
195   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
196   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
197   TEST_EXPECTED_VALUE(DstLimits::max(),
198                       MakeCheckedNum(-DstLimits::max()).Abs());
199 
200   TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
201   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
202   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
203                         DstLimits::lowest());
204 
205   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
206   TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
207   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
208                         DstLimits::lowest());
209   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
210                         DstLimits::max());
211 
212   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
213 
214   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
215   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
216   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
217   TEST_EXPECTED_VALUE(DstLimits::max(),
218                       CheckedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
219   TEST_EXPECTED_VALUE(DstLimits::max(),
220                       CheckedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
221   TEST_EXPECTED_VALUE(DstLimits::lowest(),
222                       CheckedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
223   TEST_EXPECTED_VALUE(DstLimits::lowest(),
224                       CheckedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
225   TEST_EXPECTED_VALUE(DstLimits::lowest(),
226                       MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
227   TEST_EXPECTED_VALUE(DstLimits::max(),
228                       MakeCheckedNum(DstLimits::max()).UnsignedAbs());
229   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
230   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
231   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).UnsignedAbs());
232 
233   // Modulus is legal only for integers.
234   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
235   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
236   TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
237   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
238   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
239   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
240   // Test all the different modulus combinations.
241   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
242   TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
243   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
244   CheckedNumeric<Dst> checked_dst = 1;
245   TEST_EXPECTED_VALUE(0, checked_dst %= 1);
246   // Test that div by 0 is avoided but returns invalid result.
247   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
248   // Test bit shifts.
249   volatile Dst negative_one = -1;
250   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
251   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
252                         << (IntegerBitsPlusSign<Dst>::value - 1));
253   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
254                         << IntegerBitsPlusSign<Dst>::value);
255   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
256   TEST_EXPECTED_VALUE(
257       static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2),
258       CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2));
259   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
260                              << (IntegerBitsPlusSign<Dst>::value - 1));
261   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
262   TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
263   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
264                         IntegerBitsPlusSign<Dst>::value);
265   TEST_EXPECTED_VALUE(
266       0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
267   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
268 
269   TestStrictPointerMath<Dst>();
270 }
271 
272 // Unsigned integer arithmetic.
273 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,typename std::enable_if<numeric_limits<Dst>::is_integer &&!numeric_limits<Dst>::is_signed,int>::type=0)274 static void TestSpecializedArithmetic(
275     const char* dst,
276     int line,
277     typename std::enable_if<numeric_limits<Dst>::is_integer &&
278                                 !numeric_limits<Dst>::is_signed,
279                             int>::type = 0) {
280   using DstLimits = numeric_limits<Dst>;
281   TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
282   TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
283   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
284   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
285   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
286   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
287   TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
288   TEST_EXPECTED_SUCCESS(
289       CheckedNumeric<typename std::make_signed<Dst>::type>(
290           std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
291           .UnsignedAbs());
292   TEST_EXPECTED_VALUE(DstLimits::lowest(),
293                       MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
294   TEST_EXPECTED_VALUE(DstLimits::max(),
295                       MakeCheckedNum(DstLimits::max()).UnsignedAbs());
296   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
297   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
298 
299   // Modulus is legal only for integers.
300   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
301   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
302   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
303   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
304   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
305   // Test all the different modulus combinations.
306   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
307   TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
308   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
309   CheckedNumeric<Dst> checked_dst = 1;
310   TEST_EXPECTED_VALUE(0, checked_dst %= 1);
311   // Test that div by 0 is avoided but returns invalid result.
312   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
313   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
314                         << IntegerBitsPlusSign<Dst>::value);
315   // Test bit shifts.
316   volatile int negative_one = -1;
317   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
318   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
319                         << IntegerBitsPlusSign<Dst>::value);
320   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
321                         << IntegerBitsPlusSign<Dst>::value);
322   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
323   TEST_EXPECTED_VALUE(
324       static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1),
325       CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1));
326   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
327   TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
328   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
329                         IntegerBitsPlusSign<Dst>::value);
330   TEST_EXPECTED_VALUE(
331       0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
332   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
333   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1);
334   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
335   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1);
336   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
337   TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
338                       MakeCheckedNum(DstLimits::max()) & -1);
339   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1);
340   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0);
341   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1);
342   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0);
343   TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
344                       CheckedNumeric<Dst>(0) | static_cast<Dst>(-1));
345   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1);
346   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0);
347   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1);
348   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0);
349   TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
350                       CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
351   TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
352 
353   TestStrictPointerMath<Dst>();
354 }
355 
356 // Floating point arithmetic.
357 template <typename Dst>
TestSpecializedArithmetic(const char * dst,int line,typename std::enable_if<numeric_limits<Dst>::is_iec559,int>::type=0)358 void TestSpecializedArithmetic(
359     const char* dst,
360     int line,
361     typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
362   using DstLimits = numeric_limits<Dst>;
363   TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
364 
365   TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
366   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
367 
368   TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
369   TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
370   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
371                         DstLimits::lowest());
372 
373   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
374                         DstLimits::lowest());
375   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
376                         DstLimits::max());
377 
378   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
379 
380   TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
381 }
382 
383 // Generic arithmetic tests.
384 template <typename Dst>
TestArithmetic(const char * dst,int line)385 static void TestArithmetic(const char* dst, int line) {
386   using DstLimits = numeric_limits<Dst>;
387 
388   EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
389   EXPECT_EQ(false,
390             CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
391                                 DstLimits::max()).IsValid());
392   EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
393   EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
394   EXPECT_EQ(static_cast<Dst>(1),
395             CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
396                                 DstLimits::max()).ValueOrDefault(1));
397 
398   // Test the operator combinations.
399   TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
400   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
401   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
402   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
403   TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
404   TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
405   TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
406   TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
407   TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
408   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
409   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
410   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
411   CheckedNumeric<Dst> checked_dst = 1;
412   TEST_EXPECTED_VALUE(2, checked_dst += 1);
413   checked_dst = 1;
414   TEST_EXPECTED_VALUE(0, checked_dst -= 1);
415   checked_dst = 1;
416   TEST_EXPECTED_VALUE(1, checked_dst *= 1);
417   checked_dst = 1;
418   TEST_EXPECTED_VALUE(1, checked_dst /= 1);
419 
420   // Generic negation.
421   if (DstLimits::is_signed) {
422     TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
423     TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
424     TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
425     TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
426                         -CheckedNumeric<Dst>(DstLimits::max()));
427   }
428 
429   // Generic absolute value.
430   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
431   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
432   TEST_EXPECTED_VALUE(DstLimits::max(),
433                       CheckedNumeric<Dst>(DstLimits::max()).Abs());
434 
435   // Generic addition.
436   TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
437   TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
438   if (numeric_limits<Dst>::is_signed)
439     TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
440   TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + 1);
441   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
442                         DstLimits::max());
443 
444   // Generic subtraction.
445   TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
446   TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
447   if (numeric_limits<Dst>::is_signed) {
448     TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
449     TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
450   } else {
451     TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
452   }
453 
454   // Generic multiplication.
455   TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
456   TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
457   TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
458   if (numeric_limits<Dst>::is_signed) {
459     TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
460     TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
461     TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
462   } else {
463     TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * -2);
464     TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
465                           CheckedNumeric<uintmax_t>(-2));
466   }
467   TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
468                         DstLimits::max());
469 
470   // Generic division.
471   TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
472   TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
473   TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
474                       CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
475   TEST_EXPECTED_VALUE(DstLimits::max() / 2,
476                       CheckedNumeric<Dst>(DstLimits::max()) / 2);
477 
478   TestSpecializedArithmetic<Dst>(dst, line);
479 }
480 
481 // Helper macro to wrap displaying the conversion types and line numbers.
482 #define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
483 
TEST(SafeNumerics,SignedIntegerMath)484 TEST(SafeNumerics, SignedIntegerMath) {
485   TEST_ARITHMETIC(int8_t);
486   TEST_ARITHMETIC(int);
487   TEST_ARITHMETIC(intptr_t);
488   TEST_ARITHMETIC(intmax_t);
489 }
490 
TEST(SafeNumerics,UnsignedIntegerMath)491 TEST(SafeNumerics, UnsignedIntegerMath) {
492   TEST_ARITHMETIC(uint8_t);
493   TEST_ARITHMETIC(unsigned int);
494   TEST_ARITHMETIC(uintptr_t);
495   TEST_ARITHMETIC(uintmax_t);
496 }
497 
TEST(SafeNumerics,FloatingPointMath)498 TEST(SafeNumerics, FloatingPointMath) {
499   TEST_ARITHMETIC(float);
500   TEST_ARITHMETIC(double);
501 }
502 
503 // Enumerates the five different conversions types we need to test.
504 enum NumericConversionType {
505   SIGN_PRESERVING_VALUE_PRESERVING,
506   SIGN_PRESERVING_NARROW,
507   SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
508   SIGN_TO_UNSIGN_NARROW,
509   UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
510 };
511 
512 // Template covering the different conversion tests.
513 template <typename Dst, typename Src, NumericConversionType conversion>
514 struct TestNumericConversion {};
515 
516 enum RangeConstraint {
517   RANGE_VALID = 0x0,      // Value can be represented by the destination type.
518   RANGE_UNDERFLOW = 0x1,  // Value would underflow.
519   RANGE_OVERFLOW = 0x2,   // Value would overflow.
520   RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW  // Invalid (i.e. NaN).
521 };
522 
523 // These are some wrappers to make the tests a bit cleaner.
RangeCheckToEnum(const RangeCheck constraint)524 constexpr RangeConstraint RangeCheckToEnum(const RangeCheck constraint) {
525   return static_cast<RangeConstraint>(
526       static_cast<int>(constraint.IsOverflowFlagSet()) << 1 |
527       static_cast<int>(constraint.IsUnderflowFlagSet()));
528 }
529 
530 // EXPECT_EQ wrappers providing specific detail on test failures.
531 #define TEST_EXPECTED_RANGE(expected, actual)                               \
532   EXPECT_EQ(expected,                                                       \
533             RangeCheckToEnum(                                               \
534                 base::internal::DstRangeRelationToSrcRange<Dst>(actual)))   \
535       << "Conversion test: " << src << " value " << actual << " to " << dst \
536       << " on line " << line
537 
538 template <typename Dst, typename Src>
TestStrictComparison()539 void TestStrictComparison() {
540   using DstLimits = numeric_limits<Dst>;
541   using SrcLimits = numeric_limits<Src>;
542   static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < DstLimits::max(), "");
543   static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < SrcLimits::max(), "");
544   static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= DstLimits::max()),
545                 "");
546   static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= SrcLimits::max()),
547                 "");
548   static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= DstLimits::max(),
549                 "");
550   static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= SrcLimits::max(),
551                 "");
552   static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > DstLimits::max()),
553                 "");
554   static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > SrcLimits::max()),
555                 "");
556   static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::lowest(), "");
557   static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::lowest(), "");
558   static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::lowest()),
559                 "");
560   static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::lowest()),
561                 "");
562   static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::lowest(),
563                 "");
564   static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::lowest(),
565                 "");
566   static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::lowest()),
567                 "");
568   static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::lowest()),
569                 "");
570   static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1),
571                 "");
572   static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0),
573                 "");
574   static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0),
575                 "");
576   static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(),
577                 "");
578   static_assert(
579       !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), "");
580   static_assert(
581       !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), "");
582 
583   // Due to differences in float handling between compilers, these aren't
584   // compile-time constants everywhere. So, we use run-time tests.
585   EXPECT_EQ(
586       SrcLimits::max(),
587       MakeCheckedNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie());
588   EXPECT_EQ(
589       DstLimits::max(),
590       MakeCheckedNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie());
591   EXPECT_EQ(
592       DstLimits::lowest(),
593       MakeCheckedNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie());
594   EXPECT_EQ(
595       SrcLimits::lowest(),
596       MakeCheckedNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie());
597   EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), MakeCheckedNum(0),
598                                           DstLimits::max(), SrcLimits::lowest())
599                                      .ValueOrDie());
600   EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0),
601                                        DstLimits::max(), SrcLimits::lowest())
602                                   .ValueOrDie());
603 }
604 
605 template <typename Dst, typename Src>
606 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
TestTestNumericConversion607   static void Test(const char *dst, const char *src, int line) {
608     using SrcLimits = numeric_limits<Src>;
609     using DstLimits = numeric_limits<Dst>;
610     // Integral to floating.
611     static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
612                       // Not floating to integral and...
613                       (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
614                        // Same sign, same numeric, source is narrower or same.
615                        ((SrcLimits::is_signed == DstLimits::is_signed &&
616                          MaxExponent<Dst>::value >= MaxExponent<Src>::value) ||
617                         // Or signed destination and source is smaller
618                         (DstLimits::is_signed &&
619                          MaxExponent<Dst>::value >= MaxExponent<Src>::value))),
620                   "Comparison must be sign preserving and value preserving");
621 
622     TestStrictComparison<Dst, Src>();
623 
624     const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
625     TEST_EXPECTED_SUCCESS(checked_dst);
626     if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
627       if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
628         // At least twice larger type.
629         TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
630 
631       } else {  // Larger, but not at least twice as large.
632         TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
633         TEST_EXPECTED_SUCCESS(checked_dst + 1);
634       }
635     } else {  // Same width type.
636       TEST_EXPECTED_FAILURE(checked_dst + 1);
637     }
638 
639     TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
640     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
641     if (SrcLimits::is_iec559) {
642       TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
643       TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
644       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
645       TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
646     } else if (numeric_limits<Src>::is_signed) {
647       TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
648       TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
649     }
650   }
651 };
652 
653 template <typename Dst, typename Src>
654 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
TestTestNumericConversion655   static void Test(const char *dst, const char *src, int line) {
656     using SrcLimits = numeric_limits<Src>;
657     using DstLimits = numeric_limits<Dst>;
658     static_assert(SrcLimits::is_signed == DstLimits::is_signed,
659                   "Destination and source sign must be the same");
660     static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
661                   "Destination must be narrower than source");
662 
663     TestStrictComparison<Dst, Src>();
664 
665     const CheckedNumeric<Dst> checked_dst;
666     TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
667     TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
668     TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
669 
670     TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
671     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
672     if (SrcLimits::is_iec559) {
673       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
674       TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
675       TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
676       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
677       TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
678       if (DstLimits::is_integer) {
679         if (SrcLimits::digits < DstLimits::digits) {
680           TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
681                               static_cast<Src>(DstLimits::max()));
682         } else {
683           TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
684         }
685         TEST_EXPECTED_RANGE(
686             RANGE_VALID,
687             static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
688         TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
689       }
690     } else if (SrcLimits::is_signed) {
691       TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
692       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
693       TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
694     } else {
695       TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
696       TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
697     }
698   }
699 };
700 
701 template <typename Dst, typename Src>
702 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
TestTestNumericConversion703   static void Test(const char *dst, const char *src, int line) {
704     using SrcLimits = numeric_limits<Src>;
705     using DstLimits = numeric_limits<Dst>;
706     static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
707                   "Destination must be equal or wider than source.");
708     static_assert(SrcLimits::is_signed, "Source must be signed");
709     static_assert(!DstLimits::is_signed, "Destination must be unsigned");
710 
711     TestStrictComparison<Dst, Src>();
712 
713     const CheckedNumeric<Dst> checked_dst;
714     TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
715     TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
716     TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
717 
718     TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
719     TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
720     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
721     TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
722   }
723 };
724 
725 template <typename Dst, typename Src>
726 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
TestTestNumericConversion727   static void Test(const char *dst, const char *src, int line) {
728     using SrcLimits = numeric_limits<Src>;
729     using DstLimits = numeric_limits<Dst>;
730     static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
731                   "Destination must be narrower than source.");
732     static_assert(SrcLimits::is_signed, "Source must be signed.");
733     static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
734 
735     TestStrictComparison<Dst, Src>();
736 
737     const CheckedNumeric<Dst> checked_dst;
738     TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
739     TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
740     TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
741     TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
742 
743     TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
744     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
745     TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
746 
747     // Additional saturation tests.
748     EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max())) << src;
749     EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
750 
751     if (SrcLimits::is_iec559) {
752       EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
753 
754       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
755       TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
756       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
757       TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
758       if (DstLimits::is_integer) {
759         if (SrcLimits::digits < DstLimits::digits) {
760           TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
761                               static_cast<Src>(DstLimits::max()));
762         } else {
763           TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
764         }
765         TEST_EXPECTED_RANGE(
766             RANGE_VALID,
767             static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
768         TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
769       }
770     } else {
771       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
772     }
773   }
774 };
775 
776 template <typename Dst, typename Src>
777 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
TestTestNumericConversion778   static void Test(const char *dst, const char *src, int line) {
779     using SrcLimits = numeric_limits<Src>;
780     using DstLimits = numeric_limits<Dst>;
781     static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
782                   "Destination must be narrower or equal to source.");
783     static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
784     static_assert(DstLimits::is_signed, "Destination must be signed.");
785 
786     TestStrictComparison<Dst, Src>();
787 
788     const CheckedNumeric<Dst> checked_dst;
789     TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
790     TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
791     TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
792 
793     TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
794     TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
795     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
796 
797     // Additional saturation tests.
798     EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
799     EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
800   }
801 };
802 
803 // Helper macro to wrap displaying the conversion types and line numbers
804 #define TEST_NUMERIC_CONVERSION(d, s, t) \
805   TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
806 
TEST(SafeNumerics,IntMinOperations)807 TEST(SafeNumerics, IntMinOperations) {
808   TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
809   TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
810 
811   TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
812   TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
813   TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
814 
815   TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
816 
817   TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
818   TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
819   TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
820 
821   TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
822   TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
823 }
824 
TEST(SafeNumerics,IntOperations)825 TEST(SafeNumerics, IntOperations) {
826   TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
827   TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
828                           SIGN_PRESERVING_VALUE_PRESERVING);
829   TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
830   TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
831                           SIGN_PRESERVING_VALUE_PRESERVING);
832   TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
833 
834   TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
835   TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
836   TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
837   TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
838 
839   TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
840   TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
841 
842   TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
843   TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
844   TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
845 
846   TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
847   TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
848 }
849 
TEST(SafeNumerics,IntMaxOperations)850 TEST(SafeNumerics, IntMaxOperations) {
851   TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
852   TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
853                           SIGN_PRESERVING_VALUE_PRESERVING);
854   TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
855   TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
856                           SIGN_PRESERVING_VALUE_PRESERVING);
857   TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
858                           SIGN_PRESERVING_VALUE_PRESERVING);
859   TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
860 
861   TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
862   TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
863 
864   TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
865   TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
866 
867   TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
868   TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
869 
870   TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
871 }
872 
TEST(SafeNumerics,FloatOperations)873 TEST(SafeNumerics, FloatOperations) {
874   TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
875   TEST_NUMERIC_CONVERSION(float, uintmax_t,
876                           SIGN_PRESERVING_VALUE_PRESERVING);
877   TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
878   TEST_NUMERIC_CONVERSION(float, unsigned int,
879                           SIGN_PRESERVING_VALUE_PRESERVING);
880 
881   TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
882 }
883 
TEST(SafeNumerics,DoubleOperations)884 TEST(SafeNumerics, DoubleOperations) {
885   TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
886   TEST_NUMERIC_CONVERSION(double, uintmax_t,
887                           SIGN_PRESERVING_VALUE_PRESERVING);
888   TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
889   TEST_NUMERIC_CONVERSION(double, unsigned int,
890                           SIGN_PRESERVING_VALUE_PRESERVING);
891 }
892 
TEST(SafeNumerics,SizeTOperations)893 TEST(SafeNumerics, SizeTOperations) {
894   TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
895   TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
896 }
897 
898 // A one-off test to ensure StrictNumeric won't resolve to an incorrect type.
899 // If this fails we'll just get a compiler error on an ambiguous overload.
TestOverload(int)900 int TestOverload(int) {  // Overload fails.
901   return 0;
902 }
TestOverload(uint8_t)903 uint8_t TestOverload(uint8_t) {  // Overload fails.
904   return 0;
905 }
TestOverload(size_t)906 size_t TestOverload(size_t) {  // Overload succeeds.
907   return 0;
908 }
909 
910 static_assert(
911     std::is_same<decltype(TestOverload(StrictNumeric<int>())), int>::value,
912     "");
913 static_assert(std::is_same<decltype(TestOverload(StrictNumeric<size_t>())),
914                            size_t>::value,
915               "");
916 
917 template <typename T>
918 struct CastTest1 {
NaNCastTest1919   static constexpr T NaN() { return -1; }
maxCastTest1920   static constexpr T max() { return numeric_limits<T>::max() - 1; }
OverflowCastTest1921   static constexpr T Overflow() { return max(); }
lowestCastTest1922   static constexpr T lowest() { return numeric_limits<T>::lowest() + 1; }
UnderflowCastTest1923   static constexpr T Underflow() { return lowest(); }
924 };
925 
926 template <typename T>
927 struct CastTest2 {
NaNCastTest2928   static constexpr T NaN() { return 11; }
maxCastTest2929   static constexpr T max() { return 10; }
OverflowCastTest2930   static constexpr T Overflow() { return max(); }
lowestCastTest2931   static constexpr T lowest() { return 1; }
UnderflowCastTest2932   static constexpr T Underflow() { return lowest(); }
933 };
934 
TEST(SafeNumerics,CastTests)935 TEST(SafeNumerics, CastTests) {
936 // MSVC catches and warns that we're forcing saturation in these tests.
937 // Since that's intentional, we need to shut this warning off.
938 #if defined(COMPILER_MSVC)
939 #pragma warning(disable : 4756)
940 #endif
941 
942   int small_positive = 1;
943   int small_negative = -1;
944   double double_small = 1.0;
945   double double_large = numeric_limits<double>::max();
946   double double_infinity = numeric_limits<float>::infinity();
947   double double_large_int = numeric_limits<int>::max();
948   double double_small_int = numeric_limits<int>::lowest();
949 
950   // Just test that the casts compile, since the other tests cover logic.
951   EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
952   EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
953   EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
954   EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
955   EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
956   EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
957   EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
958 
959   EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
960   EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
961   EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
962 
963   EXPECT_TRUE(IsValueNegative(-1));
964   EXPECT_TRUE(IsValueNegative(numeric_limits<int>::lowest()));
965   EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::lowest()));
966   EXPECT_TRUE(IsValueNegative(numeric_limits<double>::lowest()));
967   EXPECT_FALSE(IsValueNegative(0));
968   EXPECT_FALSE(IsValueNegative(1));
969   EXPECT_FALSE(IsValueNegative(0u));
970   EXPECT_FALSE(IsValueNegative(1u));
971   EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
972   EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
973   EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
974 
975   // These casts and coercions will fail to compile:
976   // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
977   // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
978   // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
979   // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
980 
981   // Test various saturation corner cases.
982   EXPECT_EQ(saturated_cast<int>(small_negative),
983             static_cast<int>(small_negative));
984   EXPECT_EQ(saturated_cast<int>(small_positive),
985             static_cast<int>(small_positive));
986   EXPECT_EQ(saturated_cast<unsigned>(small_negative),
987             static_cast<unsigned>(0));
988   EXPECT_EQ(saturated_cast<int>(double_small),
989             static_cast<int>(double_small));
990   EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
991   EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
992   EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
993   EXPECT_EQ(numeric_limits<int>::lowest(),
994             saturated_cast<int>(double_small_int));
995   EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
996 
997   // Test the saturated cast overrides.
998   using FloatLimits = numeric_limits<float>;
999   using IntLimits = numeric_limits<int>;
1000   EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(FloatLimits::quiet_NaN())));
1001   EXPECT_EQ(CastTest1<int>::max(),
1002             (saturated_cast<int, CastTest1>(FloatLimits::infinity())));
1003   EXPECT_EQ(CastTest1<int>::max(),
1004             (saturated_cast<int, CastTest1>(FloatLimits::max())));
1005   EXPECT_EQ(CastTest1<int>::max(),
1006             (saturated_cast<int, CastTest1>(float(IntLimits::max()))));
1007   EXPECT_EQ(CastTest1<int>::lowest(),
1008             (saturated_cast<int, CastTest1>(-FloatLimits::infinity())));
1009   EXPECT_EQ(CastTest1<int>::lowest(),
1010             (saturated_cast<int, CastTest1>(FloatLimits::lowest())));
1011   EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0.0)));
1012   EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1.0)));
1013   EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1.0)));
1014   EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0)));
1015   EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1)));
1016   EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1)));
1017   EXPECT_EQ(CastTest1<int>::lowest(),
1018             (saturated_cast<int, CastTest1>(float(IntLimits::lowest()))));
1019   EXPECT_EQ(11, (saturated_cast<int, CastTest2>(FloatLimits::quiet_NaN())));
1020   EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::infinity())));
1021   EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::max())));
1022   EXPECT_EQ(1, (saturated_cast<int, CastTest2>(-FloatLimits::infinity())));
1023   EXPECT_EQ(1, (saturated_cast<int, CastTest2>(FloatLimits::lowest())));
1024   EXPECT_EQ(1, (saturated_cast<int, CastTest2>(0U)));
1025 
1026   float not_a_number = std::numeric_limits<float>::infinity() -
1027                        std::numeric_limits<float>::infinity();
1028   EXPECT_TRUE(std::isnan(not_a_number));
1029   EXPECT_EQ(0, saturated_cast<int>(not_a_number));
1030 
1031   // Test the CheckedNumeric value extractions functions.
1032   auto int8_min = MakeCheckedNum(numeric_limits<int8_t>::lowest());
1033   auto int8_max = MakeCheckedNum(numeric_limits<int8_t>::max());
1034   auto double_max = MakeCheckedNum(numeric_limits<double>::max());
1035   static_assert(
1036       std::is_same<int16_t,
1037                    decltype(int8_min.ValueOrDie<int16_t>())::type>::value,
1038       "ValueOrDie returning incorrect type.");
1039   static_assert(
1040       std::is_same<int16_t,
1041                    decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value,
1042       "ValueOrDefault returning incorrect type.");
1043   EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
1044   EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
1045   EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::lowest()),
1046             ValueOrDieForType<int>(int8_min));
1047   EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
1048   EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
1049             ValueOrDieForType<int>(int8_max));
1050   EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
1051   uint8_t uint8_dest = 0;
1052   int16_t int16_dest = 0;
1053   double double_dest = 0;
1054   EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest));
1055   EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest);
1056   EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest));
1057   EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest));
1058   EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest);
1059   EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest));
1060   EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::lowest()), int16_dest);
1061   EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest));
1062   EXPECT_FALSE(double_max.AssignIfValid(&int16_dest));
1063   EXPECT_TRUE(double_max.AssignIfValid(&double_dest));
1064   EXPECT_EQ(numeric_limits<double>::max(), double_dest);
1065   EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1)));
1066   EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1)));
1067   EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1)));
1068 }
1069 
TEST(SafeNumerics,IsValueInRangeForNumericType)1070 TEST(SafeNumerics, IsValueInRangeForNumericType) {
1071   EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
1072   EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
1073   EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
1074   EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
1075   EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
1076   EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
1077   EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
1078   EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
1079   EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
1080       std::numeric_limits<int32_t>::lowest()));
1081   EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
1082       std::numeric_limits<int64_t>::lowest()));
1083 
1084   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
1085   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
1086   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
1087   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
1088   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
1089   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
1090   EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
1091   EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
1092   EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
1093   EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
1094   EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
1095   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
1096       std::numeric_limits<int32_t>::lowest()));
1097   EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
1098       static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
1099   EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
1100       static_cast<int64_t>(std::numeric_limits<int32_t>::lowest()) - 1));
1101   EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
1102       std::numeric_limits<int64_t>::lowest()));
1103 
1104   EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
1105   EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
1106   EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
1107   EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
1108   EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
1109   EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
1110   EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
1111   EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
1112   EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
1113       std::numeric_limits<int32_t>::lowest()));
1114   EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
1115   EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
1116       std::numeric_limits<int64_t>::lowest()));
1117 
1118   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
1119   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
1120   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
1121   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
1122   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
1123   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
1124   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
1125   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
1126   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
1127   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
1128   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
1129   EXPECT_TRUE(
1130       IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
1131   EXPECT_TRUE(
1132       IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
1133   EXPECT_FALSE(
1134       IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
1135   EXPECT_FALSE(
1136       IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
1137   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
1138       std::numeric_limits<int32_t>::lowest()));
1139   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
1140       static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
1141   EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
1142       std::numeric_limits<int64_t>::lowest()));
1143 }
1144 
TEST(SafeNumerics,CompoundNumericOperations)1145 TEST(SafeNumerics, CompoundNumericOperations) {
1146   CheckedNumeric<int> a = 1;
1147   CheckedNumeric<int> b = 2;
1148   CheckedNumeric<int> c = 3;
1149   CheckedNumeric<int> d = 4;
1150   a += b;
1151   EXPECT_EQ(3, a.ValueOrDie());
1152   a -= c;
1153   EXPECT_EQ(0, a.ValueOrDie());
1154   d /= b;
1155   EXPECT_EQ(2, d.ValueOrDie());
1156   d *= d;
1157   EXPECT_EQ(4, d.ValueOrDie());
1158 
1159   CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
1160   EXPECT_TRUE(too_large.IsValid());
1161   too_large += d;
1162   EXPECT_FALSE(too_large.IsValid());
1163   too_large -= d;
1164   EXPECT_FALSE(too_large.IsValid());
1165   too_large /= d;
1166   EXPECT_FALSE(too_large.IsValid());
1167 }
1168 
TEST(SafeNumerics,VariadicNumericOperations)1169 TEST(SafeNumerics, VariadicNumericOperations) {
1170   auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
1171   EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
1172   auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
1173   EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
1174   auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
1175   EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
1176   auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
1177   EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
1178   auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
1179   EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
1180   auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
1181   EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
1182   auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
1183   EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
1184   auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
1185   EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
1186 }
1187