Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/CheckedInt.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/* Provides checked integers, detecting integer overflow and divide-by-0. */
8
9
#ifndef mozilla_CheckedInt_h
10
#define mozilla_CheckedInt_h
11
12
#include <stdint.h>
13
#include "mozilla/Assertions.h"
14
#include "mozilla/Attributes.h"
15
#include "mozilla/IntegerTypeTraits.h"
16
17
// Probe for builtin math overflow support.  Disabled for 32-bit builds for now
18
// since "gcc -m32" claims to support these but its implementation is buggy.
19
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82274
20
#if defined(HAVE_64BIT_BUILD)
21
#if defined(__has_builtin)
22
#define MOZ_HAS_BUILTIN_OP_OVERFLOW (__has_builtin(__builtin_add_overflow))
23
#elif defined(__GNUC__)
24
// (clang also defines __GNUC__ but it supports __has_builtin since at least
25
//  v3.1 (released in 2012) so it won't get here.)
26
#define MOZ_HAS_BUILTIN_OP_OVERFLOW (__GNUC__ >= 5)
27
#else
28
#define MOZ_HAS_BUILTIN_OP_OVERFLOW (0)
29
#endif
30
#else
31
#define MOZ_HAS_BUILTIN_OP_OVERFLOW (0)
32
#endif
33
34
namespace mozilla {
35
36
template<typename T> class CheckedInt;
37
38
namespace detail {
39
40
/*
41
 * Step 1: manually record supported types
42
 *
43
 * What's nontrivial here is that there are different families of integer
44
 * types: basic integer types and stdint types. It is merrily undefined which
45
 * types from one family may be just typedefs for a type from another family.
46
 *
47
 * For example, on GCC 4.6, aside from the basic integer types, the only other
48
 * type that isn't just a typedef for some of them, is int8_t.
49
 */
50
51
struct UnsupportedType {};
52
53
template<typename IntegerType>
54
struct IsSupportedPass2
55
{
56
  static const bool value = false;
57
};
58
59
template<typename IntegerType>
60
struct IsSupported
61
{
62
  static const bool value = IsSupportedPass2<IntegerType>::value;
63
};
64
65
template<>
66
struct IsSupported<int8_t>
67
{ static const bool value = true; };
68
69
template<>
70
struct IsSupported<uint8_t>
71
{ static const bool value = true; };
72
73
template<>
74
struct IsSupported<int16_t>
75
{ static const bool value = true; };
76
77
template<>
78
struct IsSupported<uint16_t>
79
{ static const bool value = true; };
80
81
template<>
82
struct IsSupported<int32_t>
83
{ static const bool value = true; };
84
85
template<>
86
struct IsSupported<uint32_t>
87
{ static const bool value = true; };
88
89
template<>
90
struct IsSupported<int64_t>
91
{ static const bool value = true; };
92
93
template<>
94
struct IsSupported<uint64_t>
95
{ static const bool value = true; };
96
97
98
template<>
99
struct IsSupportedPass2<char>
100
{ static const bool value = true; };
101
102
template<>
103
struct IsSupportedPass2<signed char>
104
{ static const bool value = true; };
105
106
template<>
107
struct IsSupportedPass2<unsigned char>
108
{ static const bool value = true; };
109
110
template<>
111
struct IsSupportedPass2<short>
112
{ static const bool value = true; };
113
114
template<>
115
struct IsSupportedPass2<unsigned short>
116
{ static const bool value = true; };
117
118
template<>
119
struct IsSupportedPass2<int>
120
{ static const bool value = true; };
121
122
template<>
123
struct IsSupportedPass2<unsigned int>
124
{ static const bool value = true; };
125
126
template<>
127
struct IsSupportedPass2<long>
128
{ static const bool value = true; };
129
130
template<>
131
struct IsSupportedPass2<unsigned long>
132
{ static const bool value = true; };
133
134
template<>
135
struct IsSupportedPass2<long long>
136
{ static const bool value = true; };
137
138
template<>
139
struct IsSupportedPass2<unsigned long long>
140
{ static const bool value = true; };
141
142
/*
143
 * Step 2: Implement the actual validity checks.
144
 *
145
 * Ideas taken from IntegerLib, code different.
146
 */
147
148
template<typename IntegerType, size_t Size = sizeof(IntegerType)>
149
struct TwiceBiggerType
150
{
151
  typedef typename detail::StdintTypeForSizeAndSignedness<
152
                     sizeof(IntegerType) * 2,
153
                     IsSigned<IntegerType>::value
154
                   >::Type Type;
155
};
156
157
template<typename IntegerType>
158
struct TwiceBiggerType<IntegerType, 8>
159
{
160
  typedef UnsupportedType Type;
161
};
162
163
template<typename T>
164
inline bool
165
HasSignBit(T aX)
166
{
167
  // In C++, right bit shifts on negative values is undefined by the standard.
168
  // Notice that signed-to-unsigned conversions are always well-defined in the
169
  // standard, as the value congruent modulo 2**n as expected. By contrast,
170
  // unsigned-to-signed is only well-defined if the value is representable.
171
  return bool(typename MakeUnsigned<T>::Type(aX) >>
172
              PositionOfSignBit<T>::value);
173
}
174
175
// Bitwise ops may return a larger type, so it's good to use this inline
176
// helper guaranteeing that the result is really of type T.
177
template<typename T>
178
inline T
179
BinaryComplement(T aX)
180
{
181
  return ~aX;
182
}
183
184
template<typename T,
185
         typename U,
186
         bool IsTSigned = IsSigned<T>::value,
187
         bool IsUSigned = IsSigned<U>::value>
188
struct DoesRangeContainRange
189
{
190
};
191
192
template<typename T, typename U, bool Signedness>
193
struct DoesRangeContainRange<T, U, Signedness, Signedness>
194
{
195
  static const bool value = sizeof(T) >= sizeof(U);
196
};
197
198
template<typename T, typename U>
199
struct DoesRangeContainRange<T, U, true, false>
200
{
201
  static const bool value = sizeof(T) > sizeof(U);
202
};
203
204
template<typename T, typename U>
205
struct DoesRangeContainRange<T, U, false, true>
206
{
207
  static const bool value = false;
208
};
209
210
template<typename T,
211
         typename U,
212
         bool IsTSigned = IsSigned<T>::value,
213
         bool IsUSigned = IsSigned<U>::value,
214
         bool DoesTRangeContainURange = DoesRangeContainRange<T, U>::value>
215
struct IsInRangeImpl {};
216
217
template<typename T, typename U, bool IsTSigned, bool IsUSigned>
218
struct IsInRangeImpl<T, U, IsTSigned, IsUSigned, true>
219
{
220
  static bool constexpr run(U)
221
16.2M
  {
222
16.2M
    return true;
223
16.2M
  }
mozilla::detail::IsInRangeImpl<unsigned long, unsigned long, false, false, true>::run(unsigned long)
Line
Count
Source
221
60.8k
  {
222
60.8k
    return true;
223
60.8k
  }
mozilla::detail::IsInRangeImpl<long, long, true, true, true>::run(long)
Line
Count
Source
221
196
  {
222
196
    return true;
223
196
  }
mozilla::detail::IsInRangeImpl<long, int, true, true, true>::run(int)
Line
Count
Source
221
12
  {
222
12
    return true;
223
12
  }
mozilla::detail::IsInRangeImpl<int, int, true, true, true>::run(int)
Line
Count
Source
221
147k
  {
222
147k
    return true;
223
147k
  }
mozilla::detail::IsInRangeImpl<unsigned int, unsigned int, false, false, true>::run(unsigned int)
Line
Count
Source
221
16.0M
  {
222
16.0M
    return true;
223
16.0M
  }
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned long, unsigned int, false, false, true>::run(unsigned int)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<long, unsigned int, true, false, true>::run(unsigned int)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned int, unsigned short, false, false, true>::run(unsigned short)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned int, unsigned char, false, false, true>::run(unsigned char)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned long, unsigned char, false, false, true>::run(unsigned char)
224
};
225
226
template<typename T, typename U>
227
struct IsInRangeImpl<T, U, true, true, false>
228
{
229
  static bool constexpr run(U aX)
230
0
  {
231
0
    return aX <= MaxValue<T>::value && aX >= MinValue<T>::value;
232
0
  }
233
};
234
235
template<typename T, typename U>
236
struct IsInRangeImpl<T, U, false, false, false>
237
{
238
  static bool constexpr run(U aX)
239
2.03M
  {
240
2.03M
    return aX <= MaxValue<T>::value;
241
2.03M
  }
mozilla::detail::IsInRangeImpl<unsigned int, unsigned long, false, false, false>::run(unsigned long)
Line
Count
Source
239
2.03M
  {
240
2.03M
    return aX <= MaxValue<T>::value;
241
2.03M
  }
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned short, unsigned long, false, false, false>::run(unsigned long)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned char, unsigned int, false, false, false>::run(unsigned int)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned short, unsigned int, false, false, false>::run(unsigned int)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned char, unsigned long, false, false, false>::run(unsigned long)
242
};
243
244
template<typename T, typename U>
245
struct IsInRangeImpl<T, U, true, false, false>
246
{
247
  static bool constexpr run(U aX)
248
147k
  {
249
147k
    return sizeof(T) > sizeof(U) || aX <= U(MaxValue<T>::value);
250
147k
  }
mozilla::detail::IsInRangeImpl<int, unsigned long, true, false, false>::run(unsigned long)
Line
Count
Source
248
2
  {
249
2
    return sizeof(T) > sizeof(U) || aX <= U(MaxValue<T>::value);
250
2
  }
mozilla::detail::IsInRangeImpl<int, unsigned int, true, false, false>::run(unsigned int)
Line
Count
Source
248
147k
  {
249
147k
    return sizeof(T) > sizeof(U) || aX <= U(MaxValue<T>::value);
250
147k
  }
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<long, unsigned long, true, false, false>::run(unsigned long)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<signed char, unsigned long, true, false, false>::run(unsigned long)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<short, unsigned long, true, false, false>::run(unsigned long)
251
};
252
253
template<typename T, typename U>
254
struct IsInRangeImpl<T, U, false, true, false>
255
{
256
  static bool constexpr run(U aX)
257
12.4M
  {
258
12.4M
    return sizeof(T) >= sizeof(U)
259
12.4M
           ? aX >= 0
260
12.4M
           : aX >= 0 && aX <= U(MaxValue<T>::value);
261
12.4M
  }
mozilla::detail::IsInRangeImpl<unsigned int, int, false, true, false>::run(int)
Line
Count
Source
257
4.26M
  {
258
4.26M
    return sizeof(T) >= sizeof(U)
259
4.26M
           ? aX >= 0
260
4.26M
           : aX >= 0 && aX <= U(MaxValue<T>::value);
261
4.26M
  }
mozilla::detail::IsInRangeImpl<unsigned long, int, false, true, false>::run(int)
Line
Count
Source
257
8.19M
  {
258
8.19M
    return sizeof(T) >= sizeof(U)
259
8.19M
           ? aX >= 0
260
8.19M
           : aX >= 0 && aX <= U(MaxValue<T>::value);
261
8.19M
  }
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned int, long, false, true, false>::run(long)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned long, long, false, true, false>::run(long)
Unexecuted instantiation: mozilla::detail::IsInRangeImpl<unsigned short, int, false, true, false>::run(int)
262
};
263
264
template<typename T, typename U>
265
inline constexpr bool
266
IsInRange(U aX)
267
30.9M
{
268
30.9M
  return IsInRangeImpl<T, U>::run(aX);
269
30.9M
}
bool mozilla::detail::IsInRange<unsigned long, unsigned long>(unsigned long)
Line
Count
Source
267
60.8k
{
268
60.8k
  return IsInRangeImpl<T, U>::run(aX);
269
60.8k
}
bool mozilla::detail::IsInRange<long, long>(long)
Line
Count
Source
267
196
{
268
196
  return IsInRangeImpl<T, U>::run(aX);
269
196
}
bool mozilla::detail::IsInRange<long, int>(int)
Line
Count
Source
267
12
{
268
12
  return IsInRangeImpl<T, U>::run(aX);
269
12
}
bool mozilla::detail::IsInRange<int, unsigned long>(unsigned long)
Line
Count
Source
267
2
{
268
2
  return IsInRangeImpl<T, U>::run(aX);
269
2
}
bool mozilla::detail::IsInRange<int, int>(int)
Line
Count
Source
267
147k
{
268
147k
  return IsInRangeImpl<T, U>::run(aX);
269
147k
}
bool mozilla::detail::IsInRange<unsigned int, unsigned int>(unsigned int)
Line
Count
Source
267
16.0M
{
268
16.0M
  return IsInRangeImpl<T, U>::run(aX);
269
16.0M
}
bool mozilla::detail::IsInRange<int, unsigned int>(unsigned int)
Line
Count
Source
267
147k
{
268
147k
  return IsInRangeImpl<T, U>::run(aX);
269
147k
}
bool mozilla::detail::IsInRange<unsigned int, unsigned long>(unsigned long)
Line
Count
Source
267
2.03M
{
268
2.03M
  return IsInRangeImpl<T, U>::run(aX);
269
2.03M
}
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned long, unsigned int>(unsigned int)
bool mozilla::detail::IsInRange<unsigned int, int>(int)
Line
Count
Source
267
4.26M
{
268
4.26M
  return IsInRangeImpl<T, U>::run(aX);
269
4.26M
}
bool mozilla::detail::IsInRange<unsigned long, int>(int)
Line
Count
Source
267
8.19M
{
268
8.19M
  return IsInRangeImpl<T, U>::run(aX);
269
8.19M
}
Unexecuted instantiation: bool mozilla::detail::IsInRange<long, unsigned int>(unsigned int)
Unexecuted instantiation: bool mozilla::detail::IsInRange<long, unsigned long>(unsigned long)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned int, long>(long)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned short, unsigned long>(unsigned long)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned char, unsigned int>(unsigned int)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned short, unsigned int>(unsigned int)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned int, unsigned short>(unsigned short)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned long, long>(long)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned int, unsigned char>(unsigned char)
Unexecuted instantiation: bool mozilla::detail::IsInRange<int, long>(long)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned short, int>(int)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned char, unsigned long>(unsigned long)
Unexecuted instantiation: bool mozilla::detail::IsInRange<signed char, unsigned long>(unsigned long)
Unexecuted instantiation: bool mozilla::detail::IsInRange<short, unsigned long>(unsigned long)
Unexecuted instantiation: bool mozilla::detail::IsInRange<unsigned long, unsigned char>(unsigned char)
270
271
template<typename T>
272
inline bool
273
IsAddValid(T aX, T aY)
274
{
275
#if MOZ_HAS_BUILTIN_OP_OVERFLOW
276
  T dummy;
277
  return !__builtin_add_overflow(aX, aY, &dummy);
278
#else
279
  // Addition is valid if the sign of aX+aY is equal to either that of aX or
280
  // that of aY. Since the value of aX+aY is undefined if we have a signed
281
  // type, we compute it using the unsigned type of the same size.  Beware!
282
  // These bitwise operations can return a larger integer type, if T was a
283
  // small type like int8_t, so we explicitly cast to T.
284
285
  typename MakeUnsigned<T>::Type ux = aX;
286
  typename MakeUnsigned<T>::Type uy = aY;
287
  typename MakeUnsigned<T>::Type result = ux + uy;
288
  return IsSigned<T>::value
289
         ? HasSignBit(BinaryComplement(T((result ^ aX) & (result ^ aY))))
290
         : BinaryComplement(aX) >= aY;
291
#endif
292
}
293
294
template<typename T>
295
inline bool
296
IsSubValid(T aX, T aY)
297
{
298
#if MOZ_HAS_BUILTIN_OP_OVERFLOW
299
  T dummy;
300
  return !__builtin_sub_overflow(aX, aY, &dummy);
301
#else
302
  // Subtraction is valid if either aX and aY have same sign, or aX-aY and aX
303
  // have same sign. Since the value of aX-aY is undefined if we have a signed
304
  // type, we compute it using the unsigned type of the same size.
305
  typename MakeUnsigned<T>::Type ux = aX;
306
  typename MakeUnsigned<T>::Type uy = aY;
307
  typename MakeUnsigned<T>::Type result = ux - uy;
308
309
  return IsSigned<T>::value
310
         ? HasSignBit(BinaryComplement(T((result ^ aX) & (aX ^ aY))))
311
         : aX >= aY;
312
#endif
313
}
314
315
template<typename T,
316
         bool IsTSigned = IsSigned<T>::value,
317
         bool TwiceBiggerTypeIsSupported =
318
           IsSupported<typename TwiceBiggerType<T>::Type>::value>
319
struct IsMulValidImpl {};
320
321
template<typename T, bool IsTSigned>
322
struct IsMulValidImpl<T, IsTSigned, true>
323
{
324
  static bool run(T aX, T aY)
325
  {
326
    typedef typename TwiceBiggerType<T>::Type TwiceBiggerType;
327
    TwiceBiggerType product = TwiceBiggerType(aX) * TwiceBiggerType(aY);
328
    return IsInRange<T>(product);
329
  }
330
};
331
332
template<typename T>
333
struct IsMulValidImpl<T, true, false>
334
{
335
  static bool run(T aX, T aY)
336
  {
337
    const T max = MaxValue<T>::value;
338
    const T min = MinValue<T>::value;
339
340
    if (aX == 0 || aY == 0) {
341
      return true;
342
    }
343
    if (aX > 0) {
344
      return aY > 0
345
             ? aX <= max / aY
346
             : aY >= min / aX;
347
    }
348
349
    // If we reach this point, we know that aX < 0.
350
    return aY > 0
351
           ? aX >= min / aY
352
           : aY >= max / aX;
353
  }
354
};
355
356
template<typename T>
357
struct IsMulValidImpl<T, false, false>
358
{
359
  static bool run(T aX, T aY)
360
  {
361
    return aY == 0 ||  aX <= MaxValue<T>::value / aY;
362
  }
363
};
364
365
template<typename T>
366
inline bool
367
IsMulValid(T aX, T aY)
368
{
369
#if MOZ_HAS_BUILTIN_OP_OVERFLOW
370
  T dummy;
371
  return !__builtin_mul_overflow(aX, aY, &dummy);
372
#else
373
  return IsMulValidImpl<T>::run(aX, aY);
374
#endif
375
}
376
377
template<typename T>
378
inline bool
379
IsDivValid(T aX, T aY)
380
0
{
381
0
  // Keep in mind that in the signed case, min/-1 is invalid because
382
0
  // abs(min)>max.
383
0
  return aY != 0 &&
384
0
         !(IsSigned<T>::value && aX == MinValue<T>::value && aY == T(-1));
385
0
}
Unexecuted instantiation: bool mozilla::detail::IsDivValid<long>(long, long)
Unexecuted instantiation: bool mozilla::detail::IsDivValid<unsigned int>(unsigned int, unsigned int)
Unexecuted instantiation: bool mozilla::detail::IsDivValid<int>(int, int)
386
387
template<typename T, bool IsTSigned = IsSigned<T>::value>
388
struct IsModValidImpl;
389
390
template<typename T>
391
inline bool
392
IsModValid(T aX, T aY)
393
0
{
394
0
  return IsModValidImpl<T>::run(aX, aY);
395
0
}
396
397
/*
398
 * Mod is pretty simple.
399
 * For now, let's just use the ANSI C definition:
400
 * If aX or aY are negative, the results are implementation defined.
401
 *   Consider these invalid.
402
 * Undefined for aY=0.
403
 * The result will never exceed either aX or aY.
404
 *
405
 * Checking that aX>=0 is a warning when T is unsigned.
406
 */
407
408
template<typename T>
409
struct IsModValidImpl<T, false>
410
{
411
  static inline bool run(T aX, T aY)
412
  {
413
    return aY >= 1;
414
  }
415
};
416
417
template<typename T>
418
struct IsModValidImpl<T, true>
419
{
420
  static inline bool run(T aX, T aY)
421
0
  {
422
0
    if (aX < 0) {
423
0
      return false;
424
0
    }
425
0
    return aY >= 1;
426
0
  }
427
};
428
429
template<typename T, bool IsSigned = IsSigned<T>::value>
430
struct NegateImpl;
431
432
template<typename T>
433
struct NegateImpl<T, false>
434
{
435
  static CheckedInt<T> negate(const CheckedInt<T>& aVal)
436
  {
437
    // Handle negation separately for signed/unsigned, for simpler code and to
438
    // avoid an MSVC warning negating an unsigned value.
439
    return CheckedInt<T>(0, aVal.isValid() && aVal.mValue == 0);
440
  }
441
};
442
443
template<typename T>
444
struct NegateImpl<T, true>
445
{
446
  static CheckedInt<T> negate(const CheckedInt<T>& aVal)
447
271
  {
448
271
    // Watch out for the min-value, which (with twos-complement) can't be
449
271
    // negated as -min-value is then (max-value + 1).
450
271
    if (!aVal.isValid() || aVal.mValue == MinValue<T>::value) {
451
0
      return CheckedInt<T>(aVal.mValue, false);
452
0
    }
453
271
    return CheckedInt<T>(-aVal.mValue, true);
454
271
  }
mozilla::detail::NegateImpl<int, true>::negate(mozilla::CheckedInt<int> const&)
Line
Count
Source
447
271
  {
448
271
    // Watch out for the min-value, which (with twos-complement) can't be
449
271
    // negated as -min-value is then (max-value + 1).
450
271
    if (!aVal.isValid() || aVal.mValue == MinValue<T>::value) {
451
0
      return CheckedInt<T>(aVal.mValue, false);
452
0
    }
453
271
    return CheckedInt<T>(-aVal.mValue, true);
454
271
  }
Unexecuted instantiation: mozilla::detail::NegateImpl<long, true>::negate(mozilla::CheckedInt<long> const&)
455
};
456
457
} // namespace detail
458
459
460
/*
461
 * Step 3: Now define the CheckedInt class.
462
 */
463
464
/**
465
 * @class CheckedInt
466
 * @brief Integer wrapper class checking for integer overflow and other errors
467
 * @param T the integer type to wrap. Can be any type among the following:
468
 *            - any basic integer type such as |int|
469
 *            - any stdint type such as |int8_t|
470
 *
471
 * This class implements guarded integer arithmetic. Do a computation, check
472
 * that isValid() returns true, you then have a guarantee that no problem, such
473
 * as integer overflow, happened during this computation, and you can call
474
 * value() to get the plain integer value.
475
 *
476
 * The arithmetic operators in this class are guaranteed not to raise a signal
477
 * (e.g. in case of a division by zero).
478
 *
479
 * For example, suppose that you want to implement a function that computes
480
 * (aX+aY)/aZ, that doesn't crash if aZ==0, and that reports on error (divide by
481
 * zero or integer overflow). You could code it as follows:
482
   @code
483
   bool computeXPlusYOverZ(int aX, int aY, int aZ, int* aResult)
484
   {
485
     CheckedInt<int> checkedResult = (CheckedInt<int>(aX) + aY) / aZ;
486
     if (checkedResult.isValid()) {
487
       *aResult = checkedResult.value();
488
       return true;
489
     } else {
490
       return false;
491
     }
492
   }
493
   @endcode
494
 *
495
 * Implicit conversion from plain integers to checked integers is allowed. The
496
 * plain integer is checked to be in range before being casted to the
497
 * destination type. This means that the following lines all compile, and the
498
 * resulting CheckedInts are correctly detected as valid or invalid:
499
 * @code
500
   // 1 is of type int, is found to be in range for uint8_t, x is valid
501
   CheckedInt<uint8_t> x(1);
502
   // -1 is of type int, is found not to be in range for uint8_t, x is invalid
503
   CheckedInt<uint8_t> x(-1);
504
   // -1 is of type int, is found to be in range for int8_t, x is valid
505
   CheckedInt<int8_t> x(-1);
506
   // 1000 is of type int16_t, is found not to be in range for int8_t,
507
   // x is invalid
508
   CheckedInt<int8_t> x(int16_t(1000));
509
   // 3123456789 is of type uint32_t, is found not to be in range for int32_t,
510
   // x is invalid
511
   CheckedInt<int32_t> x(uint32_t(3123456789));
512
 * @endcode
513
 * Implicit conversion from
514
 * checked integers to plain integers is not allowed. As shown in the
515
 * above example, to get the value of a checked integer as a normal integer,
516
 * call value().
517
 *
518
 * Arithmetic operations between checked and plain integers is allowed; the
519
 * result type is the type of the checked integer.
520
 *
521
 * Checked integers of different types cannot be used in the same arithmetic
522
 * expression.
523
 *
524
 * There are convenience typedefs for all stdint types, of the following form
525
 * (these are just 2 examples):
526
   @code
527
   typedef CheckedInt<int32_t> CheckedInt32;
528
   typedef CheckedInt<uint16_t> CheckedUint16;
529
   @endcode
530
 */
531
template<typename T>
532
class CheckedInt
533
{
534
protected:
535
  T mValue;
536
  bool mIsValid;
537
538
  template<typename U>
539
  CheckedInt(U aValue, bool aIsValid) : mValue(aValue), mIsValid(aIsValid)
540
12.4M
  {
541
12.4M
    static_assert(detail::IsSupported<T>::value &&
542
12.4M
                  detail::IsSupported<U>::value,
543
12.4M
                  "This type is not supported by CheckedInt");
544
12.4M
  }
mozilla::CheckedInt<unsigned long>::CheckedInt<int>(int, bool)
Line
Count
Source
540
232
  {
541
232
    static_assert(detail::IsSupported<T>::value &&
542
232
                  detail::IsSupported<U>::value,
543
232
                  "This type is not supported by CheckedInt");
544
232
  }
mozilla::CheckedInt<unsigned long>::CheckedInt<unsigned long>(unsigned long, bool)
Line
Count
Source
540
106k
  {
541
106k
    static_assert(detail::IsSupported<T>::value &&
542
106k
                  detail::IsSupported<U>::value,
543
106k
                  "This type is not supported by CheckedInt");
544
106k
  }
Unexecuted instantiation: mozilla::CheckedInt<long>::CheckedInt<int>(int, bool)
mozilla::CheckedInt<long>::CheckedInt<long>(long, bool)
Line
Count
Source
540
110
  {
541
110
    static_assert(detail::IsSupported<T>::value &&
542
110
                  detail::IsSupported<U>::value,
543
110
                  "This type is not supported by CheckedInt");
544
110
  }
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>::CheckedInt<int>(int, bool)
mozilla::CheckedInt<unsigned int>::CheckedInt<unsigned int>(unsigned int, bool)
Line
Count
Source
540
12.2M
  {
541
12.2M
    static_assert(detail::IsSupported<T>::value &&
542
12.2M
                  detail::IsSupported<U>::value,
543
12.2M
                  "This type is not supported by CheckedInt");
544
12.2M
  }
mozilla::CheckedInt<int>::CheckedInt<int>(int, bool)
Line
Count
Source
540
151k
  {
541
151k
    static_assert(detail::IsSupported<T>::value &&
542
151k
                  detail::IsSupported<U>::value,
543
151k
                  "This type is not supported by CheckedInt");
544
151k
  }
Unexecuted instantiation: mozilla::CheckedInt<unsigned short>::CheckedInt<int>(int, bool)
Unexecuted instantiation: mozilla::CheckedInt<unsigned short>::CheckedInt<unsigned short>(unsigned short, bool)
545
546
  friend struct detail::NegateImpl<T>;
547
548
public:
549
  /**
550
   * Constructs a checked integer with given @a value. The checked integer is
551
   * initialized as valid or invalid depending on whether the @a value
552
   * is in range.
553
   *
554
   * This constructor is not explicit. Instead, the type of its argument is a
555
   * separate template parameter, ensuring that no conversion is performed
556
   * before this constructor is actually called. As explained in the above
557
   * documentation for class CheckedInt, this constructor checks that its
558
   * argument is valid.
559
   */
560
  template<typename U>
561
  MOZ_IMPLICIT constexpr CheckedInt(U aValue) MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT
562
    : mValue(T(aValue)),
563
      mIsValid(detail::IsInRange<T>(aValue))
564
30.9M
  {
565
30.9M
    static_assert(detail::IsSupported<T>::value &&
566
30.9M
                  detail::IsSupported<U>::value,
567
30.9M
                  "This type is not supported by CheckedInt");
568
30.9M
  }
mozilla::CheckedInt<unsigned long>::CheckedInt<unsigned long>(unsigned long)
Line
Count
Source
564
60.8k
  {
565
60.8k
    static_assert(detail::IsSupported<T>::value &&
566
60.8k
                  detail::IsSupported<U>::value,
567
60.8k
                  "This type is not supported by CheckedInt");
568
60.8k
  }
mozilla::CheckedInt<long>::CheckedInt<long>(long)
Line
Count
Source
564
196
  {
565
196
    static_assert(detail::IsSupported<T>::value &&
566
196
                  detail::IsSupported<U>::value,
567
196
                  "This type is not supported by CheckedInt");
568
196
  }
mozilla::CheckedInt<long>::CheckedInt<int>(int)
Line
Count
Source
564
12
  {
565
12
    static_assert(detail::IsSupported<T>::value &&
566
12
                  detail::IsSupported<U>::value,
567
12
                  "This type is not supported by CheckedInt");
568
12
  }
mozilla::CheckedInt<int>::CheckedInt<unsigned long>(unsigned long)
Line
Count
Source
564
2
  {
565
2
    static_assert(detail::IsSupported<T>::value &&
566
2
                  detail::IsSupported<U>::value,
567
2
                  "This type is not supported by CheckedInt");
568
2
  }
mozilla::CheckedInt<unsigned int>::CheckedInt<unsigned int>(unsigned int)
Line
Count
Source
564
16.0M
  {
565
16.0M
    static_assert(detail::IsSupported<T>::value &&
566
16.0M
                  detail::IsSupported<U>::value,
567
16.0M
                  "This type is not supported by CheckedInt");
568
16.0M
  }
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>::CheckedInt<unsigned int>(unsigned int)
mozilla::CheckedInt<unsigned int>::CheckedInt<int>(int)
Line
Count
Source
564
4.26M
  {
565
4.26M
    static_assert(detail::IsSupported<T>::value &&
566
4.26M
                  detail::IsSupported<U>::value,
567
4.26M
                  "This type is not supported by CheckedInt");
568
4.26M
  }
mozilla::CheckedInt<unsigned long>::CheckedInt<int>(int)
Line
Count
Source
564
8.19M
  {
565
8.19M
    static_assert(detail::IsSupported<T>::value &&
566
8.19M
                  detail::IsSupported<U>::value,
567
8.19M
                  "This type is not supported by CheckedInt");
568
8.19M
  }
mozilla::CheckedInt<int>::CheckedInt<int>(int)
Line
Count
Source
564
147k
  {
565
147k
    static_assert(detail::IsSupported<T>::value &&
566
147k
                  detail::IsSupported<U>::value,
567
147k
                  "This type is not supported by CheckedInt");
568
147k
  }
mozilla::CheckedInt<int>::CheckedInt<unsigned int>(unsigned int)
Line
Count
Source
564
147k
  {
565
147k
    static_assert(detail::IsSupported<T>::value &&
566
147k
                  detail::IsSupported<U>::value,
567
147k
                  "This type is not supported by CheckedInt");
568
147k
  }
Unexecuted instantiation: mozilla::CheckedInt<long>::CheckedInt<unsigned int>(unsigned int)
mozilla::CheckedInt<unsigned int>::CheckedInt<unsigned long>(unsigned long)
Line
Count
Source
564
2.03M
  {
565
2.03M
    static_assert(detail::IsSupported<T>::value &&
566
2.03M
                  detail::IsSupported<U>::value,
567
2.03M
                  "This type is not supported by CheckedInt");
568
2.03M
  }
Unexecuted instantiation: mozilla::CheckedInt<long>::CheckedInt<unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned short>::CheckedInt<unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned short>::CheckedInt<unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned char>::CheckedInt<unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>::CheckedInt<unsigned short>(unsigned short)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>::CheckedInt<long>(long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>::CheckedInt<unsigned char>(unsigned char)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>::CheckedInt<long>(long)
Unexecuted instantiation: mozilla::CheckedInt<int>::CheckedInt<long>(long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned short>::CheckedInt<int>(int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned char>::CheckedInt<unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<signed char>::CheckedInt<unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<short>::CheckedInt<unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>::CheckedInt<unsigned char>(unsigned char)
569
570
  template<typename U>
571
  friend class CheckedInt;
572
573
  template<typename U>
574
  CheckedInt<U> toChecked() const
575
2
  {
576
2
    CheckedInt<U> ret(mValue);
577
2
    ret.mIsValid = ret.mIsValid && mIsValid;
578
2
    return ret;
579
2
  }
580
581
  /** Constructs a valid checked integer with initial value 0 */
582
  constexpr CheckedInt() : mValue(0), mIsValid(true)
583
44.3k
  {
584
44.3k
    static_assert(detail::IsSupported<T>::value,
585
44.3k
                  "This type is not supported by CheckedInt");
586
44.3k
  }
mozilla::CheckedInt<unsigned int>::CheckedInt()
Line
Count
Source
583
43.0k
  {
584
43.0k
    static_assert(detail::IsSupported<T>::value,
585
43.0k
                  "This type is not supported by CheckedInt");
586
43.0k
  }
mozilla::CheckedInt<int>::CheckedInt()
Line
Count
Source
583
1.24k
  {
584
1.24k
    static_assert(detail::IsSupported<T>::value,
585
1.24k
                  "This type is not supported by CheckedInt");
586
1.24k
  }
Unexecuted instantiation: mozilla::CheckedInt<long>::CheckedInt()
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>::CheckedInt()
587
588
  /** @returns the actual value */
589
  T value() const
590
14.0M
  {
591
14.0M
    MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)");
592
14.0M
    return mValue;
593
14.0M
  }
mozilla::CheckedInt<unsigned long>::value() const
Line
Count
Source
590
42.2k
  {
591
42.2k
    MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)");
592
42.2k
    return mValue;
593
42.2k
  }
mozilla::CheckedInt<long>::value() const
Line
Count
Source
590
98
  {
591
98
    MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)");
592
98
    return mValue;
593
98
  }
mozilla::CheckedInt<int>::value() const
Line
Count
Source
590
145k
  {
591
145k
    MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)");
592
145k
    return mValue;
593
145k
  }
mozilla::CheckedInt<unsigned int>::value() const
Line
Count
Source
590
13.8M
  {
591
13.8M
    MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)");
592
13.8M
    return mValue;
593
13.8M
  }
