/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 */ |