Bug 1316206 - RefPtr construction/assignment from nullptr - r=froydnj draft
authorGerald Squelart <gsquelart@mozilla.com>
Thu, 10 Nov 2016 07:58:10 +1100
changeset 436876 f4ec156b13ea3bdcf32b1a33d76ff9771ad6d1dc
parent 436738 336759fad4621dfcd0a3293840edbed67018accd
child 436877 bc4107ce1767329e3dddfe34c55ba79202192e06
push id35228
push usergsquelart@mozilla.com
push dateWed, 09 Nov 2016 22:39:42 +0000
reviewersfroydnj
bugs1316206
milestone52.0a1
Bug 1316206 - RefPtr construction/assignment from nullptr - r=froydnj Added constructor and operator= from a nullptr, bypassing the incoming pointer check. Note that the constructor is 'explicit', because one particular use in nsBaseHashtable is doing a 'return 0' into a templated type that is a RefPtr in many cases. Making this new constructor explicit removes it from consideration in this case. As it's not strictly necessary to have it MOZ_IMPLICIT (but could still be nice), I will tackle that in the patch after next. Also changed all zeroes into nullptr when relevant in RefPtr.h (other system- wide affected files will be updated in following patch.) MozReview-Commit-ID: Ds4CEv9hZWI
mfbt/RefPtr.h
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -77,17 +77,17 @@ public:
     if (mRawPtr) {
       ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
     }
   }
 
   // Constructors
 
   RefPtr()
-    : mRawPtr(0)
+    : mRawPtr(nullptr)
     // default constructor
   {
   }
 
   RefPtr(const RefPtr<T>& aSmartPtr)
     : mRawPtr(aSmartPtr.mRawPtr)
     // copy-constructor
   {
@@ -107,16 +107,21 @@ public:
   MOZ_IMPLICIT RefPtr(T* aRawPtr)
     : mRawPtr(aRawPtr)
   {
     if (mRawPtr) {
       ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
     }
   }
 
+  explicit RefPtr(decltype(nullptr))
+    : mRawPtr(nullptr)
+  {
+  }
+
   template <typename I>
   MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
     : mRawPtr(aSmartPtr.take())
     // construct from |already_AddRefed|
   {
   }
 
   template <typename I>
@@ -151,16 +156,23 @@ public:
 
   // Defined in StaticPtr.h
   template<class U>
   MOZ_IMPLICIT RefPtr(const mozilla::StaticRefPtr<U>& aOther);
 
   // Assignment operators
 
   RefPtr<T>&
+  operator=(decltype(nullptr))
+  {
+    assign_assuming_AddRef(nullptr);
+    return *this;
+  }
+
+  RefPtr<T>&
   operator=(const RefPtr<T>& aRhs)
   // copy assignment operator
   {
     assign_with_AddRef(aRhs.mRawPtr);
     return *this;
   }
 
   template <typename I>
@@ -238,32 +250,32 @@ public:
     mRawPtr = temp;
   }
 
   already_AddRefed<T>
   forget()
   // return the value of mRawPtr and null out mRawPtr. Useful for
   // already_AddRefed return values.
   {
-    T* temp = 0;
+    T* temp = nullptr;
     swap(temp);
     return already_AddRefed<T>(temp);
   }
 
   template <typename I>
   void
   forget(I** aRhs)
   // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
   // Useful to avoid unnecessary AddRef/Release pairs with "out"
   // parameters where aRhs bay be a T** or an I** where I is a base class
   // of T.
   {
     MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
     *aRhs = mRawPtr;
-    mRawPtr = 0;
+    mRawPtr = nullptr;
   }
 
   T*
   get() const
   /*
     Prefer the implicit conversion provided automatically by |operator T*() const|.
     Use |get()| to resolve ambiguity or to get a castable pointer.
   */
@@ -298,17 +310,17 @@ public:
   // operator bool instead of the deleted operator T*?
   explicit operator bool() const { return !!mRawPtr; }
   bool operator!() const { return !mRawPtr; }
 #endif
 
   T*
   operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
   {
-    MOZ_ASSERT(mRawPtr != 0,
+    MOZ_ASSERT(mRawPtr != nullptr,
                "You can't dereference a NULL RefPtr with operator->().");
     return get();
   }
 
   template <typename R, typename... Args>
   class Proxy
   {
     typedef R (T::*member_function)(Args...);
@@ -325,17 +337,17 @@ public:
     {
       return ((*mRawPtr).*mFunction)(mozilla::Forward<ActualArgs>(aArgs)...);
     }
   };
 
   template <typename R, typename... Args>
   Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const
   {
-    MOZ_ASSERT(mRawPtr != 0,
+    MOZ_ASSERT(mRawPtr != nullptr,
                "You can't dereference a NULL RefPtr with operator->*().");
     return Proxy<R, Args...>(get(), aFptr);
   }
 
   RefPtr<T>*
   get_address()
   // This is not intended to be used by clients.  See |address_of|
   // below.
@@ -350,25 +362,25 @@ public:
   {
     return this;
   }
 
 public:
   T&
   operator*() const
   {
-    MOZ_ASSERT(mRawPtr != 0,
+    MOZ_ASSERT(mRawPtr != nullptr,
                "You can't dereference a NULL RefPtr with operator*().");
     return *get();
   }
 
   T**
   StartAssignment()
   {
-    assign_assuming_AddRef(0);
+    assign_assuming_AddRef(nullptr);
     return reinterpret_cast<T**>(&mRawPtr);
   }
 private:
   // This helper class makes |RefPtr<const T>| possible by casting away
   // the constness from the pointer when calling AddRef() and Release().
   //
   // This is necessary because AddRef() and Release() implementations can't
   // generally expected to be const themselves (without heavy use of |mutable|