Change CheckedArithmetic to not use std::enable_if_t.
[WebKit-https.git] / Source / WTF / wtf / CheckedArithmetic.h
1 /*
2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #include <wtf/Assertions.h>
29
30 #include <limits>
31 #include <stdint.h>
32 #include <type_traits>
33
34 /* Checked<T>
35  *
36  * This class provides a mechanism to perform overflow-safe integer arithmetic
37  * without having to manually ensure that you have all the required bounds checks
38  * directly in your code.
39  *
40  * There are two modes of operation:
41  *  - The default is Checked<T, CrashOnOverflow>, and crashes at the point
42  *    and overflow has occurred.
43  *  - The alternative is Checked<T, RecordOverflow>, which uses an additional
44  *    byte of storage to track whether an overflow has occurred, subsequent
45  *    unchecked operations will crash if an overflow has occured
46  *
47  * It is possible to provide a custom overflow handler, in which case you need
48  * to support these functions:
49  *  - void overflowed();
50  *    This function is called when an operation has produced an overflow.
51  *  - bool hasOverflowed();
52  *    This function must return true if overflowed() has been called on an
53  *    instance and false if it has not.
54  *  - void clearOverflow();
55  *    Used to reset overflow tracking when a value is being overwritten with
56  *    a new value.
57  *
58  * Checked<T> works for all integer types, with the following caveats:
59  *  - Mixing signedness of operands is only supported for types narrower than
60  *    64bits.
61  *  - It does have a performance impact, so tight loops may want to be careful
62  *    when using it.
63  *
64  */
65
66 namespace WTF {
67
68 enum class CheckedState {
69     DidOverflow,
70     DidNotOverflow
71 };
72
73 class AssertNoOverflow {
74 public:
75     static NO_RETURN_DUE_TO_ASSERT void overflowed()
76     {
77         ASSERT_NOT_REACHED();
78     }
79
80     void clearOverflow() { }
81
82     static NO_RETURN_DUE_TO_CRASH void crash()
83     {
84         CRASH();
85     }
86
87 public:
88     constexpr bool hasOverflowed() const { return false; }
89 };
90
91 class ConditionalCrashOnOverflow {
92 public:
93     void overflowed()
94     {
95         m_overflowed = true;
96         if (m_shouldCrashOnOverflow)
97             crash();
98     }
99
100     bool shouldCrashOnOverflow() const { return m_shouldCrashOnOverflow; }
101     void setShouldCrashOnOverflow(bool value) { m_shouldCrashOnOverflow = value; }
102
103     bool hasOverflowed() const { return m_overflowed; }
104     void clearOverflow() { m_overflowed = false; }
105
106     static NO_RETURN_DUE_TO_CRASH void crash()
107     {
108         CRASH();
109     }
110
111 private:
112     bool m_overflowed { false };
113     bool m_shouldCrashOnOverflow { true };
114 };
115
116 class CrashOnOverflow {
117 public:
118     static NO_RETURN_DUE_TO_CRASH void overflowed()
119     {
120         crash();
121     }
122
123     void clearOverflow() { }
124
125     static NO_RETURN_DUE_TO_CRASH void crash()
126     {
127         CRASH();
128     }
129
130 public:
131     bool hasOverflowed() const { return false; }
132 };
133
134 class RecordOverflow {
135 protected:
136     RecordOverflow()
137         : m_overflowed(false)
138     {
139     }
140
141     void clearOverflow()
142     {
143         m_overflowed = false;
144     }
145
146     static NO_RETURN_DUE_TO_CRASH void crash()
147     {
148         CRASH();
149     }
150
151 public:
152     bool hasOverflowed() const { return m_overflowed; }
153     void overflowed() { m_overflowed = true; }
154
155 private:
156     unsigned char m_overflowed;
157 };
158
159 template <typename T, class OverflowHandler = CrashOnOverflow> class Checked;
160 template <typename T> struct RemoveChecked;
161 template <typename T> struct RemoveChecked<Checked<T>>;
162
163 template <typename Target, typename Source, bool isTargetBigger = sizeof(Target) >= sizeof(Source), bool targetSigned = std::numeric_limits<Target>::is_signed, bool sourceSigned = std::numeric_limits<Source>::is_signed> struct BoundsChecker;
164 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, false> {
165     static bool inBounds(Source value)
166     {
167         // Same signedness so implicit type conversion will always increase precision to widest type.
168         return value <= std::numeric_limits<Target>::max();
169     }
170 };
171 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, true> {
172     static bool inBounds(Source value)
173     {
174         // Same signedness so implicit type conversion will always increase precision to widest type.
175         return std::numeric_limits<Target>::min() <= value && value <= std::numeric_limits<Target>::max();
176     }
177 };
178
179 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, true> {
180     static bool inBounds(Source value)
181     {
182         // When converting value to unsigned Source, value will become a big value if value is negative.
183         // Casted value will become bigger than Target::max as Source is bigger than Target.
184         return static_cast<typename std::make_unsigned<Source>::type>(value) <= std::numeric_limits<Target>::max();
185     }
186 };
187
188 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, false> {
189     static bool inBounds(Source value)
190     {
191         // The unsigned Source type has greater precision than the target so max(Target) -> Source will widen.
192         return value <= static_cast<Source>(std::numeric_limits<Target>::max());
193     }
194 };
195
196 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, false> {
197     static bool inBounds(Source)
198     {
199         // Same sign, greater or same precision.
200         return true;
201     }
202 };
203
204 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, true> {
205     static bool inBounds(Source)
206     {
207         // Same sign, greater or same precision.
208         return true;
209     }
210 };
211
212 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, false> {
213     static bool inBounds(Source value)
214     {
215         // Target is signed with greater or same precision. If strictly greater, it is always safe.
216         if (sizeof(Target) > sizeof(Source))
217             return true;
218         return value <= static_cast<Source>(std::numeric_limits<Target>::max());
219     }
220 };
221
222 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, true> {
223     static bool inBounds(Source value)
224     {
225         // Target is unsigned with greater precision.
226         return value >= 0;
227     }
228 };
229
230 template <typename Target, typename Source> static inline bool isInBounds(Source value)
231 {
232     return BoundsChecker<Target, Source>::inBounds(value);
233 }
234
235 template <typename Target, typename Source> static inline bool convertSafely(Source input, Target& output)
236 {
237     if (!isInBounds<Target>(input))
238         return false;
239     output = static_cast<Target>(input);
240     return true;
241 }
242
243 template <typename T> struct RemoveChecked {
244     typedef T CleanType;
245     static const CleanType DefaultValue = 0;    
246 };
247
248 template <typename T> struct RemoveChecked<Checked<T, ConditionalCrashOnOverflow>> {
249     using CleanType = typename RemoveChecked<T>::CleanType;
250     static const CleanType DefaultValue = 0;
251 };
252
253 template <typename T> struct RemoveChecked<Checked<T, CrashOnOverflow>> {
254     typedef typename RemoveChecked<T>::CleanType CleanType;
255     static const CleanType DefaultValue = 0;
256 };
257
258 template <typename T> struct RemoveChecked<Checked<T, RecordOverflow>> {
259     typedef typename RemoveChecked<T>::CleanType CleanType;
260     static const CleanType DefaultValue = 0;
261 };
262
263 // The ResultBase and SignednessSelector are used to workaround typeof not being
264 // available in MSVC
265 template <typename U, typename V, bool uIsBigger = (sizeof(U) > sizeof(V)), bool sameSize = (sizeof(U) == sizeof(V))> struct ResultBase;
266 template <typename U, typename V> struct ResultBase<U, V, true, false> {
267     typedef U ResultType;
268 };
269
270 template <typename U, typename V> struct ResultBase<U, V, false, false> {
271     typedef V ResultType;
272 };
273
274 template <typename U> struct ResultBase<U, U, false, true> {
275     typedef U ResultType;
276 };
277
278 template <typename U, typename V, bool uIsSigned = std::numeric_limits<U>::is_signed, bool vIsSigned = std::numeric_limits<V>::is_signed> struct SignednessSelector;
279 template <typename U, typename V> struct SignednessSelector<U, V, true, true> {
280     typedef U ResultType;
281 };
282
283 template <typename U, typename V> struct SignednessSelector<U, V, false, false> {
284     typedef U ResultType;
285 };
286
287 template <typename U, typename V> struct SignednessSelector<U, V, true, false> {
288     typedef V ResultType;
289 };
290
291 template <typename U, typename V> struct SignednessSelector<U, V, false, true> {
292     typedef U ResultType;
293 };
294
295 template <typename U, typename V> struct ResultBase<U, V, false, true> {
296     typedef typename SignednessSelector<U, V>::ResultType ResultType;
297 };
298
299 template <typename U, typename V> struct Result : ResultBase<typename RemoveChecked<U>::CleanType, typename RemoveChecked<V>::CleanType> {
300 };
301
302 template <typename LHS, typename RHS, typename ResultType = typename Result<LHS, RHS>::ResultType, 
303     bool lhsSigned = std::numeric_limits<LHS>::is_signed, bool rhsSigned = std::numeric_limits<RHS>::is_signed> struct ArithmeticOperations;
304
305 template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, true, true> {
306     // LHS and RHS are signed types
307
308     // Helper function
309     static inline bool signsMatch(LHS lhs, RHS rhs)
310     {
311         return (lhs ^ rhs) >= 0;
312     }
313
314     static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
315     {
316 #if COMPILER(GCC_COMPATIBLE)
317         ResultType temp;
318         if (__builtin_add_overflow(lhs, rhs, &temp))
319             return false;
320         result = temp;
321         return true;
322 #else
323         if (signsMatch(lhs, rhs)) {
324             if (lhs >= 0) {
325                 if ((std::numeric_limits<ResultType>::max() - rhs) < lhs)
326                     return false;
327             } else {
328                 ResultType temp = lhs - std::numeric_limits<ResultType>::min();
329                 if (rhs < -temp)
330                     return false;
331             }
332         } // if the signs do not match this operation can't overflow
333         result = lhs + rhs;
334         return true;
335 #endif
336     }
337
338     static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
339     {
340 #if COMPILER(GCC_COMPATIBLE)
341         ResultType temp;
342         if (__builtin_sub_overflow(lhs, rhs, &temp))
343             return false;
344         result = temp;
345         return true;
346 #else
347         if (!signsMatch(lhs, rhs)) {
348             if (lhs >= 0) {
349                 if (lhs > std::numeric_limits<ResultType>::max() + rhs)
350                     return false;
351             } else {
352                 if (rhs > std::numeric_limits<ResultType>::max() + lhs)
353                     return false;
354             }
355         } // if the signs match this operation can't overflow
356         result = lhs - rhs;
357         return true;
358 #endif
359     }
360
361     static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
362     {
363 #if COMPILER(GCC_COMPATIBLE)
364         ResultType temp;
365         if (__builtin_mul_overflow(lhs, rhs, &temp))
366             return false;
367         result = temp;
368         return true;
369 #else
370         if (signsMatch(lhs, rhs)) {
371             if (lhs >= 0) {
372                 if (lhs && (std::numeric_limits<ResultType>::max() / lhs) < rhs)
373                     return false;
374             } else {
375                 if (static_cast<ResultType>(lhs) == std::numeric_limits<ResultType>::min() || static_cast<ResultType>(rhs) == std::numeric_limits<ResultType>::min())
376                     return false;
377                 if ((std::numeric_limits<ResultType>::max() / -lhs) < -rhs)
378                     return false;
379             }
380         } else {
381             if (lhs < 0) {
382                 if (rhs && lhs < (std::numeric_limits<ResultType>::min() / rhs))
383                     return false;
384             } else {
385                 if (lhs && rhs < (std::numeric_limits<ResultType>::min() / lhs))
386                     return false;
387             }
388         }
389         result = lhs * rhs;
390         return true;
391 #endif
392     }
393
394     static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
395
396 };
397
398 template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, false, false> {
399     // LHS and RHS are unsigned types so bounds checks are nice and easy
400     static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
401     {
402 #if COMPILER(GCC_COMPATIBLE)
403         ResultType temp;
404         if (__builtin_add_overflow(lhs, rhs, &temp))
405             return false;
406         result = temp;
407         return true;
408 #else
409         ResultType temp = lhs + rhs;
410         if (temp < lhs)
411             return false;
412         result = temp;
413         return true;
414 #endif
415     }
416
417     static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
418     {
419 #if COMPILER(GCC_COMPATIBLE)
420         ResultType temp;
421         if (__builtin_sub_overflow(lhs, rhs, &temp))
422             return false;
423         result = temp;
424         return true;
425 #else
426         ResultType temp = lhs - rhs;
427         if (temp > lhs)
428             return false;
429         result = temp;
430         return true;
431 #endif
432     }
433
434     static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
435     {
436 #if COMPILER(GCC_COMPATIBLE)
437         ResultType temp;
438         if (__builtin_mul_overflow(lhs, rhs, &temp))
439             return false;
440         result = temp;
441         return true;
442 #else
443         if (!lhs || !rhs) {
444             result = 0;
445             return true;
446         }
447         if (std::numeric_limits<ResultType>::max() / lhs < rhs)
448             return false;
449         result = lhs * rhs;
450         return true;
451 #endif
452     }
453
454     static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
455
456 };
457
458 template <typename ResultType> struct ArithmeticOperations<int, unsigned, ResultType, true, false> {
459     static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
460     {
461 #if COMPILER(GCC_COMPATIBLE)
462         ResultType temp;
463         if (__builtin_add_overflow(lhs, rhs, &temp))
464             return false;
465         result = temp;
466         return true;
467 #else
468         int64_t temp = lhs + rhs;
469         if (temp < std::numeric_limits<ResultType>::min())
470             return false;
471         if (temp > std::numeric_limits<ResultType>::max())
472             return false;
473         result = static_cast<ResultType>(temp);
474         return true;
475 #endif
476     }
477     
478     static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
479     {
480 #if COMPILER(GCC_COMPATIBLE)
481         ResultType temp;
482         if (__builtin_sub_overflow(lhs, rhs, &temp))
483             return false;
484         result = temp;
485         return true;
486 #else
487         int64_t temp = lhs - rhs;
488         if (temp < std::numeric_limits<ResultType>::min())
489             return false;
490         if (temp > std::numeric_limits<ResultType>::max())
491             return false;
492         result = static_cast<ResultType>(temp);
493         return true;
494 #endif
495     }
496
497     static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
498     {
499 #if COMPILER(GCC_COMPATIBLE)
500         ResultType temp;
501         if (__builtin_mul_overflow(lhs, rhs, &temp))
502             return false;
503         result = temp;
504         return true;
505 #else
506         int64_t temp = lhs * rhs;
507         if (temp < std::numeric_limits<ResultType>::min())
508             return false;
509         if (temp > std::numeric_limits<ResultType>::max())
510             return false;
511         result = static_cast<ResultType>(temp);
512         return true;
513 #endif
514     }
515
516     static inline bool equals(int lhs, unsigned rhs)
517     {
518         return static_cast<int64_t>(lhs) == static_cast<int64_t>(rhs);
519     }
520 };
521
522 template <typename ResultType> struct ArithmeticOperations<unsigned, int, ResultType, false, true> {
523     static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
524     {
525         return ArithmeticOperations<int, unsigned, ResultType>::add(rhs, lhs, result);
526     }
527     
528     static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
529     {
530         return ArithmeticOperations<int, unsigned, ResultType>::sub(lhs, rhs, result);
531     }
532
533     static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
534     {
535         return ArithmeticOperations<int, unsigned, ResultType>::multiply(lhs, rhs, result);
536     }
537
538     static inline bool equals(unsigned lhs, int rhs)
539     {
540         return ArithmeticOperations<int, unsigned, ResultType>::equals(rhs, lhs);
541     }
542 };
543
544 template <class OverflowHandler, typename = typename std::enable_if<!std::is_scalar<OverflowHandler>::value>::type>
545 inline constexpr bool observesOverflow() { return true; }
546
547 template <>
548 inline constexpr bool observesOverflow<AssertNoOverflow>() { return !ASSERT_DISABLED; }
549
550 template <typename U, typename V, typename R> static inline bool safeAdd(U lhs, V rhs, R& result)
551 {
552     return ArithmeticOperations<U, V, R>::add(lhs, rhs, result);
553     return true;
554 }
555
556 template <class OverflowHandler, typename U, typename V, typename R, typename = typename std::enable_if<!std::is_scalar<OverflowHandler>::value>::type>
557 static inline bool safeAdd(U lhs, V rhs, R& result)
558 {
559     if (observesOverflow<OverflowHandler>())
560         return safeAdd(lhs, rhs, result);
561     result = lhs + rhs;
562     return true;
563 }
564
565 template <typename U, typename V, typename R> static inline bool safeSub(U lhs, V rhs, R& result)
566 {
567     return ArithmeticOperations<U, V, R>::sub(lhs, rhs, result);
568 }
569
570 template <class OverflowHandler, typename U, typename V, typename R, typename = typename std::enable_if<!std::is_scalar<OverflowHandler>::value>::type>
571 static inline bool safeSub(U lhs, V rhs, R& result)
572 {
573     if (observesOverflow<OverflowHandler>())
574         return safeSub(lhs, rhs, result);
575     result = lhs - rhs;
576     return true;
577 }
578
579 template <typename U, typename V, typename R> static inline bool safeMultiply(U lhs, V rhs, R& result)
580 {
581     return ArithmeticOperations<U, V, R>::multiply(lhs, rhs, result);
582 }
583
584 template <class OverflowHandler, typename U, typename V, typename R, typename = typename std::enable_if<!std::is_scalar<OverflowHandler>::value>::type>
585 static inline bool safeMultiply(U lhs, V rhs, R& result)
586 {
587     if (observesOverflow<OverflowHandler>())
588         return safeMultiply(lhs, rhs, result);
589     result = lhs * rhs;
590     return true;
591 }
592
593 template <typename U, typename V> static inline bool safeEquals(U lhs, V rhs)
594 {
595     return ArithmeticOperations<U, V>::equals(lhs, rhs);
596 }
597
598 enum ResultOverflowedTag { ResultOverflowed };
599     
600 template <typename T, class OverflowHandler> class Checked : public OverflowHandler {
601 public:
602     template <typename _T, class _OverflowHandler> friend class Checked;
603     Checked()
604         : m_value(0)
605     {
606     }
607
608     Checked(ResultOverflowedTag)
609         : m_value(0)
610     {
611         this->overflowed();
612     }
613
614     template <typename U> Checked(U value)
615     {
616         if (!isInBounds<T>(value))
617             this->overflowed();
618         m_value = static_cast<T>(value);
619     }
620     
621     template <typename V> Checked(const Checked<T, V>& rhs)
622         : m_value(rhs.m_value)
623     {
624         if (rhs.hasOverflowed())
625             this->overflowed();
626     }
627     
628     template <typename U> Checked(const Checked<U, OverflowHandler>& rhs)
629         : OverflowHandler(rhs)
630     {
631         if (!isInBounds<T>(rhs.m_value))
632             this->overflowed();
633         m_value = static_cast<T>(rhs.m_value);
634     }
635     
636     template <typename U, typename V> Checked(const Checked<U, V>& rhs)
637     {
638         if (rhs.hasOverflowed())
639             this->overflowed();
640         if (!isInBounds<T>(rhs.m_value))
641             this->overflowed();
642         m_value = static_cast<T>(rhs.m_value);
643     }
644     
645     const Checked& operator=(Checked rhs)
646     {
647         this->clearOverflow();
648         if (rhs.hasOverflowed())
649             this->overflowed();
650         m_value = static_cast<T>(rhs.m_value);
651         return *this;
652     }
653     
654     template <typename U> const Checked& operator=(U value)
655     {
656         return *this = Checked(value);
657     }
658     
659     template <typename U, typename V> const Checked& operator=(const Checked<U, V>& rhs)
660     {
661         return *this = Checked(rhs);
662     }
663     
664     // prefix
665     const Checked& operator++()
666     {
667         if (m_value == std::numeric_limits<T>::max())
668             this->overflowed();
669         m_value++;
670         return *this;
671     }
672     
673     const Checked& operator--()
674     {
675         if (m_value == std::numeric_limits<T>::min())
676             this->overflowed();
677         m_value--;
678         return *this;
679     }
680     
681     // postfix operators
682     const Checked operator++(int)
683     {
684         if (m_value == std::numeric_limits<T>::max())
685             this->overflowed();
686         return Checked(m_value++);
687     }
688     
689     const Checked operator--(int)
690     {
691         if (m_value == std::numeric_limits<T>::min())
692             this->overflowed();
693         return Checked(m_value--);
694     }
695     
696     // Boolean operators
697     bool operator!() const
698     {
699         if (this->hasOverflowed())
700             this->crash();
701         return !m_value;
702     }
703
704     explicit operator bool() const
705     {
706         if (this->hasOverflowed())
707             this->crash();
708         return m_value;
709     }
710
711     // Value accessors. unsafeGet() will crash if there's been an overflow.
712     template<typename U = T>
713     U unsafeGet() const
714     {
715         if (this->hasOverflowed())
716             this->crash();
717         return static_cast<U>(m_value);
718     }
719     
720     inline CheckedState safeGet(T& value) const WARN_UNUSED_RETURN
721     {
722         value = m_value;
723         if (this->hasOverflowed())
724             return CheckedState::DidOverflow;
725         return CheckedState::DidNotOverflow;
726     }
727
728     // Mutating assignment
729     template <typename U> const Checked operator+=(U rhs)
730     {
731         if (!safeAdd<OverflowHandler>(m_value, rhs, m_value))
732             this->overflowed();
733         return *this;
734     }
735
736     template <typename U> const Checked operator-=(U rhs)
737     {
738         if (!safeSub<OverflowHandler>(m_value, rhs, m_value))
739             this->overflowed();
740         return *this;
741     }
742
743     template <typename U> const Checked operator*=(U rhs)
744     {
745         if (!safeMultiply<OverflowHandler>(m_value, rhs, m_value))
746             this->overflowed();
747         return *this;
748     }
749
750     const Checked operator*=(double rhs)
751     {
752         double result = rhs * m_value;
753         // Handle +/- infinity and NaN
754         if (!(std::numeric_limits<T>::min() <= result && std::numeric_limits<T>::max() >= result))
755             this->overflowed();
756         m_value = (T)result;
757         return *this;
758     }
759
760     const Checked operator*=(float rhs)
761     {
762         return *this *= (double)rhs;
763     }
764     
765     template <typename U, typename V> const Checked operator+=(Checked<U, V> rhs)
766     {
767         if (rhs.hasOverflowed())
768             this->overflowed();
769         return *this += rhs.m_value;
770     }
771
772     template <typename U, typename V> const Checked operator-=(Checked<U, V> rhs)
773     {
774         if (rhs.hasOverflowed())
775             this->overflowed();
776         return *this -= rhs.m_value;
777     }
778
779     template <typename U, typename V> const Checked operator*=(Checked<U, V> rhs)
780     {
781         if (rhs.hasOverflowed())
782             this->overflowed();
783         return *this *= rhs.m_value;
784     }
785
786     // Equality comparisons
787     template <typename V> bool operator==(Checked<T, V> rhs)
788     {
789         return unsafeGet() == rhs.unsafeGet();
790     }
791
792     template <typename U> bool operator==(U rhs)
793     {
794         if (this->hasOverflowed())
795             this->crash();
796         return safeEquals(m_value, rhs);
797     }
798     
799     template <typename U, typename V> const Checked operator==(Checked<U, V> rhs)
800     {
801         return unsafeGet() == Checked(rhs.unsafeGet());
802     }
803
804     template <typename U> bool operator!=(U rhs)
805     {
806         return !(*this == rhs);
807     }
808
809     // Other comparisons
810     template <typename V> bool operator<(Checked<T, V> rhs) const
811     {
812         return unsafeGet() < rhs.unsafeGet();
813     }
814
815     bool operator<(T rhs) const
816     {
817         return unsafeGet() < rhs;
818     }
819
820     template <typename V> bool operator<=(Checked<T, V> rhs) const
821     {
822         return unsafeGet() <= rhs.unsafeGet();
823     }
824
825     bool operator<=(T rhs) const
826     {
827         return unsafeGet() <= rhs;
828     }
829
830     template <typename V> bool operator>(Checked<T, V> rhs) const
831     {
832         return unsafeGet() > rhs.unsafeGet();
833     }
834
835     bool operator>(T rhs) const
836     {
837         return unsafeGet() > rhs;
838     }
839
840     template <typename V> bool operator>=(Checked<T, V> rhs) const
841     {
842         return unsafeGet() >= rhs.unsafeGet();
843     }
844
845     bool operator>=(T rhs) const
846     {
847         return unsafeGet() >= rhs;
848     }
849
850 private:
851     // Disallow implicit conversion of floating point to integer types
852     Checked(float);
853     Checked(double);
854     void operator=(float);
855     void operator=(double);
856     void operator+=(float);
857     void operator+=(double);
858     void operator-=(float);
859     void operator-=(double);
860     T m_value;
861 };
862
863 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
864 {
865     U x = 0;
866     V y = 0;
867     bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow;
868     typename Result<U, V>::ResultType result = 0;
869     overflowed |= !safeAdd<OverflowHandler>(x, y, result);
870     if (overflowed)
871         return ResultOverflowed;
872     return result;
873 }
874
875 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
876 {
877     U x = 0;
878     V y = 0;
879     bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow;
880     typename Result<U, V>::ResultType result = 0;
881     overflowed |= !safeSub<OverflowHandler>(x, y, result);
882     if (overflowed)
883         return ResultOverflowed;
884     return result;
885 }
886
887 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
888 {
889     U x = 0;
890     V y = 0;
891     bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow;
892     typename Result<U, V>::ResultType result = 0;
893     overflowed |= !safeMultiply<OverflowHandler>(x, y, result);
894     if (overflowed)
895         return ResultOverflowed;
896     return result;
897 }
898
899 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, V rhs)
900 {
901     return lhs + Checked<V, OverflowHandler>(rhs);
902 }
903
904 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, V rhs)
905 {
906     return lhs - Checked<V, OverflowHandler>(rhs);
907 }
908
909 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, V rhs)
910 {
911     return lhs * Checked<V, OverflowHandler>(rhs);
912 }
913
914 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(U lhs, Checked<V, OverflowHandler> rhs)
915 {
916     return Checked<U, OverflowHandler>(lhs) + rhs;
917 }
918
919 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(U lhs, Checked<V, OverflowHandler> rhs)
920 {
921     return Checked<U, OverflowHandler>(lhs) - rhs;
922 }
923
924 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(U lhs, Checked<V, OverflowHandler> rhs)
925 {
926     return Checked<U, OverflowHandler>(lhs) * rhs;
927 }
928
929 // Convenience typedefs.
930 typedef Checked<int8_t, RecordOverflow> CheckedInt8;
931 typedef Checked<uint8_t, RecordOverflow> CheckedUint8;
932 typedef Checked<int16_t, RecordOverflow> CheckedInt16;
933 typedef Checked<uint16_t, RecordOverflow> CheckedUint16;
934 typedef Checked<int32_t, RecordOverflow> CheckedInt32;
935 typedef Checked<uint32_t, RecordOverflow> CheckedUint32;
936 typedef Checked<int64_t, RecordOverflow> CheckedInt64;
937 typedef Checked<uint64_t, RecordOverflow> CheckedUint64;
938 typedef Checked<size_t, RecordOverflow> CheckedSize;
939
940 template<typename T, typename U>
941 Checked<T, RecordOverflow> checkedSum(U value)
942 {
943     return Checked<T, RecordOverflow>(value);
944 }
945 template<typename T, typename U, typename... Args>
946 Checked<T, RecordOverflow> checkedSum(U value, Args... args)
947 {
948     return Checked<T, RecordOverflow>(value) + checkedSum<T>(args...);
949 }
950
951 // Sometimes, you just want to check if some math would overflow - the code to do the math is
952 // already in place, and you want to guard it.
953
954 template<typename T, typename... Args> bool sumOverflows(Args... args)
955 {
956     return checkedSum<T>(args...).hasOverflowed();
957 }
958
959 template<typename T, typename U> bool differenceOverflows(U left, U right)
960 {
961     return (Checked<T, RecordOverflow>(left) - Checked<T, RecordOverflow>(right)).hasOverflowed();
962 }
963
964 template<typename T, typename U>
965 Checked<T, RecordOverflow> checkedProduct(U value)
966 {
967     return Checked<T, RecordOverflow>(value);
968 }
969 template<typename T, typename U, typename... Args>
970 Checked<T, RecordOverflow> checkedProduct(U value, Args... args)
971 {
972     return Checked<T, RecordOverflow>(value) * checkedProduct<T>(args...);
973 }
974
975 // Sometimes, you just want to check if some math would overflow - the code to do the math is
976 // already in place, and you want to guard it.
977
978 template<typename T, typename... Args> bool productOverflows(Args... args)
979 {
980     return checkedProduct<T>(args...).hasOverflowed();
981 }
982
983 }
984
985 using WTF::AssertNoOverflow;
986 using WTF::Checked;
987 using WTF::CheckedState;
988 using WTF::CheckedInt8;
989 using WTF::CheckedUint8;
990 using WTF::CheckedInt16;
991 using WTF::CheckedUint16;
992 using WTF::CheckedInt32;
993 using WTF::CheckedUint32;
994 using WTF::CheckedInt64;
995 using WTF::CheckedUint64;
996 using WTF::CheckedSize;
997 using WTF::ConditionalCrashOnOverflow;
998 using WTF::CrashOnOverflow;
999 using WTF::RecordOverflow;
1000 using WTF::checkedSum;
1001 using WTF::differenceOverflows;
1002 using WTF::productOverflows;
1003 using WTF::sumOverflows;