Unexecuted instantiation: mozilla::CheckedInt<unsigned short>::value() const
Unexecuted instantiation: mozilla::CheckedInt<unsigned char>::value() const
Unexecuted instantiation: mozilla::CheckedInt<signed char>::value() const
Unexecuted instantiation: mozilla::CheckedInt<short>::value() const
594
595
  /**
596
   * @returns true if the checked integer is valid, i.e. is not the result
597
   * of an invalid operation or of an operation involving an invalid checked
598
   * integer
599
   */
600
  bool isValid() const
601
10.1M
  {
602
10.1M
    return mIsValid;
603
10.1M
  }
mozilla::CheckedInt<unsigned long>::isValid() const
Line
Count
Source
601
28.0k
  {
602
28.0k
    return mIsValid;
603
28.0k
  }
mozilla::CheckedInt<long>::isValid() const
Line
Count
Source
601
98
  {
602
98
    return mIsValid;
603
98
  }
mozilla::CheckedInt<unsigned int>::isValid() const
Line
Count
Source
601
10.1M
  {
602
10.1M
    return mIsValid;
603
10.1M
  }
mozilla::CheckedInt<int>::isValid() const
Line
Count
Source
601
3.70k
  {
602
3.70k
    return mIsValid;
603
3.70k
  }
