Bug 1494765 - Allow assignment from an nsCOMPtr of a related type r=froydnj
authorAndrew McCreight <continuation@gmail.com>
Tue, 02 Oct 2018 00:54:16 +0000
changeset 494810 3a9818cd5ffa027282bcc610d2845c6ef6524792
parent 494809 ce1bae1b9226fe1a3065d4a2a65973ecb0ab348a
child 494811 d0bd55d771e4097e7958434199f6b6fed2448106
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1494765
milestone64.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 1494765 - Allow assignment from an nsCOMPtr of a related type r=froydnj This adds support for conversion from nsCOMPtr<A> to nsCOMPtr<B> when A is a subclass of B. There's no reason to not allow this, and RefPtr already supports this. Differential Revision: https://phabricator.services.mozilla.com/D7226
xpcom/base/nsCOMPtr.h
--- a/xpcom/base/nsCOMPtr.h
+++ b/xpcom/base/nsCOMPtr.h
@@ -464,25 +464,51 @@ public:
   {
     assert_validity();
     if (mRawPtr) {
       NSCAP_ADDREF(this, mRawPtr);
     }
     NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
   }
 
+  template <class U>
+  MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr<U>& aSmartPtr)
+    : NSCAP_CTOR_BASE(aSmartPtr.get())
+  {
+    // Make sure that U actually inherits from T
+    static_assert(mozilla::IsBaseOf<T, U>::value,
+                  "U should be a subclass of T");
+    assert_validity();
+    if (mRawPtr) {
+      NSCAP_ADDREF(this, mRawPtr);
+    }
+    NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.get());
+  }
+
   nsCOMPtr(nsCOMPtr<T>&& aSmartPtr)
     : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
   {
     assert_validity();
     aSmartPtr.mRawPtr = nullptr;
     NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
     NSCAP_ASSERT_NO_QUERY_NEEDED();
   }
 
+  template <class U>
+  MOZ_IMPLICIT nsCOMPtr(nsCOMPtr<U>&& aSmartPtr)
+    : NSCAP_CTOR_BASE(aSmartPtr.forget().template downcast<T>().take())
+  {
+    // Make sure that U actually inherits from T
+    static_assert(mozilla::IsBaseOf<T, U>::value,
+                  "U should be a subclass of T");
+    assert_validity();
+    NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
+    NSCAP_ASSERT_NO_QUERY_NEEDED();
+  }
+
   MOZ_IMPLICIT nsCOMPtr(T* aRawPtr)
     : NSCAP_CTOR_BASE(aRawPtr)
   {
     assert_validity();
     if (mRawPtr) {
       NSCAP_ADDREF(this, mRawPtr);
     }
     NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
@@ -614,23 +640,44 @@ public:
   // Assignment operators
 
   nsCOMPtr<T>& operator=(const nsCOMPtr<T>& aRhs)
   {
     assign_with_AddRef(aRhs.mRawPtr);
     return *this;
   }
 
+  template<class U>
+  nsCOMPtr<T>& operator=(const nsCOMPtr<U>& aRhs)
+  {
+    // Make sure that U actually inherits from T
+    static_assert(mozilla::IsBaseOf<T, U>::value,
+                  "U should be a subclass of T");
+    assign_with_AddRef(static_cast<T*>(aRhs.get()));
+    return *this;
+  }
+
   nsCOMPtr<T>& operator=(nsCOMPtr<T>&& aRhs)
   {
     assign_assuming_AddRef(aRhs.forget().take());
     NSCAP_ASSERT_NO_QUERY_NEEDED();
     return *this;
   }
 
+  template<class U>
+  nsCOMPtr<T>& operator=(nsCOMPtr<U>&& aRhs)
+  {
+    // Make sure that U actually inherits from T
+    static_assert(mozilla::IsBaseOf<T, U>::value,
+                  "U should be a subclass of T");
+    assign_assuming_AddRef(aRhs.forget().template downcast<T>().take());
+    NSCAP_ASSERT_NO_QUERY_NEEDED();
+    return *this;
+  }
+
   nsCOMPtr<T>& operator=(T* aRhs)
   {
     assign_with_AddRef(aRhs);
     NSCAP_ASSERT_NO_QUERY_NEEDED();
     return *this;
   }
 
   nsCOMPtr<T>& operator=(decltype(nullptr))