js/src/yarr/CheckedArithmetic.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  *
     4  * Copyright (C) 2011 Apple Inc. All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions
     8  * are met:
     9  * 1. Redistributions of source code must retain the above copyright
    10  *    notice, this list of conditions and the following disclaimer.
    11  * 2. Redistributions in binary form must reproduce the above copyright
    12  *    notice, this list of conditions and the following disclaimer in the
    13  *    documentation and/or other materials provided with the distribution.
    14  *
    15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
    16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
    19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    26  */
    28 #ifndef yarr_CheckedArithmetic_h
    29 #define yarr_CheckedArithmetic_h
    31 #include "assembler/wtf/Assertions.h"
    33 #include <limits>
    34 #include <stdint.h>
    35 #include "mozilla/TypeTraits.h"
    37 #ifdef _MSC_VER
    38 # undef min
    39 # undef max
    40 #endif
    42 /* Checked<T>
    43  *
    44  * This class provides a mechanism to perform overflow-safe integer arithmetic
    45  * without having to manually ensure that you have all the required bounds checks
    46  * directly in your code.
    47  *
    48  * There are two modes of operation:
    49  *  - The default is Checked<T, CrashOnOverflow>, and crashes at the point
    50  *    and overflow has occurred.
    51  *  - The alternative is Checked<T, RecordOverflow>, which uses an additional
    52  *    byte of storage to track whether an overflow has occurred, subsequent
    53  *    unchecked operations will crash if an overflow has occured
    54  *
    55  * It is possible to provide a custom overflow handler, in which case you need
    56  * to support these functions:
    57  *  - void overflowed();
    58  *    This function is called when an operation has produced an overflow.
    59  *  - bool hasOverflowed();
    60  *    This function must return true if overflowed() has been called on an
    61  *    instance and false if it has not.
    62  *  - void clearOverflow();
    63  *    Used to reset overflow tracking when a value is being overwritten with
    64  *    a new value.
    65  *
    66  * Checked<T> works for all integer types, with the following caveats:
    67  *  - Mixing signedness of operands is only supported for types narrower than
    68  *    64bits.
    69  *  - It does have a performance impact, so tight loops may want to be careful
    70  *    when using it.
    71  *
    72  */
    74 namespace WTF {
    76 class CrashOnOverflow {
    77 protected:
    78     void overflowed()
    79     {
    80         CRASH();
    81     }
    83     void clearOverflow() { }
    85 public:
    86     bool hasOverflowed() const { return false; }
    87 };
    89 class RecordOverflow {
    90 protected:
    91     RecordOverflow()
    92         : m_overflowed(false)
    93     {
    94     }
    96     void overflowed()
    97     {
    98         m_overflowed = true;
    99     }
   101     void clearOverflow()
   102     {
   103         m_overflowed = false;
   104     }
   106 public:
   107     bool hasOverflowed() const { return m_overflowed; }
   109 private:
   110     unsigned char m_overflowed;
   111 };
   113 template <typename T, class OverflowHandler = RecordOverflow> class Checked;
   114 template <typename T> struct RemoveChecked;
   115 template <typename T> struct RemoveChecked<Checked<T> >;
   117 template <typename Target, typename Source, bool targetSigned = ::std::numeric_limits<Target>::is_signed, bool sourceSigned = ::std::numeric_limits<Source>::is_signed> struct BoundsChecker;
   118 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false> {
   119     static bool inBounds(Source value)
   120     {
   121         // Same signedness so implicit type conversion will always increase precision
   122         // to widest type
   123         return value <= ::std::numeric_limits<Target>::max();
   124     }
   125 };
   127 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true> {
   128     static bool inBounds(Source value)
   129     {
   130         // Same signedness so implicit type conversion will always increase precision
   131         // to widest type
   132         return ::std::numeric_limits<Target>::min() <= value && value <= ::std::numeric_limits<Target>::max();
   133     }
   134 };
   136 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true> {
   137     static bool inBounds(Source value)
   138     {
   139         // Target is unsigned so any value less than zero is clearly unsafe
   140         if (value < 0)
   141             return false;
   142         // If our (unsigned) Target is the same or greater width we can
   143         // convert value to type Target without losing precision
   144         if (sizeof(Target) >= sizeof(Source))
   145             return static_cast<Target>(value) <= ::std::numeric_limits<Target>::max();
   146         // The signed Source type has greater precision than the target so
   147         // max(Target) -> Source will widen.
   148         return value <= static_cast<Source>(::std::numeric_limits<Target>::max());
   149     }
   150 };
   152 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false> {
   153     static bool inBounds(Source value)
   154     {
   155         // Signed target with an unsigned source
   156         if (sizeof(Target) <= sizeof(Source))
   157             return value <= static_cast<Source>(::std::numeric_limits<Target>::max());
   158         // Target is Wider than Source so we're guaranteed to fit any value in
   159         // unsigned Source
   160         return true;
   161     }
   162 };
   164 template <typename Target, typename Source, bool SameType = mozilla::IsSame<Target, Source>::value> struct BoundsCheckElider;
   165 template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, true> {
   166     static bool inBounds(Source) { return true; }
   167 };
   168 template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, false> : public BoundsChecker<Target, Source> {
   169 };
   171 template <typename Target, typename Source> static inline bool isInBounds(Source value)
   172 {
   173     return BoundsCheckElider<Target, Source>::inBounds(value);
   174 }
   176 template <typename T> struct RemoveChecked {
   177     typedef T CleanType;
   178     static const CleanType DefaultValue = 0;
   179 };
   181 template <typename T> struct RemoveChecked<Checked<T, CrashOnOverflow> > {
   182     typedef typename RemoveChecked<T>::CleanType CleanType;
   183     static const CleanType DefaultValue = 0;
   184 };
   186 template <typename T> struct RemoveChecked<Checked<T, RecordOverflow> > {
   187     typedef typename RemoveChecked<T>::CleanType CleanType;
   188     static const CleanType DefaultValue = 0;
   189 };
   191 // The ResultBase and SignednessSelector are used to workaround typeof not being
   192 // available in MSVC
   193 template <typename U, typename V, bool uIsBigger = (sizeof(U) > sizeof(V)), bool sameSize = (sizeof(U) == sizeof(V))> struct ResultBase;
   194 template <typename U, typename V> struct ResultBase<U, V, true, false> {
   195     typedef U ResultType;
   196 };
   198 template <typename U, typename V> struct ResultBase<U, V, false, false> {
   199     typedef V ResultType;
   200 };
   202 template <typename U> struct ResultBase<U, U, false, true> {
   203     typedef U ResultType;
   204 };
   206 template <typename U, typename V, bool uIsSigned = ::std::numeric_limits<U>::is_signed, bool vIsSigned = ::std::numeric_limits<V>::is_signed> struct SignednessSelector;
   207 template <typename U, typename V> struct SignednessSelector<U, V, true, true> {
   208     typedef U ResultType;
   209 };
   211 template <typename U, typename V> struct SignednessSelector<U, V, false, false> {
   212     typedef U ResultType;
   213 };
   215 template <typename U, typename V> struct SignednessSelector<U, V, true, false> {
   216     typedef V ResultType;
   217 };
   219 template <typename U, typename V> struct SignednessSelector<U, V, false, true> {
   220     typedef U ResultType;
   221 };
   223 template <typename U, typename V> struct ResultBase<U, V, false, true> {
   224     typedef typename SignednessSelector<U, V>::ResultType ResultType;
   225 };
   227 template <typename U, typename V> struct Result : ResultBase<typename RemoveChecked<U>::CleanType, typename RemoveChecked<V>::CleanType> {
   228 };
   230 template <typename LHS, typename RHS, typename ResultType = typename Result<LHS, RHS>::ResultType,
   231     bool lhsSigned = ::std::numeric_limits<LHS>::is_signed, bool rhsSigned = ::std::numeric_limits<RHS>::is_signed> struct ArithmeticOperations;
   233 template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, true, true> {
   234     // LHS and RHS are signed types
   236     // Helper function
   237     static inline bool signsMatch(LHS lhs, RHS rhs)
   238     {
   239         return (lhs ^ rhs) >= 0;
   240     }
   242     static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
   243     {
   244         if (signsMatch(lhs, rhs)) {
   245             if (lhs >= 0) {
   246                 if ((::std::numeric_limits<ResultType>::max() - rhs) < lhs)
   247                     return false;
   248             } else {
   249                 ResultType temp = lhs - ::std::numeric_limits<ResultType>::min();
   250                 if (rhs < -temp)
   251                     return false;
   252             }
   253         } // if the signs do not match this operation can't overflow
   254         result = lhs + rhs;
   255         return true;
   256     }
   258     static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
   259     {
   260         if (!signsMatch(lhs, rhs)) {
   261             if (lhs >= 0) {
   262                 if (lhs > ::std::numeric_limits<ResultType>::max() + rhs)
   263                     return false;
   264             } else {
   265                 if (rhs > ::std::numeric_limits<ResultType>::max() + lhs)
   266                     return false;
   267             }
   268         } // if the signs match this operation can't overflow
   269         result = lhs - rhs;
   270         return true;
   271     }
   273     static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
   274     {
   275         if (signsMatch(lhs, rhs)) {
   276             if (lhs >= 0) {
   277                 if (lhs && (::std::numeric_limits<ResultType>::max() / lhs) < rhs)
   278                     return false;
   279             } else {
   280                 if (lhs == ::std::numeric_limits<ResultType>::min() || rhs == ::std::numeric_limits<ResultType>::min())
   281                     return false;
   282                 if ((::std::numeric_limits<ResultType>::max() / -lhs) < -rhs)
   283                     return false;
   284             }
   285         } else {
   286             if (lhs < 0) {
   287                 if (rhs && lhs < (::std::numeric_limits<ResultType>::min() / rhs))
   288                     return false;
   289             } else {
   290                 if (lhs && rhs < (::std::numeric_limits<ResultType>::min() / lhs))
   291                     return false;
   292             }
   293         }
   294         result = lhs * rhs;
   295         return true;
   296     }
   298     static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
   300 };
   302 template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, false, false> {
   303     // LHS and RHS are unsigned types so bounds checks are nice and easy
   304     static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
   305     {
   306         ResultType temp = lhs + rhs;
   307         if (temp < lhs)
   308             return false;
   309         result = temp;
   310         return true;
   311     }
   313     static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
   314     {
   315         ResultType temp = lhs - rhs;
   316         if (temp > lhs)
   317             return false;
   318         result = temp;
   319         return true;
   320     }
   322     static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
   323     {
   324         ResultType temp = lhs * rhs;
   325         if (temp < lhs)
   326             return false;
   327         result = temp;
   328         return true;
   329     }
   331     static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
   333 };
   335 template <typename ResultType> struct ArithmeticOperations<int, unsigned, ResultType, true, false> {
   336     static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
   337     {
   338         int64_t temp = lhs + rhs;
   339         if (temp < ::std::numeric_limits<ResultType>::min())
   340             return false;
   341         if (temp > ::std::numeric_limits<ResultType>::max())
   342             return false;
   343         result = static_cast<ResultType>(temp);
   344         return true;
   345     }
   347     static inline bool sub(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     }
   358     static inline bool multiply(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     }
   369     static inline bool equals(int lhs, unsigned rhs)
   370     {
   371         return static_cast<int64_t>(lhs) == static_cast<int64_t>(rhs);
   372     }
   373 };
   375 template <typename ResultType> struct ArithmeticOperations<unsigned, int, ResultType, false, true> {
   376     static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
   377     {
   378         return ArithmeticOperations<int, unsigned, ResultType>::add(rhs, lhs, result);
   379     }
   381     static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
   382     {
   383         return ArithmeticOperations<int, unsigned, ResultType>::sub(lhs, rhs, result);
   384     }
   386     static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
   387     {
   388         return ArithmeticOperations<int, unsigned, ResultType>::multiply(rhs, lhs, result);
   389     }
   391     static inline bool equals(unsigned lhs, int rhs)
   392     {
   393         return ArithmeticOperations<int, unsigned, ResultType>::equals(rhs, lhs);
   394     }
   395 };
   397 template <typename U, typename V, typename R> static inline bool safeAdd(U lhs, V rhs, R& result)
   398 {
   399     return ArithmeticOperations<U, V, R>::add(lhs, rhs, result);
   400 }
   402 template <typename U, typename V, typename R> static inline bool safeSub(U lhs, V rhs, R& result)
   403 {
   404     return ArithmeticOperations<U, V, R>::sub(lhs, rhs, result);
   405 }
   407 template <typename U, typename V, typename R> static inline bool safeMultiply(U lhs, V rhs, R& result)
   408 {
   409     return ArithmeticOperations<U, V, R>::multiply(lhs, rhs, result);
   410 }
   412 template <typename U, typename V> static inline bool safeEquals(U lhs, V rhs)
   413 {
   414     return ArithmeticOperations<U, V>::equals(lhs, rhs);
   415 }
   417 enum ResultOverflowedTag { ResultOverflowed };
   419 // FIXME: Needed to workaround http://llvm.org/bugs/show_bug.cgi?id=10801
   420 static inline bool workAroundClangBug() { return true; }
   422 template <typename T, class OverflowHandler> class Checked : public OverflowHandler {
   423 public:
   424     template <typename _T, class _OverflowHandler> friend class Checked;
   425     Checked()
   426         : m_value(0)
   427     {
   428     }
   430     Checked(ResultOverflowedTag)
   431         : m_value(0)
   432     {
   433         // FIXME: Remove this when clang fixes http://llvm.org/bugs/show_bug.cgi?id=10801
   434         if (workAroundClangBug())
   435             this->overflowed();
   436     }
   438     template <typename U> Checked(U value)
   439     {
   440         if (!isInBounds<T>(value))
   441             this->overflowed();
   442         m_value = static_cast<T>(value);
   443     }
   445     template <typename V> Checked(const Checked<T, V>& rhs)
   446         : m_value(rhs.m_value)
   447     {
   448         if (rhs.hasOverflowed())
   449             this->overflowed();
   450     }
   452     template <typename U> Checked(const Checked<U, OverflowHandler>& rhs)
   453         : OverflowHandler(rhs)
   454     {
   455         if (!isInBounds<T>(rhs.m_value))
   456             this->overflowed();
   457         m_value = static_cast<T>(rhs.m_value);
   458     }
   460     template <typename U, typename V> Checked(const Checked<U, V>& rhs)
   461     {
   462         if (rhs.hasOverflowed())
   463             this->overflowed();
   464         if (!isInBounds<T>(rhs.m_value))
   465             this->overflowed();
   466         m_value = static_cast<T>(rhs.m_value);
   467     }
   469     const Checked& operator=(Checked rhs)
   470     {
   471         this->clearOverflow();
   472         if (rhs.hasOverflowed())
   473             this->overflowed();
   474         m_value = static_cast<T>(rhs.m_value);
   475         return *this;
   476     }
   478     template <typename U> const Checked& operator=(U value)
   479     {
   480         return *this = Checked(value);
   481     }
   483     template <typename U, typename V> const Checked& operator=(const Checked<U, V>& rhs)
   484     {
   485         return *this = Checked(rhs);
   486     }
   488     // prefix
   489     const Checked& operator++()
   490     {
   491         if (m_value == ::std::numeric_limits<T>::max())
   492             this->overflowed();
   493         m_value++;
   494         return *this;
   495     }
   497     const Checked& operator--()
   498     {
   499         if (m_value == ::std::numeric_limits<T>::min())
   500             this->overflowed();
   501         m_value--;
   502         return *this;
   503     }
   505     // postfix operators
   506     const Checked operator++(int)
   507     {
   508         if (m_value == ::std::numeric_limits<T>::max())
   509             this->overflowed();
   510         return Checked(m_value++);
   511     }
   513     const Checked operator--(int)
   514     {
   515         if (m_value == ::std::numeric_limits<T>::min())
   516             this->overflowed();
   517         return Checked(m_value--);
   518     }
   520     // Boolean operators
   521     bool operator!() const
   522     {
   523         if (this->hasOverflowed())
   524             CRASH();
   525         return !m_value;
   526     }
   528     typedef void* (Checked::*UnspecifiedBoolType);
   529     operator UnspecifiedBoolType*() const
   530     {
   531         if (this->hasOverflowed())
   532             CRASH();
   533         return (m_value) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0;
   534     }
   536     // Value accessors. unsafeGet() will crash if there's been an overflow.
   537     T unsafeGet() const
   538     {
   539         if (this->hasOverflowed())
   540             CRASH();
   541         return m_value;
   542     }
   544     bool safeGet(T& value) const WARN_UNUSED_RETURN
   545     {
   546         value = m_value;
   547         return this->hasOverflowed();
   548     }
   550     // Mutating assignment
   551     template <typename U> const Checked operator+=(U rhs)
   552     {
   553         if (!safeAdd(m_value, rhs, m_value))
   554             this->overflowed();
   555         return *this;
   556     }
   558     template <typename U> const Checked operator-=(U rhs)
   559     {
   560         if (!safeSub(m_value, rhs, m_value))
   561             this->overflowed();
   562         return *this;
   563     }
   565     template <typename U> const Checked operator*=(U rhs)
   566     {
   567         if (!safeMultiply(m_value, rhs, m_value))
   568             this->overflowed();
   569         return *this;
   570     }
   572     const Checked operator*=(double rhs)
   573     {
   574         double result = rhs * m_value;
   575         // Handle +/- infinity and NaN
   576         if (!(::std::numeric_limits<T>::min() <= result && ::std::numeric_limits<T>::max() >= result))
   577             this->overflowed();
   578         m_value = (T)result;
   579         return *this;
   580     }
   582     const Checked operator*=(float rhs)
   583     {
   584         return *this *= (double)rhs;
   585     }
   587     template <typename U, typename V> const Checked operator+=(Checked<U, V> rhs)
   588     {
   589         if (rhs.hasOverflowed())
   590             this->overflowed();
   591         return *this += rhs.m_value;
   592     }
   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     }
   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     }
   608     // Equality comparisons
   609     template <typename V> bool operator==(Checked<T, V> rhs)
   610     {
   611         return unsafeGet() == rhs.unsafeGet();
   612     }
   614     template <typename U> bool operator==(U rhs)
   615     {
   616         if (this->hasOverflowed())
   617             this->overflowed();
   618         return safeEquals(m_value, rhs);
   619     }
   621     template <typename U, typename V> const Checked operator==(Checked<U, V> rhs)
   622     {
   623         return unsafeGet() == Checked(rhs.unsafeGet());
   624     }
   626     template <typename U> bool operator!=(U rhs)
   627     {
   628         return !(*this == rhs);
   629     }
   631 private:
   632     // Disallow implicit conversion of floating point to integer types
   633     Checked(float);
   634     Checked(double);
   635     void operator=(float);
   636     void operator=(double);
   637     void operator+=(float);
   638     void operator+=(double);
   639     void operator-=(float);
   640     void operator-=(double);
   641     T m_value;
   642 };
   644 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)
   645 {
   646     U x = 0;
   647     V y = 0;
   648     bool overflowed = lhs.safeGet(x) || rhs.safeGet(y);
   649     typename Result<U, V>::ResultType result = 0;
   650     overflowed |= !safeAdd(x, y, result);
   651     if (overflowed)
   652         return ResultOverflowed;
   653     return result;
   654 }
   656 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)
   657 {
   658     U x = 0;
   659     V y = 0;
   660     bool overflowed = lhs.safeGet(x) || rhs.safeGet(y);
   661     typename Result<U, V>::ResultType result = 0;
   662     overflowed |= !safeSub(x, y, result);
   663     if (overflowed)
   664         return ResultOverflowed;
   665     return result;
   666 }
   668 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)
   669 {
   670     U x = 0;
   671     V y = 0;
   672     bool overflowed = lhs.safeGet(x) || rhs.safeGet(y);
   673     typename Result<U, V>::ResultType result = 0;
   674     overflowed |= !safeMultiply(x, y, result);
   675     if (overflowed)
   676         return ResultOverflowed;
   677     return result;
   678 }
   680 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, V rhs)
   681 {
   682     return lhs + Checked<V, OverflowHandler>(rhs);
   683 }
   685 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, V rhs)
   686 {
   687     return lhs - Checked<V, OverflowHandler>(rhs);
   688 }
   690 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, V rhs)
   691 {
   692     return lhs * Checked<V, OverflowHandler>(rhs);
   693 }
   695 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(U lhs, Checked<V, OverflowHandler> rhs)
   696 {
   697     return Checked<U, OverflowHandler>(lhs) + rhs;
   698 }
   700 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(U lhs, Checked<V, OverflowHandler> rhs)
   701 {
   702     return Checked<U, OverflowHandler>(lhs) - rhs;
   703 }
   705 template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(U lhs, Checked<V, OverflowHandler> rhs)
   706 {
   707     return Checked<U, OverflowHandler>(lhs) * rhs;
   708 }
   710 }
   712 using WTF::Checked;
   713 using WTF::RecordOverflow;
   715 #endif /* yarr_CheckedArithmetic_h */

mercurial