Unexecuted instantiation: mozilla::CheckedInt<unsigned short>::isValid() const
Unexecuted instantiation: mozilla::CheckedInt<unsigned char>::isValid() const
Unexecuted instantiation: mozilla::CheckedInt<signed char>::isValid() const
Unexecuted instantiation: mozilla::CheckedInt<short>::isValid() const
604
605
  template<typename U>
606
  friend CheckedInt<U> operator +(const CheckedInt<U>& aLhs,
607
                                  const CheckedInt<U>& aRhs);
608
  template<typename U>
609
  CheckedInt& operator +=(U aRhs);
610
  CheckedInt& operator +=(const CheckedInt<T>& aRhs);
611
612
  template<typename U>
613
  friend CheckedInt<U> operator -(const CheckedInt<U>& aLhs,
614
                                  const CheckedInt<U>& aRhs);
615
  template<typename U>
616
  CheckedInt& operator -=(U aRhs);
617
  CheckedInt& operator -=(const CheckedInt<T>& aRhs);
618
619
  template<typename U>
620
  friend CheckedInt<U> operator *(const CheckedInt<U>& aLhs,
621
                                  const CheckedInt<U>& aRhs);
622
  template<typename U>
623
  CheckedInt& operator *=(U aRhs);
624
  CheckedInt& operator *=(const CheckedInt<T>& aRhs);
