Bug 1303302 - Add IsDestructible trait in TypeTraits and use it for refcounted type static check. r?froydnj draft
authorXidorn Quan <me@upsuper.org>
Fri, 16 Sep 2016 17:23:55 +1000
changeset 414490 7cdb43bcc110bdb455b9bd3009367a026dc45991
parent 414482 9257cddfc4e72040317c0d1e060144f8ca3863df
child 531451 d6ecc23020cf870d2673a84227be76d04ff0c89c
push id29680
push userxquan@mozilla.com
push dateFri, 16 Sep 2016 11:43:45 +0000
reviewersfroydnj
bugs1303302
milestone51.0a1
Bug 1303302 - Add IsDestructible trait in TypeTraits and use it for refcounted type static check. r?froydnj MozReview-Commit-ID: G3YFhrJngq0
mfbt/TypeTraits.h
mfbt/tests/TestTypeTraits.cpp
xpcom/glue/nsISupportsImpl.h
--- a/mfbt/TypeTraits.h
+++ b/mfbt/TypeTraits.h
@@ -567,16 +567,37 @@ struct IsUnsignedHelper<T, false, false,
  * mozilla::IsUnsigned<int>::value is false;
  * mozilla::IsUnsigned<const unsigned int>::value is true;
  * mozilla::IsUnsigned<unsigned char>::value is true;
  * mozilla::IsUnsigned<float>::value is false.
  */
 template<typename T>
 struct IsUnsigned : detail::IsUnsignedHelper<T> {};
 
+namespace detail {
+
+struct DoIsDestructibleImpl
+{
+  template<typename T, typename = decltype(DeclVal<T&>().~T())>
+  static TrueType test(int);
+  template<typename T>
+  static FalseType test(...);
+};
+
+template<typename T>
+struct IsDestructibleImpl : public DoIsDestructibleImpl
+{
+  typedef decltype(test<T>(0)) Type;
+};
+
+} // namespace detail
+
+template<typename T>
+struct IsDestructible : public detail::IsDestructibleImpl<T>::Type {};
+
 /* 20.9.5 Type property queries [meta.unary.prop.query] */
 
 /* 20.9.6 Relationships between types [meta.rel] */
 
 /**
  * IsSame tests whether two types are the same type.
  *
  * mozilla::IsSame<int, int>::value is true;
--- a/mfbt/tests/TestTypeTraits.cpp
+++ b/mfbt/tests/TestTypeTraits.cpp
@@ -26,16 +26,17 @@ using mozilla::IsConvertible;
 using mozilla::IsEmpty;
 using mozilla::IsLvalueReference;
 using mozilla::IsPointer;
 using mozilla::IsReference;
 using mozilla::IsRvalueReference;
 using mozilla::IsSame;
 using mozilla::IsSigned;
 using mozilla::IsUnsigned;
+using mozilla::IsDestructible;
 using mozilla::MakeSigned;
 using mozilla::MakeUnsigned;
 using mozilla::RemoveExtent;
 using mozilla::RemovePointer;
 
 static_assert(!IsFunction<int>::value,
               "int is not a function type");
 static_assert(IsFunction<void(int)>::value,
@@ -347,16 +348,37 @@ class NotIntConstructible
   NotIntConstructible(int) = delete;
 };
 
 static_assert(!IsSigned<NotIntConstructible>::value,
               "non-arithmetic types are not signed");
 static_assert(!IsUnsigned<NotIntConstructible>::value,
               "non-arithmetic types are not unsigned");
 
+class PublicDestructible
+{
+public:
+  ~PublicDestructible();
+};
+class PrivateDestructible
+{
+private:
+  ~PrivateDestructible();
+};
+class TrivialDestructible
+{
+};
+
+static_assert(IsDestructible<PublicDestructible>::value,
+              "public destructible class is destructible");
+static_assert(!IsDestructible<PrivateDestructible>::value,
+              "private destructible class is not destructible");
+static_assert(IsDestructible<TrivialDestructible>::value,
+              "trivial destructible class is destructible");
+
 namespace CPlusPlus11IsBaseOf {
 
 // Adapted from C++11 ยง 20.9.6.
 struct B {};
 struct B1 : B {};
 struct B2 : B {};
 struct D : private B1, private B2 {};
 
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -24,69 +24,20 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Compiler.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MacroArgs.h"
 #include "mozilla/MacroForEach.h"
 #include "mozilla/TypeTraits.h"
 
-#if defined(__clang__)
-   // bug 1028428 shows that at least in FreeBSD 10.0 with Clang 3.4 and libc++ 3.4,
-   // std::is_destructible is buggy in that it returns false when it should return true
-   // on ipc::SharedMemory. On the other hand, all Clang versions currently in use
-   // seem to handle the fallback just fine.
-#  define MOZ_CAN_USE_IS_DESTRUCTIBLE_FALLBACK
-#elif defined(__GNUC__)
-   // GCC 4.7 has buggy std::is_destructible.
-#  if MOZ_USING_LIBSTDCXX
-#    define MOZ_HAVE_STD_IS_DESTRUCTIBLE
-#  endif
-   // Some GCC versions have an ICE when using destructors in decltype().
-   // Works on GCC 4.8 at least.
-#  define MOZ_CAN_USE_IS_DESTRUCTIBLE_FALLBACK
-#endif
-
-#ifdef MOZ_HAVE_STD_IS_DESTRUCTIBLE
-#  include <type_traits>
-#  define MOZ_IS_DESTRUCTIBLE(X) (std::is_destructible<X>::value)
-#elif defined MOZ_CAN_USE_IS_DESTRUCTIBLE_FALLBACK
-  namespace mozilla {
-    struct IsDestructibleFallbackImpl
-    {
-      template<typename T, typename = decltype(DeclVal<T>().~T())>
-      static TrueType Test(int);
-
-      template<typename>
-      static FalseType Test(...);
-
-      template<typename T>
-      struct Selector
-      {
-        typedef decltype(Test<T>(0)) type;
-      };
-    };
-
-    template<typename T>
-    struct IsDestructibleFallback
-      : IsDestructibleFallbackImpl::Selector<T>::type
-    {
-    };
-  } // namespace mozilla
-#  define MOZ_IS_DESTRUCTIBLE(X) (mozilla::IsDestructibleFallback<X>::value)
-#endif
-
-#ifdef MOZ_IS_DESTRUCTIBLE
 #define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X) \
-  static_assert(!MOZ_IS_DESTRUCTIBLE(X), \
+  static_assert(!mozilla::IsDestructible<X>::value, \
                 "Reference-counted class " #X " should not have a public destructor. " \
                 "Make this class's destructor non-public");
-#else
-#define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X)
-#endif
 
 inline nsISupports*
 ToSupports(nsISupports* aSupports)
 {
   return aSupports;
 }
 
 inline nsISupports*