[go: nahoru, domu]

blob: ec6d0037c9f0a0285844c179c9a40130fa4f9169 [file] [log] [blame]
scottmg@chromium.orgc1c090d32013-01-16 23:34:041// 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
avi9b6f42932015-12-26 22:15:145#include <stddef.h>
jschuh@chromium.org4efb2c32014-01-16 06:57:256#include <stdint.h>
7
8#include <limits>
vmpstr98a2fad2015-11-30 20:15:179#include <type_traits>
jschuh@chromium.org4efb2c32014-01-16 06:57:2510
11#include "base/compiler_specific.h"
jschuh224f1d72016-11-25 20:08:4812#include "base/logging.h"
jschuh@chromium.org5bfecbc2014-02-27 13:49:0413#include "base/numerics/safe_conversions.h"
14#include "base/numerics/safe_math.h"
gab190f7542016-08-01 20:03:4115#include "base/test/gtest_util.h"
avi9b6f42932015-12-26 22:15:1416#include "build/build_config.h"
jschuh@chromium.org4efb2c32014-01-16 06:57:2517#include "testing/gtest/include/gtest/gtest.h"
scottmg@chromium.orgc1c090d32013-01-16 23:34:0418
avi9b6f42932015-12-26 22:15:1419#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
20#include <mmintrin.h>
21#endif
22
jschuh@chromium.org5bfecbc2014-02-27 13:49:0423using std::numeric_limits;
24using base::CheckedNumeric;
jschuh23a4b062016-12-02 02:55:0825using base::IsValidForType;
26using base::ValueOrDieForType;
27using base::ValueOrDefaultForType;
jschuh4bc919c2016-12-04 15:08:2728using base::MakeCheckedNum;
jschuh711ac6a2016-12-04 07:17:4829using base::CheckMax;
30using base::CheckMin;
jschuh4fcd6fa2016-11-24 11:58:3931using base::CheckAdd;
32using base::CheckSub;
33using base::CheckMul;
34using base::CheckDiv;
35using base::CheckMod;
36using base::CheckLsh;
37using base::CheckRsh;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0438using base::checked_cast;
jschuhfafe0712015-09-14 20:21:2439using base::IsValueInRangeForNumericType;
jschuh07345e62015-09-22 22:13:3640using base::IsValueNegative;
jschuh4bf22c6d2015-05-28 02:29:2541using base::SizeT;
42using base::StrictNumeric;
jschuh711ac6a2016-12-04 07:17:4843using base::MakeStrictNum;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0444using base::saturated_cast;
jschuh4bf22c6d2015-05-28 02:29:2545using base::strict_cast;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0446using base::internal::MaxExponent;
jschuh5030b002016-12-05 18:21:4847using base::internal::IntegerBitsPlusSign;
jschuh082b2ba2017-01-06 11:40:5448using base::internal::RangeCheck;
jschuh@chromium.org5bfecbc2014-02-27 13:49:0449
jschuh3ab54042016-11-17 06:58:4450// These tests deliberately cause arithmetic boundary errors. If the compiler is
51// aggressive enough, it can const detect these errors, so we disable warnings.
ncbray@chromium.orgb6bf5c322014-08-09 05:24:0252#if defined(OS_WIN)
jschuh3ab54042016-11-17 06:58:4453#pragma warning(disable : 4756) // Arithmetic overflow.
54#pragma warning(disable : 4293) // Invalid shift.
ncbray@chromium.orgb6bf5c322014-08-09 05:24:0255#endif
jschuhfafe0712015-09-14 20:21:2456
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.
59template <typename Dst, typename Src>
60Dst GetMaxConvertibleToFloat() {
jschuh5030b002016-12-05 18:21:4861 using DstLimits = numeric_limits<Dst>;
62 using SrcLimits = numeric_limits<Src>;
jschuhfafe0712015-09-14 20:21:2463 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}
ncbray@chromium.orgb6bf5c322014-08-09 05:24:0276
jschuhd1c1f2e2016-11-21 21:45:4877namespace base {
78namespace internal {
jschuh33232e02017-01-03 20:33:3679
80// Test corner case promotions used
81static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int8_t>::value, "");
82static_assert(IsIntegerArithmeticSafe<int32_t, int16_t, int8_t>::value, "");
83static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int16_t>::value, "");
84static_assert(!IsIntegerArithmeticSafe<int32_t, int32_t, int8_t>::value, "");
85static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
86static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
87static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
88static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
89static_assert(
90 std::is_same<BigEnoughPromotion<int16_t, int8_t>::type, int16_t>::value,
91 "");
92static_assert(
93 std::is_same<BigEnoughPromotion<int32_t, uint32_t>::type, int64_t>::value,
94 "");
95static_assert(
96 std::is_same<BigEnoughPromotion<intmax_t, int8_t>::type, intmax_t>::value,
97 "");
98static_assert(
99 std::is_same<BigEnoughPromotion<uintmax_t, int8_t>::type, uintmax_t>::value,
100 "");
101static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
102static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
103static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
104static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
105static_assert(
106 std::is_same<FastIntegerArithmeticPromotion<int16_t, int8_t>::type,
107 int32_t>::value,
108 "");
109static_assert(
110 std::is_same<FastIntegerArithmeticPromotion<int32_t, uint32_t>::type,
111 int64_t>::value,
112 "");
113static_assert(
114 std::is_same<FastIntegerArithmeticPromotion<intmax_t, int8_t>::type,
115 intmax_t>::value,
116 "");
117static_assert(
118 std::is_same<FastIntegerArithmeticPromotion<uintmax_t, int8_t>::type,
119 uintmax_t>::value,
120 "");
121static_assert(FastIntegerArithmeticPromotion<int16_t, int8_t>::is_contained,
122 "");
123static_assert(FastIntegerArithmeticPromotion<int32_t, uint32_t>::is_contained,
124 "");
125static_assert(!FastIntegerArithmeticPromotion<intmax_t, int8_t>::is_contained,
126 "");
127static_assert(!FastIntegerArithmeticPromotion<uintmax_t, int8_t>::is_contained,
128 "");
129
jschuhd1c1f2e2016-11-21 21:45:48130template <typename U>
131U GetNumericValueForTest(const CheckedNumeric<U>& src) {
132 return src.state_.value();
133}
134} // namespace internal.
135} // namespace base.
136
137using base::internal::GetNumericValueForTest;
138
jschuh224f1d72016-11-25 20:08:48139// Logs the ValueOrDie() failure instead of crashing.
140struct LogOnFailure {
141 template <typename T>
142 static T HandleFailure() {
143 LOG(WARNING) << "ValueOrDie() failed unexpectedly.";
144 return T();
145 }
146};
147
jschuh@chromium.org5bfecbc2014-02-27 13:49:04148// Helper macros to wrap displaying the conversion types and line numbers.
149#define TEST_EXPECTED_VALIDITY(expected, actual) \
jschuh4fcd6fa2016-11-24 11:58:39150 EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid()) \
jschuhd1c1f2e2016-11-21 21:45:48151 << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
152 << dst << " on line " << line
jschuh819c8262016-05-21 01:39:03153
154#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
155#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
jschuh@chromium.org5bfecbc2014-02-27 13:49:04156
jschuhba3c4f942016-12-10 14:03:55157// 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 " \
jschuhd1c1f2e2016-11-21 21:45:48166 << dst << " on line " << line
jschuh@chromium.org5bfecbc2014-02-27 13:49:04167
jschuh23a4b062016-12-02 02:55:08168// Test the simple pointer arithmetic overrides.
169template <typename Dst>
170void 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
jschuh@chromium.org5bfecbc2014-02-27 13:49:04185// Signed integer arithmetic.
186template <typename Dst>
187static void TestSpecializedArithmetic(
188 const char* dst,
189 int line,
vmpstr98a2fad2015-11-30 20:15:17190 typename std::enable_if<numeric_limits<Dst>::is_integer &&
191 numeric_limits<Dst>::is_signed,
192 int>::type = 0) {
jschuh5030b002016-12-05 18:21:48193 using DstLimits = numeric_limits<Dst>;
194 TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
195 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04196 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
jschuhba3c4f942016-12-10 14:03:55197 TEST_EXPECTED_VALUE(DstLimits::max(),
198 MakeCheckedNum(-DstLimits::max()).Abs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04199
jschuh819c8262016-05-21 01:39:03200 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
jschuh5030b002016-12-05 18:21:48201 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
202 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
203 DstLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04204
jschuh5030b002016-12-05 18:21:48205 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
206 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
jschuh819c8262016-05-21 01:39:03207 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48208 DstLimits::lowest());
209 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03210 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04211
jschuh5030b002016-12-05 18:21:48212 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04213
jschuh5030b002016-12-05 18:21:48214 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04215 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
jschuh5030b002016-12-05 18:21:48216 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
jschuh33232e02017-01-03 20:33:36217 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()));
jschuhba3c4f942016-12-10 14:03:55225 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());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04232
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);
jschuh819c8262016-05-21 01:39:03237 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
jschuh5030b002016-12-05 18:21:48238 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04239 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);
tsepezdfd77a92016-11-02 20:18:06246 // Test that div by 0 is avoided but returns invalid result.
247 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh3ab54042016-11-17 06:58:44248 // Test bit shifts.
249 volatile Dst negative_one = -1;
250 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48251 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
252 << (IntegerBitsPlusSign<Dst>::value - 1));
253 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
254 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44255 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48256 TEST_EXPECTED_VALUE(
257 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2),
258 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2));
jschuh3ab54042016-11-17 06:58:44259 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
jschuh5030b002016-12-05 18:21:48260 << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44261 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
262 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48263 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
264 IntegerBitsPlusSign<Dst>::value);
265 TEST_EXPECTED_VALUE(
266 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44267 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuh23a4b062016-12-02 02:55:08268
269 TestStrictPointerMath<Dst>();
jschuh@chromium.org5bfecbc2014-02-27 13:49:04270}
271
272// Unsigned integer arithmetic.
273template <typename Dst>
274static void TestSpecializedArithmetic(
275 const char* dst,
276 int line,
vmpstr98a2fad2015-11-30 20:15:17277 typename std::enable_if<numeric_limits<Dst>::is_integer &&
278 !numeric_limits<Dst>::is_signed,
279 int>::type = 0) {
jschuh5030b002016-12-05 18:21:48280 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);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04286 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
jschuh5030b002016-12-05 18:21:48287 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
jschuh819c8262016-05-21 01:39:03288 TEST_EXPECTED_SUCCESS(
jschuh5030b002016-12-05 18:21:48289 CheckedNumeric<typename std::make_signed<Dst>::type>(
290 std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
jschuheaf375f2015-09-17 01:04:28291 .UnsignedAbs());
jschuhba3c4f942016-12-10 14:03:55292 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());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04298
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);
jschuh5030b002016-12-05 18:21:48303 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04304 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);
tsepezdfd77a92016-11-02 20:18:06311 // Test that div by 0 is avoided but returns invalid result.
312 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
jschuh5030b002016-12-05 18:21:48313 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
314 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44315 // Test bit shifts.
316 volatile int negative_one = -1;
317 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
jschuh5030b002016-12-05 18:21:48318 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
319 << IntegerBitsPlusSign<Dst>::value);
320 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
321 << IntegerBitsPlusSign<Dst>::value);
jschuh3ab54042016-11-17 06:58:44322 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
jschuh5030b002016-12-05 18:21:48323 TEST_EXPECTED_VALUE(
324 static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1),
325 CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44326 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
327 TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
jschuh5030b002016-12-05 18:21:48328 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
329 IntegerBitsPlusSign<Dst>::value);
330 TEST_EXPECTED_VALUE(
331 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
jschuh3ab54042016-11-17 06:58:44332 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
jschuhb6737bb2016-11-29 03:06:59333 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(),
jschuh4bc919c2016-12-04 15:08:27338 MakeCheckedNum(DstLimits::max()) & -1);
jschuhb6737bb2016-11-29 03:06:59339 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));
jschuh970313c2016-11-24 21:40:58351 TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
jschuh23a4b062016-12-02 02:55:08352
353 TestStrictPointerMath<Dst>();
jschuh@chromium.org5bfecbc2014-02-27 13:49:04354}
355
356// Floating point arithmetic.
357template <typename Dst>
358void TestSpecializedArithmetic(
359 const char* dst,
360 int line,
vmpstr98a2fad2015-11-30 20:15:17361 typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
jschuh5030b002016-12-05 18:21:48362 using DstLimits = numeric_limits<Dst>;
363 TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
jschuh@chromium.org5bfecbc2014-02-27 13:49:04364
jschuh5030b002016-12-05 18:21:48365 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04366 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
367
jschuh5030b002016-12-05 18:21:48368 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
jschuh819c8262016-05-21 01:39:03369 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
jschuh5030b002016-12-05 18:21:48370 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
371 DstLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04372
jschuh819c8262016-05-21 01:39:03373 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
jschuh5030b002016-12-05 18:21:48374 DstLimits::lowest());
375 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
jschuh819c8262016-05-21 01:39:03376 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04377
jschuh5030b002016-12-05 18:21:48378 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04379
380 TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04381}
382
383// Generic arithmetic tests.
384template <typename Dst>
385static void TestArithmetic(const char* dst, int line) {
jschuh5030b002016-12-05 18:21:48386 using DstLimits = numeric_limits<Dst>;
jschuh@chromium.org5bfecbc2014-02-27 13:49:04387
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.
jschuh749c7f72016-09-07 16:22:26421 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 }
jschuh@chromium.org5bfecbc2014-02-27 13:49:04428
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));
jschuh216b62a2016-11-08 03:53:08438 if (numeric_limits<Dst>::is_signed)
439 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
jschuh5030b002016-12-05 18:21:48440 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + 1);
jschuh819c8262016-05-21 01:39:03441 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
442 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04443
444 // Generic subtraction.
jschuh@chromium.org5bfecbc2014-02-27 13:49:04445 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
jschuh819c8262016-05-21 01:39:03446 TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
jschuh216b62a2016-11-08 03:53:08447 if (numeric_limits<Dst>::is_signed) {
448 TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
449 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
jschuh657a3d62016-11-15 18:23:45450 } else {
451 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
jschuh216b62a2016-11-08 03:53:08452 }
jschuh@chromium.org5bfecbc2014-02-27 13:49:04453
454 // Generic multiplication.
455 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
456 TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
eroman0397125f2015-05-18 14:44:32457 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
jschuh216b62a2016-11-08 03:53:08458 if (numeric_limits<Dst>::is_signed) {
459 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
460 TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
jschuh749c7f72016-09-07 16:22:26461 TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
jschuh657a3d62016-11-15 18:23:45462 } else {
463 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * -2);
464 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
465 CheckedNumeric<uintmax_t>(-2));
jschuh749c7f72016-09-07 16:22:26466 }
jschuh216b62a2016-11-08 03:53:08467 TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
468 DstLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04469
470 // Generic division.
471 TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
472 TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
jschuh5030b002016-12-05 18:21:48473 TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
474 CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04475 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
484TEST(SafeNumerics, SignedIntegerMath) {
485 TEST_ARITHMETIC(int8_t);
486 TEST_ARITHMETIC(int);
487 TEST_ARITHMETIC(intptr_t);
488 TEST_ARITHMETIC(intmax_t);
489}
490
491TEST(SafeNumerics, UnsignedIntegerMath) {
492 TEST_ARITHMETIC(uint8_t);
493 TEST_ARITHMETIC(unsigned int);
494 TEST_ARITHMETIC(uintptr_t);
495 TEST_ARITHMETIC(uintmax_t);
496}
497
498TEST(SafeNumerics, FloatingPointMath) {
499 TEST_ARITHMETIC(float);
500 TEST_ARITHMETIC(double);
501}
scottmg@chromium.orgc1c090d32013-01-16 23:34:04502
jschuh@chromium.org4efb2c32014-01-16 06:57:25503// Enumerates the five different conversions types we need to test.
504enum 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};
scottmg@chromium.orgc1c090d32013-01-16 23:34:04511
jschuh@chromium.org4efb2c32014-01-16 06:57:25512// Template covering the different conversion tests.
513template <typename Dst, typename Src, NumericConversionType conversion>
514struct TestNumericConversion {};
scottmg@chromium.orgc1c090d32013-01-16 23:34:04515
jschuh082b2ba2017-01-06 11:40:54516enum 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.
524constexpr 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
jschuh@chromium.org5bfecbc2014-02-27 13:49:04530// EXPECT_EQ wrappers providing specific detail on test failures.
jschuh082b2ba2017-01-06 11:40:54531#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 \
jschuh657a3d62016-11-15 18:23:45536 << " on line " << line
jschuh@chromium.org4efb2c32014-01-16 06:57:25537
538template <typename Dst, typename Src>
jschuh23a4b062016-12-02 02:55:08539void TestStrictComparison() {
jschuh5030b002016-12-05 18:21:48540 using DstLimits = numeric_limits<Dst>;
541 using SrcLimits = numeric_limits<Src>;
jschuh711ac6a2016-12-04 07:17:48542 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()),
jschuh23a4b062016-12-02 02:55:08545 "");
jschuh711ac6a2016-12-04 07:17:48546 static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= SrcLimits::max()),
jschuh23a4b062016-12-02 02:55:08547 "");
jschuh711ac6a2016-12-04 07:17:48548 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= DstLimits::max(),
jschuh23a4b062016-12-02 02:55:08549 "");
jschuh711ac6a2016-12-04 07:17:48550 static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= SrcLimits::max(),
jschuh23a4b062016-12-02 02:55:08551 "");
jschuh711ac6a2016-12-04 07:17:48552 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 "");
jschuh23a4b062016-12-02 02:55:08570 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 "");
jschuh711ac6a2016-12-04 07:17:48576 static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(),
577 "");
jschuh23a4b062016-12-02 02:55:08578 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)), "");
jschuh711ac6a2016-12-04 07:17:48582
583 // Due to differences in float handling between compilers, these aren't
584 // compile-time constants everywhere. So, we use run-time tests.
jschuh4bc919c2016-12-04 15:08:27585 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),
jschuh711ac6a2016-12-04 07:17:48598 DstLimits::max(), SrcLimits::lowest())
599 .ValueOrDie());
jschuh4bc919c2016-12-04 15:08:27600 EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0),
jschuh711ac6a2016-12-04 07:17:48601 DstLimits::max(), SrcLimits::lowest())
602 .ValueOrDie());
jschuh23a4b062016-12-02 02:55:08603}
604
605template <typename Dst, typename Src>
jschuh@chromium.org4efb2c32014-01-16 06:57:25606struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
607 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48608 using SrcLimits = numeric_limits<Src>;
609 using DstLimits = numeric_limits<Dst>;
610 // Integral to floating.
jschuhd2d9fe02014-10-14 14:31:37611 static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
jschuh5030b002016-12-05 18:21:48612 // 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))),
jschuhd2d9fe02014-10-14 14:31:37620 "Comparison must be sign preserving and value preserving");
jschuh23a4b062016-12-02 02:55:08621
622 TestStrictComparison<Dst, Src>();
jschuh@chromium.org4efb2c32014-01-16 06:57:25623
jschuh@chromium.org5bfecbc2014-02-27 13:49:04624 const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
jschuh819c8262016-05-21 01:39:03625 TEST_EXPECTED_SUCCESS(checked_dst);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04626 if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
627 if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
628 // At least twice larger type.
jschuh819c8262016-05-21 01:39:03629 TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04630
631 } else { // Larger, but not at least twice as large.
jschuh819c8262016-05-21 01:39:03632 TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
633 TEST_EXPECTED_SUCCESS(checked_dst + 1);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04634 }
635 } else { // Same width type.
jschuh819c8262016-05-21 01:39:03636 TEST_EXPECTED_FAILURE(checked_dst + 1);
jschuh@chromium.org5bfecbc2014-02-27 13:49:04637 }
638
639 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
640 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuh@chromium.org4efb2c32014-01-16 06:57:25641 if (SrcLimits::is_iec559) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04642 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());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04646 } else if (numeric_limits<Src>::is_signed) {
647 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:48648 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
jschuh@chromium.org4efb2c32014-01-16 06:57:25649 }
scottmg@chromium.orgc1c090d32013-01-16 23:34:04650 }
jschuh@chromium.org4efb2c32014-01-16 06:57:25651};
652
653template <typename Dst, typename Src>
654struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
655 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48656 using SrcLimits = numeric_limits<Src>;
657 using DstLimits = numeric_limits<Dst>;
jschuhd2d9fe02014-10-14 14:31:37658 static_assert(SrcLimits::is_signed == DstLimits::is_signed,
659 "Destination and source sign must be the same");
jschuh5030b002016-12-05 18:21:48660 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37661 "Destination must be narrower than source");
jschuh23a4b062016-12-02 02:55:08662
663 TestStrictComparison<Dst, Src>();
jschuh@chromium.org4efb2c32014-01-16 06:57:25664
jschuh@chromium.org5bfecbc2014-02-27 13:49:04665 const CheckedNumeric<Dst> checked_dst;
jschuh819c8262016-05-21 01:39:03666 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04667 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:03668 TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04669
670 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
671 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuh@chromium.org4efb2c32014-01-16 06:57:25672 if (SrcLimits::is_iec559) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04673 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());
jschuhfafe0712015-09-14 20:21:24678 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>()));
jschuh5030b002016-12-05 18:21:48688 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:24689 }
jschuh@chromium.org4efb2c32014-01-16 06:57:25690 } else if (SrcLimits::is_signed) {
jschuh@chromium.org5bfecbc2014-02-27 13:49:04691 TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
jschuh5030b002016-12-05 18:21:48692 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04693 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
jschuh@chromium.org4efb2c32014-01-16 06:57:25694 } else {
jschuh819c8262016-05-21 01:39:03695 TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
jschuh5030b002016-12-05 18:21:48696 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
jschuh@chromium.org4efb2c32014-01-16 06:57:25697 }
698 }
699};
700
701template <typename Dst, typename Src>
702struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
703 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48704 using SrcLimits = numeric_limits<Src>;
705 using DstLimits = numeric_limits<Dst>;
706 static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37707 "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");
jschuh@chromium.org4efb2c32014-01-16 06:57:25710
jschuh23a4b062016-12-02 02:55:08711 TestStrictComparison<Dst, Src>();
712
jschuh@chromium.org5bfecbc2014-02-27 13:49:04713 const CheckedNumeric<Dst> checked_dst;
714 TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
jschuh819c8262016-05-21 01:39:03715 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:48716 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04717
jschuh5030b002016-12-05 18:21:48718 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04719 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));
jschuh@chromium.org4efb2c32014-01-16 06:57:25722 }
723};
724
725template <typename Dst, typename Src>
726struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
727 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48728 using SrcLimits = numeric_limits<Src>;
729 using DstLimits = numeric_limits<Dst>;
730 static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37731 "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.");
jschuh23a4b062016-12-02 02:55:08734
735 TestStrictComparison<Dst, Src>();
jschuh@chromium.org4efb2c32014-01-16 06:57:25736
jschuh@chromium.org5bfecbc2014-02-27 13:49:04737 const CheckedNumeric<Dst> checked_dst;
738 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:03739 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
740 TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
jschuh5030b002016-12-05 18:21:48741 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04742
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));
jschuhe3bd1f62016-12-20 05:11:30746
747 // Additional saturation tests.
jschuhc8f03cd2017-01-05 03:40:51748 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max())) << src;
jschuhe3bd1f62016-12-20 05:11:30749 EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
750
jschuh@chromium.org4efb2c32014-01-16 06:57:25751 if (SrcLimits::is_iec559) {
jschuhe3bd1f62016-12-20 05:11:30752 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
753
jschuh@chromium.org5bfecbc2014-02-27 13:49:04754 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());
jschuhfafe0712015-09-14 20:21:24758 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>()));
jschuh5030b002016-12-05 18:21:48768 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
jschuhfafe0712015-09-14 20:21:24769 }
jschuh@chromium.org4efb2c32014-01-16 06:57:25770 } else {
jschuh5030b002016-12-05 18:21:48771 TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
jschuh@chromium.org4efb2c32014-01-16 06:57:25772 }
773 }
774};
775
776template <typename Dst, typename Src>
777struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
778 static void Test(const char *dst, const char *src, int line) {
jschuh5030b002016-12-05 18:21:48779 using SrcLimits = numeric_limits<Src>;
780 using DstLimits = numeric_limits<Dst>;
781 static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
jschuhd2d9fe02014-10-14 14:31:37782 "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.");
jschuh23a4b062016-12-02 02:55:08785
786 TestStrictComparison<Dst, Src>();
jschuh@chromium.org4efb2c32014-01-16 06:57:25787
jschuh@chromium.org5bfecbc2014-02-27 13:49:04788 const CheckedNumeric<Dst> checked_dst;
789 TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
jschuh819c8262016-05-21 01:39:03790 TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
jschuh5030b002016-12-05 18:21:48791 TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04792
jschuh5030b002016-12-05 18:21:48793 TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
jschuh@chromium.org5bfecbc2014-02-27 13:49:04794 TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
795 TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
jschuhe3bd1f62016-12-20 05:11:30796
797 // Additional saturation tests.
798 EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
799 EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
jschuh@chromium.org4efb2c32014-01-16 06:57:25800 }
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
jschuh@chromium.org5bfecbc2014-02-27 13:49:04807TEST(SafeNumerics, IntMinOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25808 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);
scottmg@chromium.orgc1c090d32013-01-16 23:34:04823}
824
jschuh@chromium.org5bfecbc2014-02-27 13:49:04825TEST(SafeNumerics, IntOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25826 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);
scottmg@chromium.orgc1c090d32013-01-16 23:34:04848}
849
jschuh@chromium.org5bfecbc2014-02-27 13:49:04850TEST(SafeNumerics, IntMaxOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25851 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
jschuh@chromium.org5bfecbc2014-02-27 13:49:04873TEST(SafeNumerics, FloatOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25874 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
jschuh@chromium.org5bfecbc2014-02-27 13:49:04884TEST(SafeNumerics, DoubleOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25885 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
jschuh@chromium.org5bfecbc2014-02-27 13:49:04893TEST(SafeNumerics, SizeTOperations) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25894 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
jschuh23a4b062016-12-02 02:55:08898// 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.
900int TestOverload(int) { // Overload fails.
901 return 0;
902}
903uint8_t TestOverload(uint8_t) { // Overload fails.
904 return 0;
905}
906size_t TestOverload(size_t) { // Overload succeeds.
907 return 0;
908}
909
910static_assert(
911 std::is_same<decltype(TestOverload(StrictNumeric<int>())), int>::value,
912 "");
913static_assert(std::is_same<decltype(TestOverload(StrictNumeric<size_t>())),
914 size_t>::value,
915 "");
916
jschuh71b669a2016-12-17 01:13:31917template <typename T>
918struct CastTest1 {
jschuhc8f03cd2017-01-05 03:40:51919 static constexpr T NaN() { return -1; }
jschuh71b669a2016-12-17 01:13:31920 static constexpr T max() { return numeric_limits<T>::max() - 1; }
jschuhc8f03cd2017-01-05 03:40:51921 static constexpr T Overflow() { return max(); }
jschuh71b669a2016-12-17 01:13:31922 static constexpr T lowest() { return numeric_limits<T>::lowest() + 1; }
jschuhc8f03cd2017-01-05 03:40:51923 static constexpr T Underflow() { return lowest(); }
jschuh71b669a2016-12-17 01:13:31924};
925
926template <typename T>
927struct CastTest2 {
jschuhc8f03cd2017-01-05 03:40:51928 static constexpr T NaN() { return 11; }
jschuh71b669a2016-12-17 01:13:31929 static constexpr T max() { return 10; }
jschuhc8f03cd2017-01-05 03:40:51930 static constexpr T Overflow() { return max(); }
jschuh71b669a2016-12-17 01:13:31931 static constexpr T lowest() { return 1; }
jschuhc8f03cd2017-01-05 03:40:51932 static constexpr T Underflow() { return lowest(); }
jschuh71b669a2016-12-17 01:13:31933};
934
agrieve7772a0502016-12-16 18:18:48935TEST(SafeNumerics, CastTests) {
jschuh@chromium.org4efb2c32014-01-16 06:57:25936// 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)
scottmg@chromium.orgc1c090d32013-01-16 23:34:04940#endif
941
scottmg@chromium.orgc1c090d32013-01-16 23:34:04942 int small_positive = 1;
943 int small_negative = -1;
jschuh@chromium.org4efb2c32014-01-16 06:57:25944 double double_small = 1.0;
jschuh@chromium.org5bfecbc2014-02-27 13:49:04945 double double_large = numeric_limits<double>::max();
946 double double_infinity = numeric_limits<float>::infinity();
danakj3193742f2015-06-05 18:15:10947 double double_large_int = numeric_limits<int>::max();
jschuh5030b002016-12-05 18:21:48948 double double_small_int = numeric_limits<int>::lowest();
scottmg@chromium.orgc1c090d32013-01-16 23:34:04949
jschuh4bf22c6d2015-05-28 02:29:25950 // Just test that the casts compile, since the other tests cover logic.
jschuh@chromium.org5bfecbc2014-02-27 13:49:04951 EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
jschuh4bf22c6d2015-05-28 02:29:25952 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
jschuh07345e62015-09-22 22:13:36963 EXPECT_TRUE(IsValueNegative(-1));
jschuh5030b002016-12-05 18:21:48964 EXPECT_TRUE(IsValueNegative(numeric_limits<int>::lowest()));
965 EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::lowest()));
966 EXPECT_TRUE(IsValueNegative(numeric_limits<double>::lowest()));
jschuh07345e62015-09-22 22:13:36967 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
jschuh4bf22c6d2015-05-28 02:29:25975 // 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));
scottmg@chromium.orgc1c090d32013-01-16 23:34:04980
jschuh@chromium.org4efb2c32014-01-16 06:57:25981 // 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));
jschuh@chromium.org5bfecbc2014-02-27 13:49:04990 EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
jschuh@chromium.org4efb2c32014-01-16 06:57:25991 EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
992 EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
jschuh5030b002016-12-05 18:21:48993 EXPECT_EQ(numeric_limits<int>::lowest(),
994 saturated_cast<int>(double_small_int));
danakj3193742f2015-06-05 18:15:10995 EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
vmpstredf1e182015-12-14 20:09:42996
jschuh71b669a2016-12-17 01:13:31997 // 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
vmpstredf1e182015-12-14 20:09:421026 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));
jschuh224f1d72016-11-25 20:08:481030
1031 // Test the CheckedNumeric value extractions functions.
jschuh5030b002016-12-05 18:21:481032 auto int8_min = MakeCheckedNum(numeric_limits<int8_t>::lowest());
jschuh4bc919c2016-12-04 15:08:271033 auto int8_max = MakeCheckedNum(numeric_limits<int8_t>::max());
1034 auto double_max = MakeCheckedNum(numeric_limits<double>::max());
jschuh224f1d72016-11-25 20:08:481035 static_assert(
jschuh23a4b062016-12-02 02:55:081036 std::is_same<int16_t,
1037 decltype(int8_min.ValueOrDie<int16_t>())::type>::value,
jschuh224f1d72016-11-25 20:08:481038 "ValueOrDie returning incorrect type.");
1039 static_assert(
1040 std::is_same<int16_t,
jschuh23a4b062016-12-02 02:55:081041 decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value,
jschuh224f1d72016-11-25 20:08:481042 "ValueOrDefault returning incorrect type.");
jschuh23a4b062016-12-02 02:55:081043 EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
1044 EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
jschuh5030b002016-12-05 18:21:481045 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::lowest()),
jschuh23a4b062016-12-02 02:55:081046 ValueOrDieForType<int>(int8_min));
1047 EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
jschuh224f1d72016-11-25 20:08:481048 EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
jschuh23a4b062016-12-02 02:55:081049 ValueOrDieForType<int>(int8_max));
1050 EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
jschuhe17e0f12016-11-26 03:00:081051 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));
jschuh5030b002016-12-05 18:21:481060 EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::lowest()), int16_dest);
jschuhe17e0f12016-11-26 03:00:081061 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);
jschuh23a4b062016-12-02 02:55:081065 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)));
agrieve7772a0502016-12-16 18:18:481068}
1069
jschuhfafe0712015-09-14 20:21:241070TEST(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>(
jschuh5030b002016-12-05 18:21:481080 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241081 EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
jschuh5030b002016-12-05 18:21:481082 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241083
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>(
jschuh5030b002016-12-05 18:21:481096 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241097 EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481098 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241099 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481100 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest()) - 1));
jschuhfafe0712015-09-14 20:21:241101 EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
jschuh5030b002016-12-05 18:21:481102 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241103
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>(
jschuh5030b002016-12-05 18:21:481113 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241114 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
1115 EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
jschuh5030b002016-12-05 18:21:481116 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241117
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>(
jschuh5030b002016-12-05 18:21:481138 std::numeric_limits<int32_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241139 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481140 static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
jschuhfafe0712015-09-14 20:21:241141 EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
jschuh5030b002016-12-05 18:21:481142 std::numeric_limits<int64_t>::lowest()));
jschuhfafe0712015-09-14 20:21:241143}
vmpstr19477492015-09-29 22:34:491144
1145TEST(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}
jschuh4fcd6fa2016-11-24 11:58:391168
1169TEST(SafeNumerics, VariadicNumericOperations) {
jschuh4bc919c2016-12-04 15:08:271170 auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081171 EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
jschuh4bc919c2016-12-04 15:08:271172 auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081173 EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
jschuh4bc919c2016-12-04 15:08:271174 auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081175 EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
jschuh4bc919c2016-12-04 15:08:271176 auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081177 EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
jschuh4bc919c2016-12-04 15:08:271178 auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081179 EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
jschuh4bc919c2016-12-04 15:08:271180 auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081181 EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
jschuh4bc919c2016-12-04 15:08:271182 auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081183 EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
jschuh4fcd6fa2016-11-24 11:58:391184 auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
jschuh23a4b062016-12-02 02:55:081185 EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
jschuh4fcd6fa2016-11-24 11:58:391186}