625
626
  template<typename U>
627
  friend CheckedInt<U> operator /(const CheckedInt<U>& aLhs,
628
                                  const CheckedInt<U>& aRhs);
629
  template<typename U>
630
  CheckedInt& operator /=(U aRhs);
631
  CheckedInt& operator /=(const CheckedInt<T>& aRhs);
632
633
  template<typename U>
634
  friend CheckedInt<U> operator %(const CheckedInt<U>& aLhs,
635
                                  const CheckedInt<U>& aRhs);
636
  template<typename U>
637
  CheckedInt& operator %=(U aRhs);
638
  CheckedInt& operator %=(const CheckedInt<T>& aRhs);
639
640
  CheckedInt operator -() const
641
271
  {
642
271
    return detail::NegateImpl<T>::negate(*this);
643
271
  }
mozilla::CheckedInt<int>::operator-() const
Line
Count
Source
641
271
  {
642
271
    return detail::NegateImpl<T>::negate(*this);
643
271
  }
Unexecuted instantiation: mozilla::CheckedInt<long>::operator-() const
644
645
  /**
646
   * @returns true if the left and right hand sides are valid
647
   * and have the same value.
648
   *
649
   * Note that these semantics are the reason why we don't offer
650
   * a operator!=. Indeed, we'd want to have a!=b be equivalent to !(a==b)
651
   * but that would mean that whenever a or b is invalid, a!=b
652
   * is always true, which would be very confusing.
653
   *
654
   * For similar reasons, operators <, >, <=, >= would be very tricky to
655
   * specify, so we just avoid offering them.
656
   *
657
   * Notice that these == semantics are made more reasonable by these facts:
658
   *  1. a==b implies equality at the raw data level
659
   *     (the converse is false, as a==b is never true among invalids)
660
   *  2. This is similar to the behavior of IEEE floats, where a==b
661
   *     means that a and b have the same value *and* neither is NaN.
662
   */
