Bug 1443367 - Rework MakeNotNull to build with VS 2017 15.6 - r?njn draft
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 06 Mar 2018 20:27:27 +1100
changeset 763648 b25899328e42e89216169ce4dd47e0891b59e5ea
parent 763635 a007dd56b9947a93c276e82275d7065db1949c9e
push id101505
push usergsquelart@mozilla.com
push dateTue, 06 Mar 2018 11:16:57 +0000
reviewersnjn
bugs1443367
milestone60.0a1
Bug 1443367 - Rework MakeNotNull to build with VS 2017 15.6 - r?njn VS 2017 15.6 (March 2018) doesn't seem to understand `*DeclVal<SharedFontList*>()` anymore. To work around this issue, the pointed-to type is now extracted in a separate struct, for which we provide a specialization for raw pointers, so we don't encounter the shaky `*DeclVal<T*>()` statement anymore. MozReview-Commit-ID: FuslManbfdB
mfbt/NotNull.h
--- a/mfbt/NotNull.h
+++ b/mfbt/NotNull.h
@@ -150,27 +150,57 @@ template <typename T>
 NotNull<T>
 WrapNotNull(const T aBasePtr)
 {
   NotNull<T> notNull(aBasePtr);
   MOZ_RELEASE_ASSERT(aBasePtr);
   return notNull;
 }
 
+namespace detail {
+
+// Extract the pointed-to type from a pointer type (be it raw or smart).
+// The default implementation uses the dereferencing operator of the pointer
+// type to find what it's pointing to.
+template<typename Pointer>
+struct PointedTo
+{
+  // Remove the reference that dereferencing operators may return.
+  using Type = typename RemoveReference<decltype(*DeclVal<Pointer>())>::Type;
+  using NonConstType = typename RemoveConst<Type>::Type;
+};
+
+// Specializations for raw pointers.
+// This is especially required because VS 2017 15.6 (March 2018) started
+// rejecting the above `decltype(*DeclVal<Pointer>())` trick for raw pointers.
+// See bug 1443367.
+template<typename T>
+struct PointedTo<T*>
+{
+  using Type = T;
+  using NonConstType = T;
+};
+
+template<typename T>
+struct PointedTo<const T*>
+{
+  using Type = const T;
+  using NonConstType = T;
+};
+
+} // namespace detail
+
 // Allocate an object with infallible new, and wrap its pointer in NotNull.
 // |MakeNotNull<Ptr<Ob>>(args...)| will run |new Ob(args...)|
 // and return NotNull<Ptr<Ob>>.
 template<typename T, typename... Args>
 NotNull<T>
 MakeNotNull(Args&&... aArgs)
 {
-  // Extract the pointee type from what T's dereferencing operator returns
-  // (which could be a reference to a const type).
-  using Pointee = typename mozilla::RemoveConst<
-    typename mozilla::RemoveReference<decltype(*DeclVal<T>())>::Type>::Type;
+  using Pointee = typename detail::PointedTo<T>::NonConstType;
   static_assert(!IsArray<Pointee>::value,
                 "MakeNotNull cannot construct an array");
   return NotNull<T>(new Pointee(Forward<Args>(aArgs)...));
 }
 
 // Compare two NotNulls.
 template <typename T, typename U>
 inline bool