Bug 1303302 - Add IsDestructible trait in TypeTraits and use it for refcounted type static check. r?froydnj
MozReview-Commit-ID: G3YFhrJngq0
--- 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*