15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <mmintrin.h>
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stdint.h>
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <limits>
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/compiler_specific.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/numerics/safe_conversions.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/numerics/safe_math.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/template_util.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using std::numeric_limits;
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::CheckedNumeric;
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::checked_cast;
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::saturated_cast;
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::internal::MaxExponent;
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::internal::RANGE_VALID;
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::internal::RANGE_INVALID;
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::internal::RANGE_OVERFLOW;
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::internal::RANGE_UNDERFLOW;
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::enable_if;
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// MSVS 2013 ia32 may not reset the FPU between calculations, and the test
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// framework masks the exceptions. So we just force a manual reset after NaN.
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)inline void ResetFloatingPointUnit() {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  _mm_empty();
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// These tests deliberately cause arithmetic overflows. If the compiler is
386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// aggressive enough, it can const fold these overflows. Disable warnings about
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// overflows for const expressions.
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if defined(OS_WIN)
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#pragma warning(disable:4756)
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Helper macros to wrap displaying the conversion types and line numbers.
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define TEST_EXPECTED_VALIDITY(expected, actual)                           \
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).validity())              \
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst \
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      << " on line " << line;
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define TEST_EXPECTED_VALUE(expected, actual)                                \
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(static_cast<Dst>(expected),                                      \
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            CheckedNumeric<Dst>(actual).ValueUnsafe())                       \
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst \
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      << " on line " << line;
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Signed integer arithmetic.
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename Dst>
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void TestSpecializedArithmetic(
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const char* dst,
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int line,
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typename enable_if<
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        numeric_limits<Dst>::is_integer&& numeric_limits<Dst>::is_signed,
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        int>::type = 0) {
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef numeric_limits<Dst> DstLimits;
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         -CheckedNumeric<Dst>(DstLimits::min()));
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()).Abs());
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID,
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::max()) + -1);
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) + -1);
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      RANGE_UNDERFLOW,
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) - 1);
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID,
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) - -1);
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      RANGE_OVERFLOW,
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      RANGE_UNDERFLOW,
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) * 2);
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW,
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) / -1);
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Modulus is legal only for integers.
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_INVALID, CheckedNumeric<Dst>(-1) % -2);
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Test all the different modulus combinations.
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CheckedNumeric<Dst> checked_dst = 1;
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, checked_dst %= 1);
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Unsigned integer arithmetic.
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename Dst>
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void TestSpecializedArithmetic(
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const char* dst,
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int line,
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typename enable_if<
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed,
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        int>::type = 0) {
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef numeric_limits<Dst> DstLimits;
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min()));
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID,
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()).Abs());
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) + -1);
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW,
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) - 1);
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2);
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Modulus is legal only for integers.
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Test all the different modulus combinations.
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CheckedNumeric<Dst> checked_dst = 1;
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, checked_dst %= 1);
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Floating point arithmetic.
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename Dst>
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TestSpecializedArithmetic(
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const char* dst,
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int line,
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typename enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef numeric_limits<Dst> DstLimits;
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID, -CheckedNumeric<Dst>(DstLimits::min()));
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID,
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()).Abs());
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID,
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) + -1);
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID,
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::max()) + 1);
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      RANGE_UNDERFLOW,
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      RANGE_OVERFLOW,
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      RANGE_UNDERFLOW,
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID,
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) * 2);
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Generic arithmetic tests.
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename Dst>
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void TestArithmetic(const char* dst, int line) {
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef numeric_limits<Dst> DstLimits;
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(false,
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                DstLimits::max()).IsValid());
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(static_cast<Dst>(1),
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                DstLimits::max()).ValueOrDefault(1));
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Test the operator combinations.
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CheckedNumeric<Dst> checked_dst = 1;
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(2, checked_dst += 1);
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  checked_dst = 1;
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, checked_dst -= 1);
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  checked_dst = 1;
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, checked_dst *= 1);
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  checked_dst = 1;
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, checked_dst /= 1);
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Generic negation.
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      -CheckedNumeric<Dst>(DstLimits::max()));
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Generic absolute value.
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(DstLimits::max(),
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      CheckedNumeric<Dst>(DstLimits::max()).Abs());
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Generic addition.
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID,
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::min()) + 1);
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Generic subtraction.
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(RANGE_VALID,
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         CheckedNumeric<Dst>(DstLimits::max()) - 1);
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Generic multiplication.
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALIDITY(
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      RANGE_OVERFLOW, CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Generic division.
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(DstLimits::min() / 2,
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      CheckedNumeric<Dst>(DstLimits::min()) / 2);
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_EXPECTED_VALUE(DstLimits::max() / 2,
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      CheckedNumeric<Dst>(DstLimits::max()) / 2);
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TestSpecializedArithmetic<Dst>(dst, line);
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Helper macro to wrap displaying the conversion types and line numbers.
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(SafeNumerics, SignedIntegerMath) {
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(int8_t);
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(int);
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(intptr_t);
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(intmax_t);
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(SafeNumerics, UnsignedIntegerMath) {
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(uint8_t);
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(unsigned int);
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(uintptr_t);
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(uintmax_t);
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(SafeNumerics, FloatingPointMath) {
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(float);
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TEST_ARITHMETIC(double);
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Enumerates the five different conversions types we need to test.
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)enum NumericConversionType {
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SIGN_PRESERVING_VALUE_PRESERVING,
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SIGN_PRESERVING_NARROW,
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SIGN_TO_UNSIGN_NARROW,
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Template covering the different conversion tests.
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src, NumericConversionType conversion>
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct TestNumericConversion {};
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// EXPECT_EQ wrappers providing specific detail on test failures.
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define TEST_EXPECTED_RANGE(expected, actual)                                  \
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      << "Conversion test: " << src << " value " << actual << " to " << dst    \
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      << " on line " << line;
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src>
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void Test(const char *dst, const char *src, int line) {
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Src> SrcLimits;
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Dst> DstLimits;
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   // Integral to floating.
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT((DstLimits::is_iec559 && SrcLimits::is_integer) ||
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   // Not floating to integral and...
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    // Same sign, same numeric, source is narrower or same.
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    ((SrcLimits::is_signed == DstLimits::is_signed &&
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     sizeof(Dst) >= sizeof(Src)) ||
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    // Or signed destination and source is smaller
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   comparison_must_be_sign_preserving_and_value_preserving);
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ;
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst);
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // At least twice larger type.
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        TEST_EXPECTED_VALIDITY(RANGE_VALID, SrcLimits::max() * checked_dst);
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      } else {  // Larger, but not at least twice as large.
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, SrcLimits::max() * checked_dst);
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        TEST_EXPECTED_VALIDITY(RANGE_VALID, checked_dst + 1);
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else {  // Same width type.
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + 1);
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (SrcLimits::is_iec559) {
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ResetFloatingPointUnit();
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else if (numeric_limits<Src>::is_signed) {
346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src>
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void Test(const char *dst, const char *src, int line) {
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Src> SrcLimits;
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Dst> DstLimits;
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(SrcLimits::is_signed == DstLimits::is_signed,
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   destination_and_source_sign_must_be_the_same);
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(sizeof(Dst) < sizeof(Src) ||
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   (DstLimits::is_integer && SrcLimits::is_iec559),
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   destination_must_be_narrower_than_source);
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const CheckedNumeric<Dst> checked_dst;
364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst - SrcLimits::max());
367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (SrcLimits::is_iec559) {
371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ResetFloatingPointUnit();
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (SrcLimits::is_signed) {
378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_VALIDITY(RANGE_INVALID, checked_dst - static_cast<Src>(1));
383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src>
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void Test(const char *dst, const char *src, int line) {
391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Src> SrcLimits;
392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Dst> DstLimits;
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(sizeof(Dst) >= sizeof(Src),
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   destination_must_be_equal_or_wider_than_source);
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(SrcLimits::is_signed, source_must_be_signed);
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(!DstLimits::is_signed, destination_must_be_unsigned);
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const CheckedNumeric<Dst> checked_dst;
399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1));
401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max());
402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src>
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void Test(const char *dst, const char *src, int line) {
413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Src> SrcLimits;
414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Dst> DstLimits;
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT((DstLimits::is_integer && SrcLimits::is_iec559) ||
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   (sizeof(Dst) < sizeof(Src)),
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      destination_must_be_narrower_than_source);
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(SrcLimits::is_signed, source_must_be_signed);
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(!DstLimits::is_signed, destination_must_be_unsigned);
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const CheckedNumeric<Dst> checked_dst;
422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + static_cast<Src>(-1));
425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALIDITY(RANGE_UNDERFLOW, checked_dst + -SrcLimits::max());
426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (SrcLimits::is_iec559) {
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ResetFloatingPointUnit();
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <typename Dst, typename Src>
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static void Test(const char *dst, const char *src, int line) {
445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Src> SrcLimits;
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    typedef numeric_limits<Dst> DstLimits;
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(sizeof(Dst) <= sizeof(Src),
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   destination_must_be_narrower_or_equal_to_source);
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(!SrcLimits::is_signed, source_must_be_unsigned);
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    COMPILE_ASSERT(DstLimits::is_signed, destination_must_be_signed);
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const CheckedNumeric<Dst> checked_dst;
453a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALIDITY(RANGE_OVERFLOW, checked_dst + SrcLimits::max());
455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Helper macro to wrap displaying the conversion types and line numbers
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define TEST_NUMERIC_CONVERSION(d, s, t) \
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(SafeNumerics, IntMinOperations) {
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(SafeNumerics, IntOperations) {
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          SIGN_PRESERVING_VALUE_PRESERVING);
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          SIGN_PRESERVING_VALUE_PRESERVING);
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(SafeNumerics, IntMaxOperations) {
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          SIGN_PRESERVING_VALUE_PRESERVING);
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          SIGN_PRESERVING_VALUE_PRESERVING);
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          SIGN_PRESERVING_VALUE_PRESERVING);
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(SafeNumerics, FloatOperations) {
5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(float, uintmax_t,
5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          SIGN_PRESERVING_VALUE_PRESERVING);
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(float, unsigned int,
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          SIGN_PRESERVING_VALUE_PRESERVING);
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
544a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(SafeNumerics, DoubleOperations) {
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(double, uintmax_t,
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          SIGN_PRESERVING_VALUE_PRESERVING);
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(double, unsigned int,
5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          SIGN_PRESERVING_VALUE_PRESERVING);
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(SafeNumerics, SizeTOperations) {
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(SafeNumerics, CastTests) {
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// MSVC catches and warns that we're forcing saturation in these tests.
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Since that's intentional, we need to shut this warning off.
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(COMPILER_MSVC)
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#pragma warning(disable : 4756)
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int small_positive = 1;
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int small_negative = -1;
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  double double_small = 1.0;
568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  double double_large = numeric_limits<double>::max();
569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  double double_infinity = numeric_limits<float>::infinity();
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Just test that the cast compiles, since the other tests cover logic.
572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Test various saturation corner cases.
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(saturated_cast<int>(small_negative),
5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            static_cast<int>(small_negative));
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(saturated_cast<int>(small_positive),
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            static_cast<int>(small_positive));
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(saturated_cast<unsigned>(small_negative),
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            static_cast<unsigned>(0));
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(saturated_cast<int>(double_small),
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            static_cast<int>(double_small));
583a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
588