Bug 1193298 - Part 3: Delete RefPtr<T>::operator T*()&&. r=froydnj
authorAryeh Gregor <ayg@aryeh.name>
Tue, 11 Aug 2015 06:45:00 -0400
changeset 257838 a2676b325b8ab911a43a3d99be73959a786eec8c
parent 257837 1a488cbda2a6698557206ebccc29370b256aa736
child 257839 20874c0e47fa4013dc521857bb9852bd981eedbe
push id63732
push userryanvm@gmail.com
push dateFri, 14 Aug 2015 14:07:46 +0000
treeherdermozilla-inbound@bc7d2eccea16 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1193298
milestone43.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 1193298 - Part 3: Delete RefPtr<T>::operator T*()&&. r=froydnj I put MOZ_HAVE_REF_QUALIFIERS in Attributes.h for lack of a better place. I didn't especially want to make a whole new file for it. To make the tree compile, support for moving RefPtr to nsRefPtr was needed. I chose to put the definitions in RefPtr.h instead of nsRefPtr.h because RefPtr.h looks to be included in fewer files, so I preferred to bloat fewer files with the extra include. For some reason operator!() wasn't necessary here, although it seems it is for nsRefPtr.
mfbt/Attributes.h
mfbt/RefPtr.h
mfbt/nsRefPtr.h
--- a/mfbt/Attributes.h
+++ b/mfbt/Attributes.h
@@ -527,11 +527,27 @@
 #  define MOZ_NO_ADDREF_RELEASE_ON_RETURN /* nothing */
 #  define MOZ_MUST_USE /* nothing */
 #  define MOZ_NEEDS_NO_VTABLE_TYPE /* nothing */
 #  define MOZ_NON_MEMMOVABLE /* nothing */
 #  define MOZ_NEEDS_MEMMOVABLE_TYPE /* nothing */
 #  define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS /* nothing */
 #endif /* MOZ_CLANG_PLUGIN */
 
+/*
+ * MOZ_HAVE_REF_QUALIFIERS is defined for compilers that support C++11's rvalue
+ * qualifier, "&&".
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1900
+#  define MOZ_HAVE_REF_QUALIFIERS
+#elif defined(__clang__)
+// All supported Clang versions
+#  define MOZ_HAVE_REF_QUALIFIERS
+#elif defined(__GNUC__)
+#  include "mozilla/Compiler.h"
+#  if MOZ_GCC_VERSION_AT_LEAST(4, 8, 1)
+#    define MOZ_HAVE_REF_QUALIFIERS
+#  endif
+#endif
+
 #endif /* __cplusplus */
 
 #endif /* mozilla_Attributes_h */
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -10,16 +10,17 @@
 #define mozilla_RefPtr_h
 
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Move.h"
 #include "mozilla/RefCountType.h"
+#include "mozilla/nsRefPtr.h"
 #include "mozilla/TypeTraits.h"
 #if defined(MOZILLA_INTERNAL_API)
 #include "nsXPCOM.h"
 #endif
 
 #if defined(MOZILLA_INTERNAL_API) && \
     !defined(MOZILLA_XPCOMRT_API) && \
     (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
@@ -273,20 +274,33 @@ public:
   already_AddRefed<T> forget()
   {
     T* tmp = mPtr;
     mPtr = nullptr;
     return already_AddRefed<T>(tmp);
   }
 
   T* get() const { return mPtr; }
-  operator T*() const { return mPtr; }
+  operator T*() const
+#ifdef MOZ_HAVE_REF_QUALIFIERS
+  &
+#endif
+  { return mPtr; }
   T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { return mPtr; }
   T& operator*() const { return *mPtr; }
 
+#ifdef MOZ_HAVE_REF_QUALIFIERS
+  // Don't allow implicit conversion of temporary RefPtr to raw pointer, because
+  // the refcount might be one and the pointer will immediately become invalid.
+  operator T*() const && = delete;
+
+  // Needed to avoid the deleted operator above
+  explicit operator bool() const { return !!mPtr; }
+#endif
+
 private:
   void assign(T* aVal)
   {
     T* tmp = mPtr;
     mPtr = aVal;
     unref(tmp);
   }
 
@@ -370,9 +384,24 @@ already_AddRefed<T>
 MakeAndAddRef(Args&&... aArgs)
 {
   RefPtr<T> p(new T(Forward<Args>(aArgs)...));
   return p.forget();
 }
 
 } // namespace mozilla
 