663
  bool operator ==(const CheckedInt& aOther) const
664
0
  {
665
0
    return mIsValid && aOther.mIsValid && mValue == aOther.mValue;
666
0
  }
Unexecuted instantiation: mozilla::CheckedInt<int>::operator==(mozilla::CheckedInt<int> const&) const
Unexecuted instantiation: mozilla::CheckedInt<long>::operator==(mozilla::CheckedInt<long> const&) const
667
668
  /** prefix ++ */
669
  CheckedInt& operator++()
670
0
  {
671
0
    *this += 1;
672
0
    return *this;
673
0
  }
674
675
  /** postfix ++ */
676
  CheckedInt operator++(int)
677
0
  {
678
0
    CheckedInt tmp = *this;
679
0
    *this += 1;
680
0
    return tmp;
681
0
  }
682
683
  /** prefix -- */
684
  CheckedInt& operator--()
685
  {
686
    *this -= 1;
687
    return *this;
688
  }
689
690
  /** postfix -- */
691
  CheckedInt operator--(int)
692
  {
693
    CheckedInt tmp = *this;
694
    *this -= 1;
695
    return tmp;
696
  }
697
698
private:
699
  /**
700
   * The !=, <, <=, >, >= operators are disabled:
701
   * see the comment on operator==.
702
   */
703
  template<typename U> bool operator !=(U aOther) const = delete;
704
  template<typename U> bool operator < (U aOther) const = delete;
705
  template<typename U> bool operator <=(U aOther) const = delete;
706
  template<typename U> bool operator > (U aOther) const = delete;
707
  template<typename U> bool operator >=(U aOther) const = delete;
708
};
709
710
#define MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(NAME, OP)                        \
711
  template<typename T>                                                        \
712
  inline CheckedInt<T>                                                        \
713
  operator OP(const CheckedInt<T>& aLhs, const CheckedInt<T>& aRhs)           \
714
0
  {                                                                           \
715
0
    if (!detail::Is##NAME##Valid(aLhs.mValue, aRhs.mValue)) {                 \
716
0
      return CheckedInt<T>(0, false);                                         \
717
0
    }                                                                         \
718
0
    return CheckedInt<T>(aLhs.mValue OP aRhs.mValue,                          \
719
0
                         aLhs.mIsValid && aRhs.mIsValid);                     \
720
0
  }
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator/<long>(mozilla::CheckedInt<long> const&, mozilla::CheckedInt<long> const&)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator%<long>(mozilla::CheckedInt<long> const&, mozilla::CheckedInt<long> const&)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator/<unsigned int>(mozilla::CheckedInt<unsigned int> const&, mozilla::CheckedInt<unsigned int> const&)
Unexecuted instantiation: mozilla::CheckedInt<int> mozilla::operator/<int>(mozilla::CheckedInt<int> const&, mozilla::CheckedInt<int> const&)
721
722
#if MOZ_HAS_BUILTIN_OP_OVERFLOW
723
#define MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2(NAME, OP, FUN)                  \
724
  template<typename T>                                                        \
725
  inline CheckedInt<T>                                                        \
726
  operator OP(const CheckedInt<T>& aLhs, const CheckedInt<T>& aRhs)           \
727
12.4M
  {                                                                           \
728
12.4M
    T result;                                                                 \
729
12.4M
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
254
      return CheckedInt<T>(0, false);                                         \
731
254
    }                                                                         \
