Bug 1097512 - Allow using compound operators where the LHS and RHS are both CheckedInt<T>. r=jwalden+bmo
authorMatthew Gregan <kinetik@flim.org>
Fri, 14 Nov 2014 16:13:23 +1300
changeset 215697 5a2271cb4a6760cdf574bd6ff4c850f3ffaf1091
parent 215696 fd662a7e86879b84d925985f43fa6016614c65c5
child 215698 0b0b306c021dbcbbba9a812e781858cb14c29593
push id27823
push usercbook@mozilla.com
push dateFri, 14 Nov 2014 11:59:57 +0000
treeherdermozilla-central@bbb68df450c2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1097512
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1097512 - Allow using compound operators where the LHS and RHS are both CheckedInt<T>. r=jwalden+bmo
mfbt/CheckedInt.h
mfbt/tests/TestCheckedInt.cpp
--- a/mfbt/CheckedInt.h
+++ b/mfbt/CheckedInt.h
@@ -569,40 +569,45 @@ public:
     return mIsValid;
   }
 
   template<typename U>
   friend CheckedInt<U> operator +(const CheckedInt<U>& aLhs,
                                   const CheckedInt<U>& aRhs);
   template<typename U>
   CheckedInt& operator +=(U aRhs);
+  CheckedInt& operator +=(const CheckedInt<T>& aRhs);
 
   template<typename U>
   friend CheckedInt<U> operator -(const CheckedInt<U>& aLhs,
                                   const CheckedInt<U>& aRhs);
   template<typename U>
   CheckedInt& operator -=(U aRhs);
+  CheckedInt& operator -=(const CheckedInt<T>& aRhs);
 
   template<typename U>
   friend CheckedInt<U> operator *(const CheckedInt<U>& aLhs,
                                   const CheckedInt<U>& aRhs);
   template<typename U>
   CheckedInt& operator *=(U aRhs);
+  CheckedInt& operator *=(const CheckedInt<T>& aRhs);
 
   template<typename U>
   friend CheckedInt<U> operator /(const CheckedInt<U>& aLhs,
                                   const CheckedInt<U>& aRhs);
   template<typename U>
   CheckedInt& operator /=(U aRhs);
+  CheckedInt& operator /=(const CheckedInt<T>& aRhs);
 
   template<typename U>
   friend CheckedInt<U> operator %(const CheckedInt<U>& aLhs,
                                   const CheckedInt<U>& aRhs);
   template<typename U>
   CheckedInt& operator %=(U aRhs);
+  CheckedInt& operator %=(const CheckedInt<T>& aRhs);
 
   CheckedInt operator -() const
   {
     return detail::NegateImpl<T>::negate(*this);
   }
 
   /**
    * @returns true if the left and right hand sides are valid
@@ -718,33 +723,39 @@ inline typename detail::CastToCheckedInt
 castToCheckedInt(U aU)
 {
   static_assert(detail::IsSupported<T>::value &&
                 detail::IsSupported<U>::value,
                 "This type is not supported by CheckedInt");
   return detail::CastToCheckedIntImpl<T, U>::run(aU);
 }
 
-#define MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP)          \
-  template<typename T>                                                        \
-  template<typename U>                                                        \
-  CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(U aRhs)                  \
-  {                                                                           \
-    *this = *this OP castToCheckedInt<T>(aRhs);                               \
-    return *this;                                                             \
-  }                                                                           \
-  template<typename T, typename U>                                            \
-  inline CheckedInt<T> operator OP(const CheckedInt<T>& aLhs, U aRhs)         \
-  {                                                                           \
-    return aLhs OP castToCheckedInt<T>(aRhs);                                 \
-  }                                                                           \
-  template<typename T, typename U>                                            \
-  inline CheckedInt<T> operator OP(U aLhs, const CheckedInt<T>& aRhs)         \
-  {                                                                           \
-    return castToCheckedInt<T>(aLhs) OP aRhs;                                 \
+#define MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP)            \
+  template<typename T>                                                          \
+  template<typename U>                                                          \
+  CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(U aRhs)                    \
+  {                                                                             \
+    *this = *this OP castToCheckedInt<T>(aRhs);                                 \
+    return *this;                                                               \
+  }                                                                             \
+  template<typename T>                                                          \
+  CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(const CheckedInt<T>& aRhs) \
+  {                                                                             \
+    *this = *this OP aRhs;                                                      \
+    return *this;                                                               \
+  }                                                                             \
+  template<typename T, typename U>                                              \
+  inline CheckedInt<T> operator OP(const CheckedInt<T>& aLhs, U aRhs)           \
+  {                                                                             \
+    return aLhs OP castToCheckedInt<T>(aRhs);                                   \
+  }                                                                             \
+  template<typename T, typename U>                                              \
+  inline CheckedInt<T> operator OP(U aLhs, const CheckedInt<T>& aRhs)           \
+  {                                                                             \
+    return castToCheckedInt<T>(aLhs) OP aRhs;                                   \
   }
 
 MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=)
 MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=)
 MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=)
 MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=)
 MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(%, %=)
 
--- a/mfbt/tests/TestCheckedInt.cpp
+++ b/mfbt/tests/TestCheckedInt.cpp
@@ -417,16 +417,72 @@ void test()
 
   VERIFY(one == 1);
   VERIFY(1 == one);
   VERIFY_IS_FALSE(two == 1);
   VERIFY_IS_FALSE(1 == two);
   VERIFY_IS_FALSE(someInvalid == 1);
   VERIFY_IS_FALSE(1 == someInvalid);
 
+  // Check that compound operators work when both sides of the expression
+  // are checked integers
+  {
+    CheckedInt<T> x = one;
+    x += two;
+    VERIFY(x == three);
+  }
+  {
+    CheckedInt<T> x = two;
+    x -= one;
+    VERIFY(x == one);
+  }
+  {
+    CheckedInt<T> x = one;
+    x *= two;
+    VERIFY(x == two);
+  }
+  {
+    CheckedInt<T> x = four;
+    x /= two;
+    VERIFY(x == two);
+  }
+  {
+    CheckedInt<T> x = three;
+    x %= two;
+    VERIFY(x == one);
+  }
+
+  // Check that compound operators work when both sides of the expression
+  // are checked integers and the right-hand side is invalid
+  {
+    CheckedInt<T> x = one;
+    x += someInvalid;
+    VERIFY_IS_INVALID(x);
+  }
+  {
+    CheckedInt<T> x = two;
+    x -= someInvalid;
+    VERIFY_IS_INVALID(x);
+  }
+  {
+    CheckedInt<T> x = one;
+    x *= someInvalid;
+    VERIFY_IS_INVALID(x);
+  }
+  {
+    CheckedInt<T> x = four;
+    x /= someInvalid;
+    VERIFY_IS_INVALID(x);
+  }
+  {
+    CheckedInt<T> x = three;
+    x %= someInvalid;
+    VERIFY_IS_INVALID(x);
+  }
+
   // Check simple casting between different signedness and sizes.
   {
     CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(2).toChecked<uint8_t>();
     VERIFY_IS_VALID(foo);
     VERIFY(foo == 2);
   }
   {
     CheckedInt<uint8_t> foo = CheckedInt<uint16_t>(255).toChecked<uint8_t>();