Bug 1600096 - Disable RefPtr conversion constructors when underlying pointer types are not convertible. r=froydnj
authorSimon Giesecke <sgiesecke@mozilla.com>
Wed, 11 Dec 2019 10:11:45 +0000
changeset 506620 41f4ca1d2e222837038671feb2dd2deeb2074838
parent 506619 bd27dfd96896dde5f30d6d3942072cf35fba7827
child 506621 c6f80ffff41b0abd65cf6ff376ac6aff39ab1513
push id36910
push usercsabou@mozilla.com
push dateThu, 12 Dec 2019 21:50:40 +0000
treeherdermozilla-central@0f6958f49842 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1600096
milestone73.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 1600096 - Disable RefPtr conversion constructors when underlying pointer types are not convertible. r=froydnj Differential Revision: https://phabricator.services.mozilla.com/D55141
mfbt/RefPtr.h
mfbt/tests/TestRefPtr.cpp
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -7,16 +7,18 @@
 #ifndef mozilla_RefPtr_h
 #define mozilla_RefPtr_h
 
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DbgMacro.h"
 
+#include <type_traits>
+
 /*****************************************************************************/
 
 // template <class T> class RefPtrGetterAddRefs;
 
 class nsQueryReferent;
 class nsCOMPtr_helper;
 class nsISupports;
 
@@ -105,39 +107,43 @@ class MOZ_IS_REFPTR RefPtr {
   MOZ_IMPLICIT RefPtr(T* aRawPtr) : mRawPtr(aRawPtr) {
     if (mRawPtr) {
       ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
     }
   }
 
   MOZ_IMPLICIT RefPtr(decltype(nullptr)) : mRawPtr(nullptr) {}
 
-  template <typename I>
+  template <typename I,
+            typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
   MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
       : mRawPtr(aSmartPtr.take())
   // construct from |already_AddRefed|
   {}
 
-  template <typename I>
+  template <typename I,
+            typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
   MOZ_IMPLICIT RefPtr(already_AddRefed<I>&& aSmartPtr)
       : mRawPtr(aSmartPtr.take())
   // construct from |otherRefPtr.forget()|
   {}
 
-  template <typename I>
+  template <typename I,
+            typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
   MOZ_IMPLICIT RefPtr(const RefPtr<I>& aSmartPtr)
       : mRawPtr(aSmartPtr.get())
   // copy-construct from a smart pointer with a related pointer type
   {
     if (mRawPtr) {
       ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
     }
   }
 
-  template <typename I>
+  template <typename I,
+            typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
   MOZ_IMPLICIT RefPtr(RefPtr<I>&& aSmartPtr)
       : mRawPtr(aSmartPtr.forget().take())
   // construct from |Move(RefPtr<SomeSubclassOfT>)|.
   {}
 
   MOZ_IMPLICIT RefPtr(const nsQueryReferent& aHelper);
   MOZ_IMPLICIT RefPtr(const nsCOMPtr_helper& aHelper);
 #if defined(XP_WIN)
--- a/mfbt/tests/TestRefPtr.cpp
+++ b/mfbt/tests/TestRefPtr.cpp
@@ -109,10 +109,18 @@ int main() {
   MOZ_RELEASE_ASSERT(11 == Foo::sNumDestroyed);
 
   {
     RefPtr<Foo> f = GetNullFoo();
     MOZ_RELEASE_ASSERT(11 == Foo::sNumDestroyed);
   }
   MOZ_RELEASE_ASSERT(11 == Foo::sNumDestroyed);
 
+  {
+    bool condition = true;
+    const auto f =
+        condition ? mozilla::MakeRefPtr<Bar>() : mozilla::MakeRefPtr<Foo>();
+
+    MOZ_RELEASE_ASSERT(f);
+  }
+
   return 0;
 }