732
12.4M
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
12.4M
  }
mozilla::CheckedInt<unsigned long> mozilla::operator*<unsigned long>(mozilla::CheckedInt<unsigned long> const&, mozilla::CheckedInt<unsigned long> const&)
Line
Count
Source
727
53.2k
  {                                                                           \
728
53.2k
    T result;                                                                 \
729
53.2k
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
232
      return CheckedInt<T>(0, false);                                         \
731
232
    }                                                                         \
732
53.2k
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
53.2k
  }
mozilla::CheckedInt<long> mozilla::operator+<long>(mozilla::CheckedInt<long> const&, mozilla::CheckedInt<long> const&)
Line
Count
Source
727
110
  {                                                                           \
728
110
    T result;                                                                 \
729
110
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
0
      return CheckedInt<T>(0, false);                                         \
731
0
    }                                                                         \
732
110
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
110
  }
mozilla::CheckedInt<unsigned long> mozilla::operator+<unsigned long>(mozilla::CheckedInt<unsigned long> const&, mozilla::CheckedInt<unsigned long> const&)
Line
Count
Source
727
53.4k
  {                                                                           \
728
53.4k
    T result;                                                                 \
729
53.4k
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
0
      return CheckedInt<T>(0, false);                                         \
731
0
    }                                                                         \
732
53.4k
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
53.4k
  }
mozilla::CheckedInt<unsigned int> mozilla::operator*<unsigned int>(mozilla::CheckedInt<unsigned int> const&, mozilla::CheckedInt<unsigned int> const&)
Line
Count
Source
727
2.03M
  {                                                                           \
728
2.03M
    T result;                                                                 \
729
2.03M
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
0
      return CheckedInt<T>(0, false);                                         \
731
0
    }                                                                         \
732
2.03M
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
2.03M
  }
mozilla::CheckedInt<unsigned int> mozilla::operator+<unsigned int>(mozilla::CheckedInt<unsigned int> const&, mozilla::CheckedInt<unsigned int> const&)
Line
Count
Source
727
9.12M
  {                                                                           \
728
9.12M
    T result;                                                                 \
729
9.12M
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
0
      return CheckedInt<T>(0, false);                                         \
731
0
    }                                                                         \
732
9.12M
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
9.12M
  }
mozilla::CheckedInt<int> mozilla::operator+<int>(mozilla::CheckedInt<int> const&, mozilla::CheckedInt<int> const&)
Line
Count
Source
727
147k
  {                                                                           \
728
147k
    T result;                                                                 \
729
147k
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
1
      return CheckedInt<T>(0, false);                                         \
731
1
    }                                                                         \
732
147k
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
147k
  }
mozilla::CheckedInt<int> mozilla::operator*<int>(mozilla::CheckedInt<int> const&, mozilla::CheckedInt<int> const&)
Line
Count
Source
727
3.43k
  {                                                                           \
728
3.43k
    T result;                                                                 \
729
3.43k
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
21
      return CheckedInt<T>(0, false);                                         \
731
21
    }                                                                         \
732
3.43k
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
3.43k
  }
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator*<long>(mozilla::CheckedInt<long> const&, mozilla::CheckedInt<long> const&)
mozilla::CheckedInt<unsigned int> mozilla::operator-<unsigned int>(mozilla::CheckedInt<unsigned int> const&, mozilla::CheckedInt<unsigned int> const&)
Line
Count
Source
727
1.06M
  {                                                                           \
728
1.06M
    T result;                                                                 \
729
1.06M
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
0
      return CheckedInt<T>(0, false);                                         \
731
0
    }                                                                         \
732
1.06M
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
1.06M
  }
Unexecuted instantiation: mozilla::CheckedInt<int> mozilla::operator-<int>(mozilla::CheckedInt<int> const&, mozilla::CheckedInt<int> const&)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator-<long>(mozilla::CheckedInt<long> const&, mozilla::CheckedInt<long> const&)
mozilla::CheckedInt<unsigned long> mozilla::operator-<unsigned long>(mozilla::CheckedInt<unsigned long> const&, mozilla::CheckedInt<unsigned long> const&)
Line
Count
Source
727
2
  {                                                                           \
728
2
    T result;                                                                 \
729
2
    if (FUN(aLhs.mValue, aRhs.mValue, &result)) {                             \
730
0
      return CheckedInt<T>(0, false);                                         \
731
0
    }                                                                         \
732
2
    return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid);             \
733
2
  }