+// Declared in nsRefPtr.h
+template<class T> template<class U>
+nsRefPtr<T>::nsRefPtr(mozilla::RefPtr<U>&& aOther)
+  : nsRefPtr(aOther.forget())
+{
+}
+
+template<class T> template<class U>
+nsRefPtr<T>&
+nsRefPtr<T>::operator=(mozilla::RefPtr<U>&& aOther)
+{
+  assign_assuming_AddRef(aOther.forget().take());
+  return *this;
+}
+
 #endif /* mozilla_RefPtr_h */
--- a/mfbt/nsRefPtr.h
+++ b/mfbt/nsRefPtr.h
@@ -2,40 +2,29 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_nsRefPtr_h
 #define mozilla_nsRefPtr_h
 
-#if defined(_MSC_VER) && _MSC_VER >= 1900
-#  define MOZ_HAVE_REF_QUALIFIERS
-#elif defined(__clang__)
-// All supported Clang versions
-#  define MOZ_HAVE_REF_QUALIFIERS
-#elif defined(__GNUC__)
-#  include "mozilla/Compiler.h"
-#  if MOZ_GCC_VERSION_AT_LEAST(4, 8, 1)
-#    define MOZ_HAVE_REF_QUALIFIERS
-#  endif
-#endif
-
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 
 /*****************************************************************************/
 
 // template <class T> class nsRefPtrGetterAddRefs;
 
 class nsCOMPtr_helper;
 
 namespace mozilla {
 template<class T> class OwningNonNull;
+template<class T> class RefPtr;
 } // namespace mozilla
 
 template <class T>
 class nsRefPtr
 {
 private:
   void
   assign_with_AddRef(T* aRawPtr)
@@ -134,16 +123,20 @@ public:
   }
 
   MOZ_IMPLICIT nsRefPtr(const nsCOMPtr_helper& aHelper);
 
   // Defined in OwningNonNull.h
   template<class U>
   MOZ_IMPLICIT nsRefPtr(const mozilla::OwningNonNull<U>& aOther);
 
+  // Defined in RefPtr.h
+  template<class U>
+  MOZ_IMPLICIT nsRefPtr(mozilla::RefPtr<U>&& aOther);
+
   // Assignment operators
 
   nsRefPtr<T>&
   operator=(const nsRefPtr<T>& aRhs)
   // copy assignment operator
   {
     assign_with_AddRef(aRhs.mRawPtr);
     return *this;
@@ -194,16 +187,21 @@ public:
     return *this;
   }
 
   // Defined in OwningNonNull.h
   template<class U>
   nsRefPtr<T>&
   operator=(const mozilla::OwningNonNull<U>& aOther);
 
+  // Defined in RefPtr.h
+  template<class U>
+  nsRefPtr<T>&
+  operator=(mozilla::RefPtr<U>&& aOther);
+
   // Other pointer operators
 
   void
   swap(nsRefPtr<T>& aRhs)
   // ...exchange ownership with |aRhs|; can save a pair of refcount operations
   {
     T* temp = aRhs.mRawPtr;
     aRhs.mRawPtr = mRawPtr;
@@ -594,13 +592,9 @@ operator!=(::detail::nsRefPtrZero* aLhs,
 template <class T>
 inline already_AddRefed<T>
 do_AddRef(T*&& aObj)
 {
   nsRefPtr<T> ref(aObj);
   return ref.forget();
 }
 
-#ifdef MOZ_HAVE_REF_QUALIFIERS
-#undef MOZ_HAVE_REF_QUALIFIERS
-#endif
-
 #endif /* mozilla_nsRefPtr_h */