6cc45b329c40f7a0d64b2d062686368583146b54
[WebKit.git] / Source / WTF / wtf / CheckedArithmetic.h
1 /*
2  * Copyright (C) 2011 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 #ifndef CheckedArithmetic_h
27 #define CheckedArithmetic_h
28
29 #include <wtf/Assertions.h>
30
31 #include <limits>
32 #include <stdint.h>
33 #include <type_traits>
34
35 /* Checked<T>
36  *
37  * This class provides a mechanism to perform overflow-safe integer arithmetic
38  * without having to manually ensure that you have all the required bounds checks
39  * directly in your code.
40  *
41  * There are two modes of operation:
42  *  - The default is Checked<T, CrashOnOverflow>, and crashes at the point
43  *    and overflow has occurred.
44  *  - The alternative is Checked<T, RecordOverflow>, which uses an additional
45  *    byte of storage to track whether an overflow has occurred, subsequent
46  *    unchecked operations will crash if an overflow has occured
47  *
48  * It is possible to provide a custom overflow handler, in which case you need
49  * to support these functions:
50  *  - void overflowed();
51  *    This function is called when an operation has produced an overflow.
52  *  - bool hasOverflowed();
53  *    This function must return true if overflowed() has been called on an
54  *    instance and false if it has not.
55  *  - void clearOverflow();
56  *    Used to reset overflow tracking when a value is being overwritten with
57  *    a new value.
58  *
59  * Checked<T> works for all integer types, with the following caveats:
60  *  - Mixing signedness of operands is only supported for types narrower than
61  *    64bits.
62  *  - It does have a performance impact, so tight loops may want to be careful
63  *    when using it.
64  *
65  */
66
67 namespace WTF {
68
69 enum class CheckedState {
70     DidOverflow,
71     DidNotOverflow
72 };
73
74 class CrashOnOverflow {
75 public:
76     static NO_RETURN_DUE_TO_CRASH void overflowed()
77     {
78         crash();
79     }
80
81     void clearOverflow() { }
82
83     static NO_RETURN_DUE_TO_CRASH void crash()
84     {
85         CRASH();
86     }
87
88 public:
89     bool hasOverflowed() const { return false; }
90 };
91
92 class RecordOverflow {
93 protected:
94     RecordOverflow()
95         : m_overflowed(false)
96     {
97     }
98
99     void overflowed()
100     {
101         m_overflowed = true;
102     }
103
104     void clearOverflow()
105     {
106         m_overflowed = false;
107     }
108
109     static NO_RETURN_DUE_TO_CRASH void crash()
110     {
111         CRASH();
112     }
113
114 public:
115     bool hasOverflowed() const { return m_overflowed; }
116
117 private:
118     unsigned char m_overflowed;
119 };
120
121 template <typename T, class OverflowHandler = CrashOnOverflow> class Checked;
122 template <typename T> struct RemoveChecked;
123 template <typename T> struct RemoveChecked<Checked<T>>;
124
125 template <typename Target, typename Source, bool targetSigned = std::numeric_limits<Target>::is_signed, bool sourceSigned = std::numeric_limits<Source>::is_signed> struct BoundsChecker;
126 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false> {
127     static bool inBounds(Source value)
128     {
129         // Same signedness so implicit type conversion will always increase precision
130         // to widest type
131         return value <= std::numeric_limits<Target>::max();
132     }
133 };
134
135 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true> {
136     static bool inBounds(Source value)
137     {
138         // Same signedness so implicit type conversion will always increase precision
139         // to widest type
140         return std::numeric_limits<Target>::min() <= value && value <= std::numeric_limits<Target>::max();
141     }
142 };
143
144 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true> {
145     static bool inBounds(Source value)
146     {
147         // Target is unsigned so any value less than zero is clearly unsafe
148         if (value < 0)
149             return false;
150         // If our (unsigned) Target is the same or greater width we can
151         // convert value to type Target without losing precision
152         if (sizeof(Target) >= sizeof(Source)) 
153             return static_cast<Target>(value) <= std::numeric_limits<Target>::max();
154         // The signed Source type has greater precision than the target so
155         // max(Target) -> Source will widen.
156         return value <= static_cast<Source>(std::numeric_limits<Target>::max());
157     }
158 };
159
160 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false> {
161     static bool inBounds(Source value)
162     {
163         // Signed target with an unsigned source
164         if (sizeof(Target) <= sizeof(Source)) 
165             return value <= static_cast<Source>(std::numeric_limits<Target>::max());
166         // Target is Wider than Source so we're guaranteed to fit any value in
167         // unsigned Source
168         return true;
169     }
170 };
171
172 template <typename Target, typename Source, bool CanElide = std::is_same<Target, Source>::value || (sizeof(Target) > sizeof(Source)) > struct BoundsCheckElider;
173 template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, true> {
174     static bool inBounds(Source) { return true; }
175 };
176 template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, false> : public BoundsChecker<Target, Source> {
177 };
178
179 template <typename Target, typename Source> static inline bool isInBounds(Source value)
180 {
181     return BoundsCheckElider<Target, Source>::inBounds(value);
182 }
183
184 template <typename T> struct RemoveChecked {
185     typedef T CleanType;
186     static const CleanType DefaultValue = 0;    
187 };
188
189 template <typename T> struct RemoveChecked<Checked<T, CrashOnOverflow>> {
190     typedef typename RemoveChecked<T>::CleanType CleanType;
191     static const CleanType DefaultValue = 0;
192 };
193
194 template <typename T> struct RemoveChecked<Checked<T, RecordOverflow>> {
195     typedef typename RemoveChecked<T>::CleanType CleanType;
196     static const CleanType DefaultValue = 0;
197 };
198
199 // The ResultBase and SignednessSelector are used to workaround typeof not being
200 // available in MSVC
201 template <typename U, typename V, bool uIsBigger = (sizeof(U) > sizeof(V)), bool sameSize = (sizeof(U) == sizeof(V))> struct ResultBase;
202 template <typename U, typename V> struct ResultBase<U, V, true, false> {
203     typedef U ResultType;
204 };
205
206 template <typename U, typename V> struct ResultBase<U, V, false, false> {
207     typedef V ResultType;
208 };
209
210 template <typename U> struct ResultBase<U, U, false, true> {
211     typedef U ResultType;
212 };
213
214 template <typename U, typename V, bool uIsSigned = std::numeric_limits<U>::is_signed, bool vIsSigned = std::numeric_limits<V>::is_signed> struct SignednessSelector;
215 template <typename U, typename V> struct SignednessSelector<U, V, true, true> {
216     typedef U ResultType;
217 };
218
219 template <typename U, typename V> struct SignednessSelector<U, V, false, false> {
220     typedef U ResultType;
221 };
222
223 template <typename U, typename V> struct SignednessSelector<U, V, true, false> {
224     typedef V ResultType;
225 };
226
227 template <typename U, typename V> struct SignednessSelector<U, V, false, true> {
228     typedef U ResultType;
229 };
230
231 template <typename U, typename V> struct ResultBase<U, V, false, true> {
232     typedef typename SignednessSelector<U, V>::ResultType ResultType;
233 };
234
235 template <typename U, typename V> struct Result : ResultBase<typename RemoveChecked<U>::CleanType, typename RemoveChecked<V>::CleanType> {
236 };
237
238 template <typename LHS, typename RHS, typename ResultType = typename Result<LHS, RHS>::ResultType, 
239     bool lhsSigned = std::numeric_limits<LHS>::is_signed, bool rhsSigned = std::numeric_limits<RHS>::is_signed> struct ArithmeticOperations;
240
241 template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, true, true> {
242     // LHS and RHS are signed types
243
244     // Helper function
245     static inline bool signsMatch(LHS lhs, RHS rhs)
246     {
247         return (lhs ^ rhs) >= 0;
248     }
249
250     static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
251     {
252         if (signsMatch(lhs, rhs)) {
253             if (lhs >= 0) {
254                 if ((std::numeric_limits<ResultType>::max() - rhs) < lhs)
255                     return false;
256             } else {
257                 ResultType temp = lhs - std::numeric_limits<ResultType>::min();
258                 if (rhs < -temp)
259                     return false;
260             }
261         } // if the signs do not match this operation can't overflow
262         result = lhs + rhs;
263         return true;
264     }
265
266     static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
267     {
268         if (!signsMatch(lhs, rhs)) {
269             if (lhs >= 0) {
270                 if (lhs > std::numeric_limits<ResultType>::max() + rhs)
271                     return false;
272             } else {
273                 if (rhs > std::numeric_limits<ResultType>::max() + lhs)
274                     return false;
275             }
276         } // if the signs match this operation can't overflow
277         result = lhs - rhs;
278         return true;
279     }
280
281     static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
282     {
283         if (signsMatch(lhs, rhs)) {
284             if (lhs >= 0) {
285                 if (lhs && (std::numeric_limits<ResultType>::max() / lhs) < rhs)
286                     return false;
287             } else {
288                 if (static_cast<ResultType>(lhs) == std::numeric_limits<ResultType>::min() || static_cast<ResultType>(rhs) == std::numeric_limits<ResultType>::min())
289                     return false;
290                 if ((std::numeric_limits<ResultType>::max() / -lhs) < -rhs)
291                     return false;
292             }
293         } else {
294             if (lhs < 0) {
295                 if (rhs && lhs < (std::numeric_limits<ResultType>::min() / rhs))
296                     return false;
297             } else {
298                 if (lhs && rhs < (std::numeric_limits<ResultType>::min() / lhs))
299                     return false;
300             }
301         }
302         result = lhs * rhs;
303         return true;
304     }
305
306     static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
307
308 };
309
310 template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, false, false> {
311     // LHS and RHS are unsigned types so bounds checks are nice and easy
312     static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
313     {
314         ResultType temp = lhs + rhs;
315         if (temp < lhs)
316             return false;
317         result = temp;
318         return true;
319     }
320
321     static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
322     {
323         ResultType temp = lhs - rhs;
324         if (temp > lhs)
325             return false;
326         result = temp;
327         return true;
328     }
329
330     static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
331     {
332         if (!lhs || !rhs) {
333             result = 0;
334             return true;
335         }
336         if (std::numeric_limits<ResultType>::max() / lhs < rhs)
337             return false;
338         result = lhs * rhs;
339         return true;
340     }
341
342     static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
343
344 };
345
346 template <typename ResultType> struct ArithmeticOperations<int, unsigned, ResultType, true, false> {
347     static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
348     {
349         int64_t temp = lhs + rhs;
350         if (temp < std::numeric_limits<ResultType>::min())
351             return false;
352         if (temp > std::numeric_limits<ResultType>::max())
353             return false;
354         result = static_cast<ResultType>(temp);
355         return true;
356     }
357     
358     static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
359     {
360         int64_t temp = lhs - rhs;
361         if (temp < std::numeric_limits<ResultType>::min())
362             return false;
363         if (temp > std::numeric_limits<ResultType>::max())
364             return false;
365         result = static_cast<ResultType>(temp);
366         return true;
367     }
368
369     static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
370     {
371         int64_t temp = lhs * rhs;
372         if (temp < std::numeric_limits<ResultType>::min())
373             return false;
374         if (temp > std::numeric_limits<ResultType>::max())
375             return false;
376         result = static_cast<ResultType>(temp);
377         return true;
378     }
379
380     static inline bool equals(int lhs, unsigned rhs)
381     {
382         return static_cast<int64_t>(lhs) == static_cast<int64_t>(rhs);
383     }
384 };
385
386 template <typename ResultType> struct ArithmeticOperations<unsigned, int, ResultType, false, true> {
387     static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
388     {
389         return ArithmeticOperations<int, unsigned, ResultType>::add(rhs, lhs, result);
390     }
391     
392     static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
393     {
394         return ArithmeticOperations<int, unsigned, ResultType>::sub(lhs, rhs, result);
395     }
396
397     static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
398     {
399         return ArithmeticOperations<int, unsigned, ResultType>::multiply(rhs, lhs, result);
400     }
401
402     static inline bool equals(unsigned lhs, int rhs)
403     {
404         return ArithmeticOperations<int, unsigned, ResultType>::equals(rhs, lhs);
405     }
406 };
407
408 template <typename U, typename V, typename R> static inline bool safeAdd(U lhs, V rhs, R& result)
409 {
410     return ArithmeticOperations<U, V, R>::add(lhs, rhs, result);
411 }
412
413 template <typename U, typename V, typename R> static inline bool safeSub(U lhs, V rhs, R& result)
414 {
415     return ArithmeticOperations<U, V, R>::sub(lhs, rhs, result);
416 }
417
418 template <typename U, typename V, typename R> static inline bool safeMultiply(U lhs, V rhs, R& result)
419 {
420     return ArithmeticOperations<U, V, R>::multiply(lhs, rhs, result);
421 }
422
423 template <typename U, typename V> static inline bool safeEquals(U lhs, V rhs)
424 {
425     return ArithmeticOperations<U, V>::equals(lhs, rhs);
426 }
427
428 enum ResultOverflowedTag { ResultOverflowed };
429     
430 template <typename T, class OverflowHandler> class Checked : public OverflowHandler {
431 public:
432     template <typename _T, class _OverflowHandler> friend class Checked;
433     Checked()
434         : m_value(0)
435     {
436     }
437
438     Checked(ResultOverflowedTag)
439         : m_value(0)
440     {
441         this->overflowed();
442     }
443
444     template <typename U> Checked(U value)
445     {
446         if (!isInBounds<T>(value))
447             this->overflowed();
448         m_value = static_cast<T>(value);
449     }
450     
451     template <typename V> Checked(const Checked<T, V>& rhs)
452         : m_value(rhs.m_value)
453     {
454         if (rhs.hasOverflowed())
455             this->overflowed();
456     }
457     
458     template <typename U> Checked(const Checked<U, OverflowHandler>& rhs)
459         : OverflowHandler(rhs)
460     {
461         if (!isInBounds<T>(rhs.m_value))
462             this->overflowed();
463         m_value = static_cast<T>(rhs.m_value);
464     }
465     
466     template <typename U, typename V> Checked(const Checked<U, V>& rhs)
467     {
468         if (rhs.hasOverflowed())
469             this->overflowed();
470         if (!isInBounds<T>(rhs.m_value))
471             this->overflowed();
472         m_value = static_cast<T>(rhs.m_value);
473     }
474     
475     const Checked& operator=(Checked rhs)
476     {
477         this->clearOverflow();
478         if (rhs.hasOverflowed())
479             this->overflowed();
480         m_value = static_cast<T>(rhs.m_value);
481         return *this;
482     }
483     
484     template <typename U> const Checked& operator=(U value)
485     {
486         return *this = Checked(value);
487     }
488     
489     template <typename U, typename V> const Checked& operator=(const Checked<U, V>& rhs)
490     {
491         return *this = Checked(rhs);
492     }
493     
494     // prefix
495     const Checked& operator++()
496     {
497         if (m_value == std::numeric_limits<T>::max())
498             this->overflowed();
499         m_value++;
500         return *this;
501     }
502     
503     const Checked& operator--()
504     {
505         if (m_value == std::numeric_limits<T>::min())
506             this->overflowed();
507         m_value--;
508         return *this;
509     }
510     
511     // postfix operators
512     const Checked operator++(int)
513     {
514         if (m_value == std::numeric_limits<T>::max())
515             this->overflowed();
516         return Checked(m_value++);
517     }
518     
519     const Checked operator--(int)
520     {
521         if (m_value == std::numeric_limits<T>::min())
522             this->overflowed();
523         return Checked(m_value--);
524     }
525     
526     // Boolean operators
527     bool operator!() const
528     {
529         if (this->hasOverflowed())
530             this->crash();
531         return !m_value;
532     }
533
534     explicit operator bool() const
535     {
536         if (this->hasOverflowed())
537             this->crash();
538         return m_value;
539     }
540
541     // Value accessors. unsafeGet() will crash if there's been an overflow.
542     T unsafeGet() const
543     {
544         if (this->hasOverflowed())
545             this->crash();
546         return m_value;
547     }
548     
549     inline CheckedState safeGet(T& value) const WARN_UNUSED_RETURN
550     {
551         value = m_value;
552         if (this->hasOverflowed())
553             return CheckedState::DidOverflow;
554         return CheckedState::DidNotOverflow;
555     }
556
557     // Mutating assignment
558     template <typename U> const Checked operator+=(U rhs)
559     {
560         if (!safeAdd(m_value, rhs, m_value))
561             this->overflowed();
562         return *this;
563     }
564
565     template <typename U> const Checked operator-=(U rhs)
566     {
567         if (!safeSub(m_value, rhs, m_value))
568             this->overflowed();
569         return *this;
570     }
571
572     template <typename U> const Checked operator*=(U rhs)
573     {
574         if (!safeMultiply(m_value, rhs, m_value))
575             this->overflowed();
576         return *this;
577     }
578
579     const Checked operator*=(double rhs)
580     {
581         double result = rhs * m_value;
582         // Handle +/- infinity and NaN
583         if (!(std::numeric_limits<T>::min() <= result && std::numeric_limits<T>::max() >= result))
584             this->overflowed();
585         m_value = (T)result;
586         return *this;
587     }
588
589     const Checked operator*=(float rhs)
590     {
591         return *this *= (double)rhs;
592     }
593     
594     template <typename U, typename V> const Checked operator+=(Checked<U, V> rhs)
595     {
596         if (rhs.hasOverflowed())
597             this->overflowed();
598         return *this += rhs.m_value;
599     }
600
601     template <typename U, typename V> const Checked operator-=(Checked<U, V> rhs)
602     {
603         if (rhs.hasOverflowed())
604             this->overflowed();
605         return *this -= rhs.m_value;
606     }
607
608     template <typename U, typename V> const Checked operator*=(Checked<U, V> rhs)
609     {
610         if (rhs.hasOverflowed())
611             this->overflowed();
612         return *this *= rhs.m_value;
613     }
614
615     // Equality comparisons
616     template <typename V> bool operator==(Checked<T, V> rhs)
617     {
618         return unsafeGet() == rhs.unsafeGet();
619     }
620
621     template <typename U> bool operator==(U rhs)
622     {
623         if (this->hasOverflowed())
624             this->crash();
625         return safeEquals(m_value, rhs);
626     }
627     
628     template <typename U, typename V> const Checked operator==(Checked<U, V> rhs)
629     {
630         return unsafeGet() == Checked(rhs.unsafeGet());
631     }
632
633     template <typename U> bool operator!=(U rhs)
634     {
635         return !(*this == rhs);
636     }
637
638     // Other comparisons
639     template <typename V> bool operator<(Checked<T, V> rhs) const
640     {
641         return unsafeGet() < rhs.unsafeGet();
642     }
643
644     bool operator<(T rhs) const
645     {
646         return unsafeGet() < rhs;
647     }
648
649     template <typename V> bool operator<=(Checked<T, V> rhs) const
650     {
651         return unsafeGet() <= rhs.unsafeGet();
652     }
653
654     bool operator<=(T rhs) const
655     {
656         return unsafeGet() <= rhs;
657     }
658
659     template <typename V> bool operator>(Checked<T, V> rhs) const
660     {
661         return unsafeGet() > rhs.unsafeGet();
662     }
663
664     bool operator>(T rhs) const
665     {
666         return unsafeGet() > rhs;
667     }
668
669     template <typename V> bool operator>=(Checked<T, V> rhs) const
670     {
671         return unsafeGet() >= rhs.unsafeGet();
672     }
673
674     bool operator>=(T rhs) const
675     {
676         return unsafeGet() >= rhs;
677     }
678
679 private:
680     // Disallow implicit conversion of floating point to integer types
681     Checked(float);
682     Checked(double);
683     void operator=(float);
684     void operator=(double);
685     void operator+=(float);
686     void operator+=(double);
687     void operator-=(float);
688     void operator-=(double);
689     T m_value;
690 };
691
692 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)
693 {
694     U x = 0;
695     V y = 0;
696     bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow;
697     typename Result<U, V>::ResultType result = 0;
698     overflowed |= !safeAdd(x, y, result);
699     if (overflowed)
700         return ResultOverflowed;
701     return result;
702 }
703
704 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)
705 {
706     U x = 0;
707     V y = 0;
708     bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow;
709     typename Result<U, V>::ResultType result = 0;
710     overflowed |= !safeSub(x, y, result);
711     if (overflowed)
712         return ResultOverflowed;
713     return result;
714 }
715
716 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)
717 {
718     U x = 0;
719     V y = 0;
720     bool overflowed = lhs.safeGet(x) == CheckedState::DidOverflow || rhs.safeGet(y) == CheckedState::DidOverflow;
721     typename Result<U, V>::ResultType result = 0;
722     overflowed |= !safeMultiply(x, y, result);
723     if (overflowed)
724         return ResultOverflowed;
725     return result;
726 }
727
728 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, V rhs)
729 {
730     return lhs + Checked<V, OverflowHandler>(rhs);
731 }
732
733 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, V rhs)
734 {
735     return lhs - Checked<V, OverflowHandler>(rhs);
736 }
737
738 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, V rhs)
739 {
740     return lhs * Checked<V, OverflowHandler>(rhs);
741 }
742
743 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(U lhs, Checked<V, OverflowHandler> rhs)
744 {
745     return Checked<U, OverflowHandler>(lhs) + rhs;
746 }
747
748 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(U lhs, Checked<V, OverflowHandler> rhs)
749 {
750     return Checked<U, OverflowHandler>(lhs) - rhs;
751 }
752
753 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(U lhs, Checked<V, OverflowHandler> rhs)
754 {
755     return Checked<U, OverflowHandler>(lhs) * rhs;
756 }
757
758 // Convenience typedefs.
759 typedef Checked<int8_t, RecordOverflow> CheckedInt8;
760 typedef Checked<uint8_t, RecordOverflow> CheckedUint8;
761 typedef Checked<int16_t, RecordOverflow> CheckedInt16;
762 typedef Checked<uint16_t, RecordOverflow> CheckedUint16;
763 typedef Checked<int32_t, RecordOverflow> CheckedInt32;
764 typedef Checked<uint32_t, RecordOverflow> CheckedUint32;
765 typedef Checked<int64_t, RecordOverflow> CheckedInt64;
766 typedef Checked<uint64_t, RecordOverflow> CheckedUint64;
767 typedef Checked<size_t, RecordOverflow> CheckedSize;
768
769 template<typename T, typename U>
770 Checked<T, RecordOverflow> checkedSum(U value)
771 {
772     return Checked<T, RecordOverflow>(value);
773 }
774 template<typename T, typename U, typename... Args>
775 Checked<T, RecordOverflow> checkedSum(U value, Args... args)
776 {
777     return Checked<T, RecordOverflow>(value) + checkedSum<T>(args...);
778 }
779
780 // Sometimes, you just want to check if some math would overflow - the code to do the math is
781 // already in place, and you want to guard it.
782
783 template<typename T, typename... Args> bool sumOverflows(Args... args)
784 {
785     return checkedSum<T>(args...).hasOverflowed();
786 }
787
788 }
789
790 using WTF::Checked;
791 using WTF::CheckedState;
792 using WTF::RecordOverflow;
793 using WTF::CheckedInt8;
794 using WTF::CheckedUint8;
795 using WTF::CheckedInt16;
796 using WTF::CheckedUint16;
797 using WTF::CheckedInt32;
798 using WTF::CheckedUint32;
799 using WTF::CheckedInt64;
800 using WTF::CheckedUint64;
801 using WTF::CheckedSize;
802 using WTF::checkedSum;
803 using WTF::sumOverflows;
804
805 #endif