Unexecuted instantiation: mozilla::CheckedInt<unsigned short> mozilla::operator+<unsigned short>(mozilla::CheckedInt<unsigned short> const&, mozilla::CheckedInt<unsigned short> const&)
734
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2(Add, +, __builtin_add_overflow)
735
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2(Sub, -, __builtin_sub_overflow)
736
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2(Mul, *, __builtin_mul_overflow)
737
#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2
738
#else
739
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +)
740
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -)
741
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *)
742
#endif
743
744
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Div, /)
745
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mod, %)
746
#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR
747
748
// Implement castToCheckedInt<T>(x), making sure that
749
//  - it allows x to be either a CheckedInt<T> or any integer type
750
//    that can be casted to T
751
//  - if x is already a CheckedInt<T>, we just return a reference to it,
752
//    instead of copying it (optimization)
753
754
namespace detail {
755
756
template<typename T, typename U>
757
struct CastToCheckedIntImpl
758
{
759
  typedef CheckedInt<T> ReturnType;
760
12.4M
  static CheckedInt<T> run(U aU) { return aU; }
mozilla::detail::CastToCheckedIntImpl<unsigned long, unsigned long>::run(unsigned long)
Line
Count
Source
760
53.4k
  static CheckedInt<T> run(U aU) { return aU; }
mozilla::detail::CastToCheckedIntImpl<long, long>::run(long)
Line
Count
Source
760
98
  static CheckedInt<T> run(U aU) { return aU; }
mozilla::detail::CastToCheckedIntImpl<long, int>::run(int)
Line
Count
Source
760
12
  static CheckedInt<T> run(U aU) { return aU; }
mozilla::detail::CastToCheckedIntImpl<unsigned int, unsigned long>::run(unsigned long)
Line
Count
Source
760
1.01M
  static CheckedInt<T> run(U aU) { return aU; }
mozilla::detail::CastToCheckedIntImpl<unsigned int, int>::run(int)
Line
Count
Source
760
4.26M
  static CheckedInt<T> run(U aU) { return aU; }
mozilla::detail::CastToCheckedIntImpl<unsigned long, int>::run(int)
Line
Count
Source
760
53.2k
  static CheckedInt<T> run(U aU) { return aU; }
mozilla::detail::CastToCheckedIntImpl<unsigned int, unsigned int>::run(unsigned int)
Line
Count
Source
760
6.94M
  static CheckedInt<T> run(U aU) { return aU; }
mozilla::detail::CastToCheckedIntImpl<int, int>::run(int)
Line
Count
Source
760
147k
  static CheckedInt<T> run(U aU) { return aU; }
mozilla::detail::CastToCheckedIntImpl<int, unsigned int>::run(unsigned int)
Line
Count
Source
760
3.42k
  static CheckedInt<T> run(U aU) { return aU; }
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<long, unsigned int>::run(unsigned int)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<long, unsigned long>::run(unsigned long)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned long, unsigned int>::run(unsigned int)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<int, unsigned long>::run(unsigned long)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned int, unsigned short>::run(unsigned short)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned long, long>::run(long)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned int, unsigned char>::run(unsigned char)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned int, long>::run(long)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned short, unsigned int>::run(unsigned int)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned long, unsigned char>::run(unsigned char)
761
};
762
763
template<typename T>
764
struct CastToCheckedIntImpl<T, CheckedInt<T> >
765
{
766
  typedef const CheckedInt<T>& ReturnType;
767
  static const CheckedInt<T>& run(const CheckedInt<T>& aU) { return aU; }
768
};
769
770
} // namespace detail
771
772
template<typename T, typename U>
773
inline typename detail::CastToCheckedIntImpl<T, U>::ReturnType
774
castToCheckedInt(U aU)
775
12.4M
{
776
12.4M
  static_assert(detail::IsSupported<T>::value &&
777
12.4M
                detail::IsSupported<U>::value,
778
12.4M
                "This type is not supported by CheckedInt");
779
12.4M
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
12.4M
}
mozilla::detail::CastToCheckedIntImpl<unsigned long, unsigned long>::ReturnType mozilla::castToCheckedInt<unsigned long, unsigned long>(unsigned long)
Line
Count
Source
775
53.4k
{
776
53.4k
  static_assert(detail::IsSupported<T>::value &&
777
53.4k
                detail::IsSupported<U>::value,
778
53.4k
                "This type is not supported by CheckedInt");
779
53.4k
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
53.4k
}
mozilla::detail::CastToCheckedIntImpl<long, long>::ReturnType mozilla::castToCheckedInt<long, long>(long)
Line
Count
Source
775
98
{
776
98
  static_assert(detail::IsSupported<T>::value &&
777
98
                detail::IsSupported<U>::value,
778
98
                "This type is not supported by CheckedInt");
779
98
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
98
}
mozilla::detail::CastToCheckedIntImpl<long, int>::ReturnType mozilla::castToCheckedInt<long, int>(int)
Line
Count
Source
775
12
{
776
12
  static_assert(detail::IsSupported<T>::value &&
777
12
                detail::IsSupported<U>::value,
778
12
                "This type is not supported by CheckedInt");
779
12
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
12
}
mozilla::detail::CastToCheckedIntImpl<unsigned int, unsigned long>::ReturnType mozilla::castToCheckedInt<unsigned int, unsigned long>(unsigned long)
Line
Count
Source
775
1.01M
{
776
1.01M
  static_assert(detail::IsSupported<T>::value &&
777
1.01M
                detail::IsSupported<U>::value,
778
1.01M
                "This type is not supported by CheckedInt");
779
1.01M
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
1.01M
}
mozilla::detail::CastToCheckedIntImpl<unsigned int, int>::ReturnType mozilla::castToCheckedInt<unsigned int, int>(int)
Line
Count
Source
775
4.26M
{
776
4.26M
  static_assert(detail::IsSupported<T>::value &&
777
4.26M
                detail::IsSupported<U>::value,
778
4.26M
                "This type is not supported by CheckedInt");
779
4.26M
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
4.26M
}
mozilla::detail::CastToCheckedIntImpl<unsigned long, int>::ReturnType mozilla::castToCheckedInt<unsigned long, int>(int)
Line
Count
Source
775
53.2k
{
776
53.2k
  static_assert(detail::IsSupported<T>::value &&
777
53.2k
                detail::IsSupported<U>::value,
778
53.2k
                "This type is not supported by CheckedInt");
779
53.2k
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
53.2k
}
mozilla::detail::CastToCheckedIntImpl<unsigned int, unsigned int>::ReturnType mozilla::castToCheckedInt<unsigned int, unsigned int>(unsigned int)
Line
Count
Source
775
6.94M
{
776
6.94M
  static_assert(detail::IsSupported<T>::value &&
777
6.94M
                detail::IsSupported<U>::value,
778
6.94M
                "This type is not supported by CheckedInt");
779
6.94M
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
6.94M
}
mozilla::detail::CastToCheckedIntImpl<int, int>::ReturnType mozilla::castToCheckedInt<int, int>(int)
Line
Count
Source
775
147k
{
776
147k
  static_assert(detail::IsSupported<T>::value &&
777
147k
                detail::IsSupported<U>::value,
778
147k
                "This type is not supported by CheckedInt");
779
147k
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
147k
}
mozilla::detail::CastToCheckedIntImpl<int, unsigned int>::ReturnType mozilla::castToCheckedInt<int, unsigned int>(unsigned int)
Line
Count
Source
775
3.42k
{
776
3.42k
  static_assert(detail::IsSupported<T>::value &&
777
3.42k
                detail::IsSupported<U>::value,
778
3.42k
                "This type is not supported by CheckedInt");
779
3.42k
  return detail::CastToCheckedIntImpl<T, U>::run(aU);
780
3.42k
}
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<long, unsigned int>::ReturnType mozilla::castToCheckedInt<long, unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<long, unsigned long>::ReturnType mozilla::castToCheckedInt<long, unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned long, unsigned int>::ReturnType mozilla::castToCheckedInt<unsigned long, unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<int, unsigned long>::ReturnType mozilla::castToCheckedInt<int, unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned int, unsigned short>::ReturnType mozilla::castToCheckedInt<unsigned int, unsigned short>(unsigned short)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned long, long>::ReturnType mozilla::castToCheckedInt<unsigned long, long>(long)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned int, unsigned char>::ReturnType mozilla::castToCheckedInt<unsigned int, unsigned char>(unsigned char)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned int, long>::ReturnType mozilla::castToCheckedInt<unsigned int, long>(long)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned short, unsigned int>::ReturnType mozilla::castToCheckedInt<unsigned short, unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::detail::CastToCheckedIntImpl<unsigned long, unsigned char>::ReturnType mozilla::castToCheckedInt<unsigned long, unsigned char>(unsigned char)
781
782
#define MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP)            \
783
  template<typename T>                                                          \
784
  template<typename U>                                                          \
785
  CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(U aRhs)                    \
786
7.18M
  {                                                                             \
787
7.18M
    *this = *this OP castToCheckedInt<T>(aRhs);                                 \
788
7.18M
    return *this;                                                               \
789
7.18M
  }                                                                             \
mozilla::CheckedInt<long>& mozilla::CheckedInt<long>::operator+=<int>(int)
Line
Count
Source
786
12
  {                                                                             \
787
12
    *this = *this OP castToCheckedInt<T>(aRhs);                                 \
788
12
    return *this;                                                               \
789
12
  }                                                                             \
mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator+=<unsigned long>(unsigned long)
Line
Count
Source
786
46.3k
  {                                                                             \
787
46.3k
    *this = *this OP castToCheckedInt<T>(aRhs);                                 \
788
46.3k
    return *this;                                                               \
789
46.3k
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator*=<int>(int)
mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator+=<int>(int)
Line
Count
Source
786
349
  {                                                                             \
787
349
    *this = *this OP castToCheckedInt<T>(aRhs);                                 \
788
349
    return *this;                                                               \
789
349
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator+=<int>(int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator*=<unsigned long>(unsigned long)
mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator+=<unsigned int>(unsigned int)
Line
Count
Source
786
5.87M
  {                                                                             \
787
5.87M
    *this = *this OP castToCheckedInt<T>(aRhs);                                 \
788
5.87M
    return *this;                                                               \
789
5.87M
  }                                                                             \
mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator-=<unsigned int>(unsigned int)
Line
Count
Source
786
1.06M
  {                                                                             \
787
1.06M
    *this = *this OP castToCheckedInt<T>(aRhs);                                 \
788
1.06M
    return *this;                                                               \
789
1.06M
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<int>& mozilla::CheckedInt<int>::operator*=<int>(int)
mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator*=<int>(int)
Line
Count
Source
786
46.1k
  {                                                                             \
787
46.1k
    *this = *this OP castToCheckedInt<T>(aRhs);                                 \
788
46.1k
    return *this;                                                               \
789
46.1k
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<long>& mozilla::CheckedInt<long>::operator+=<unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<long>& mozilla::CheckedInt<long>::operator+=<long>(long)
mozilla::CheckedInt<int>& mozilla::CheckedInt<int>::operator+=<int>(int)
Line
Count
Source
786
144k
  {                                                                             \
787
144k
    *this = *this OP castToCheckedInt<T>(aRhs);                                 \
788
144k
    return *this;                                                               \
789
144k
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator-=<unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator-=<int>(int)
Unexecuted instantiation: mozilla::CheckedInt<long>& mozilla::CheckedInt<long>::operator+=<unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator*=<unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator+=<unsigned long>(unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<int>& mozilla::CheckedInt<int>::operator/=<int>(int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator*=<unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<long>& mozilla::CheckedInt<long>::operator/=<unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator*=<unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator+=<unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned short>& mozilla::CheckedInt<unsigned short>::operator+=<unsigned int>(unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator+=<unsigned short>(unsigned short)
Unexecuted instantiation: mozilla::CheckedInt<long>& mozilla::CheckedInt<long>::operator*=<int>(int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator+=<long>(long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long>& mozilla::CheckedInt<unsigned long>::operator+=<unsigned char>(unsigned char)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator+=<unsigned char>(unsigned char)
Unexecuted instantiation: mozilla::CheckedInt<long>& mozilla::CheckedInt<long>::operator-=<int>(int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>& mozilla::CheckedInt<unsigned int>::operator-=<unsigned long>(unsigned long)
790
  template<typename T>                                                          \
791
  CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(const CheckedInt<T>& aRhs) \
792
0
  {                                                                             \
793
0
    *this = *this OP aRhs;                                                      \
794
0
    return *this;                                                               \
795
0
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>::operator+=(mozilla::CheckedInt<unsigned int> const&)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int>::operator*=(mozilla::CheckedInt<unsigned int> const&)
Unexecuted instantiation: mozilla::CheckedInt<int>::operator+=(mozilla::CheckedInt<int> const&)
796
  template<typename T, typename U>                                              \
797
  inline CheckedInt<T> operator OP(const CheckedInt<T>& aLhs, U aRhs)           \
798
5.30M
  {                                                                             \
799
5.30M
    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
800
5.30M
  }                                                                             \
mozilla::CheckedInt<unsigned long> mozilla::operator*<unsigned long, unsigned long>(mozilla::CheckedInt<unsigned long> const&, unsigned long)
Line
Count
Source
798
7.14k
  {                                                                             \
799
7.14k
    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
800
7.14k
  }                                                                             \
mozilla::CheckedInt<long> mozilla::operator+<long, long>(mozilla::CheckedInt<long> const&, long)
Line
Count
Source
798
98
  {                                                                             \
799
98
    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
800
98
  }                                                                             \
mozilla::CheckedInt<unsigned int> mozilla::operator*<unsigned int, unsigned long>(mozilla::CheckedInt<unsigned int> const&, unsigned long)
Line
Count
Source
798
1.01M
  {                                                                             \
799
1.01M
    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
800
1.01M
  }                                                                             \
mozilla::CheckedInt<int> mozilla::operator+<int, int>(mozilla::CheckedInt<int> const&, int)
Line
Count
Source
798
3.42k
  {                                                                             \
799
3.42k
    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
800
3.42k
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator+<long, int>(mozilla::CheckedInt<long> const&, int)
mozilla::CheckedInt<unsigned long> mozilla::operator+<unsigned long, int>(mozilla::CheckedInt<unsigned long> const&, int)
Line
Count
Source
798
7.14k
  {                                                                             \
799
7.14k
    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
800
7.14k
  }                                                                             \
mozilla::CheckedInt<unsigned int> mozilla::operator*<unsigned int, int>(mozilla::CheckedInt<unsigned int> const&, int)
Line
Count
Source
798
1.01M
  {                                                                             \
799
1.01M
    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
800
1.01M
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator+<unsigned int, unsigned long>(mozilla::CheckedInt<unsigned int> const&, unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator+<unsigned int, unsigned int>(mozilla::CheckedInt<unsigned int> const&, unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator*<unsigned int, unsigned int>(mozilla::CheckedInt<unsigned int> const&, unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator/<long, int>(mozilla::CheckedInt<long> const&, int)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator%<long, int>(mozilla::CheckedInt<long> const&, int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long> mozilla::operator*<unsigned long, unsigned int>(mozilla::CheckedInt<unsigned long> const&, unsigned int)
mozilla::CheckedInt<unsigned int> mozilla::operator+<unsigned int, int>(mozilla::CheckedInt<unsigned int> const&, int)
Line
Count
Source
798
3.24M
  {                                                                             \
799
3.24M
    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
800
3.24M
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator/<unsigned int, int>(mozilla::CheckedInt<unsigned int> const&, int)
Unexecuted instantiation: mozilla::CheckedInt<int> mozilla::operator*<int, unsigned long>(mozilla::CheckedInt<int> const&, unsigned long)
mozilla::CheckedInt<int> mozilla::operator*<int, int>(mozilla::CheckedInt<int> const&, int)
Line
Count
Source
798
15
  {                                                                             \
799
15
    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
800
15
  }                                                                             \
Unexecuted instantiation: mozilla::CheckedInt<unsigned long> mozilla::operator+<unsigned long, unsigned long>(mozilla::CheckedInt<unsigned long> const&, unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<int> mozilla::operator*<int, unsigned int>(mozilla::CheckedInt<int> const&, unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator*<unsigned int, unsigned short>(mozilla::CheckedInt<unsigned int> const&, unsigned short)
Unexecuted instantiation: mozilla::CheckedInt<unsigned long> mozilla::operator+<unsigned long, long>(mozilla::CheckedInt<unsigned long> const&, long)
Unexecuted instantiation: mozilla::CheckedInt<int> mozilla::operator-<int, int>(mozilla::CheckedInt<int> const&, int)
Unexecuted instantiation: mozilla::CheckedInt<int> mozilla::operator+<int, unsigned int>(mozilla::CheckedInt<int> const&, unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator*<unsigned int, unsigned char>(mozilla::CheckedInt<unsigned int> const&, unsigned char)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator/<unsigned int, unsigned int>(mozilla::CheckedInt<unsigned int> const&, unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator*<unsigned int, long>(mozilla::CheckedInt<unsigned int> const&, long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator-<unsigned int, int>(mozilla::CheckedInt<unsigned int> const&, int)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator-<unsigned int, long>(mozilla::CheckedInt<unsigned int> const&, long)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator/<unsigned int, unsigned char>(mozilla::CheckedInt<unsigned int> const&, unsigned char)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator+<unsigned int, unsigned char>(mozilla::CheckedInt<unsigned int> const&, unsigned char)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator*<long, long>(mozilla::CheckedInt<long> const&, long)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator/<long, long>(mozilla::CheckedInt<long> const&, long)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator-<long, long>(mozilla::CheckedInt<long> const&, long)
Unexecuted instantiation: mozilla::CheckedInt<int> mozilla::operator/<int, int>(mozilla::CheckedInt<int> const&, int)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator*<long, int>(mozilla::CheckedInt<long> const&, int)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator*<long, unsigned int>(mozilla::CheckedInt<long> const&, unsigned int)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator*<long, unsigned long>(mozilla::CheckedInt<long> const&, unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator+<long, unsigned long>(mozilla::CheckedInt<long> const&, unsigned long)
Unexecuted instantiation: mozilla::CheckedInt<int> mozilla::operator/<int, unsigned int>(mozilla::CheckedInt<int> const&, unsigned int)
801
  template<typename T, typename U>                                              \
802
  inline CheckedInt<T> operator OP(U aLhs, const CheckedInt<T>& aRhs)           \
803
3.42k
  {                                                                             \
804
3.42k
    return castToCheckedInt<T>(aLhs) OP aRhs;                                   \
805
3.42k
  }
mozilla::CheckedInt<int> mozilla::operator*<int, unsigned int>(unsigned int, mozilla::CheckedInt<int> const&)
Line
Count
Source
803
3.42k
  {                                                                             \
804
3.42k
    return castToCheckedInt<T>(aLhs) OP aRhs;                                   \
805
3.42k
  }
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator*<long, unsigned int>(unsigned int, mozilla::CheckedInt<long> const&)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator/<unsigned int, unsigned long>(unsigned long, mozilla::CheckedInt<unsigned int> const&)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator*<unsigned int, unsigned char>(unsigned char, mozilla::CheckedInt<unsigned int> const&)
Unexecuted instantiation: mozilla::CheckedInt<unsigned int> mozilla::operator+<unsigned int, int>(int, mozilla::CheckedInt<unsigned int> const&)
Unexecuted instantiation: mozilla::CheckedInt<long> mozilla::operator+<long, long>(long, mozilla::CheckedInt<long> const&)
806
807
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=)
808
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=)
809
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=)
810
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=)
811
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(%, %=)
812
813
#undef MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS
814
815
template<typename T, typename U>
816
inline bool
817
operator ==(const CheckedInt<T>& aLhs, U aRhs)
818
0
{
819
0
  return aLhs == castToCheckedInt<T>(aRhs);
820
0
}
Unexecuted instantiation: bool mozilla::operator==<int, int>(mozilla::CheckedInt<int> const&, int)
Unexecuted instantiation: bool mozilla::operator==<long, int>(mozilla::CheckedInt<long> const&, int)
821
822
template<typename T, typename U>
823
inline bool
824
operator ==(U aLhs, const CheckedInt<T>& aRhs)
825
{
826
  return castToCheckedInt<T>(aLhs) == aRhs;
827
}
828
829
// Convenience typedefs.
830
typedef CheckedInt<int8_t>   CheckedInt8;
831
typedef CheckedInt<uint8_t>  CheckedUint8;
832
typedef CheckedInt<int16_t>  CheckedInt16;
833
typedef CheckedInt<uint16_t> CheckedUint16;
834
typedef CheckedInt<int32_t>  CheckedInt32;
835
typedef CheckedInt<uint32_t> CheckedUint32;
836
typedef CheckedInt<int64_t>  CheckedInt64;
837
typedef CheckedInt<uint64_t> CheckedUint64;
838
839
} // namespace mozilla
840
841
#endif /* mozilla_CheckedInt_h */