diff --git a/include/cppgc/prefinalizer.h b/include/cppgc/prefinalizer.h index bde76429ec..9b7bc0e594 100644 --- a/include/cppgc/prefinalizer.h +++ b/include/cppgc/prefinalizer.h @@ -34,7 +34,7 @@ class PrefinalizerRegistration final { public: \ static bool InvokePreFinalizer(const cppgc::LivenessBroker& liveness_broker, \ void* object) { \ - static_assert(cppgc::internal::IsGarbageCollectedTypeV, \ + static_assert(cppgc::IsGarbageCollectedTypeV, \ "Only garbage collected objects can have prefinalizers"); \ Class* self = static_cast(object); \ if (liveness_broker.IsHeapObjectAlive(self)) return false; \ diff --git a/include/cppgc/type-traits.h b/include/cppgc/type-traits.h index 4d8ab809c8..c7d02db902 100644 --- a/include/cppgc/type-traits.h +++ b/include/cppgc/type-traits.h @@ -5,6 +5,8 @@ #ifndef INCLUDE_CPPGC_TYPE_TRAITS_H_ #define INCLUDE_CPPGC_TYPE_TRAITS_H_ +// This file should stay with minimal dependencies to allow embedder to check +// against Oilpan types without including any other parts. #include namespace cppgc { @@ -12,6 +14,14 @@ namespace cppgc { class Visitor; namespace internal { +template +class BasicMember; +struct DijkstraWriteBarrierPolicy; +struct NoWriteBarrierPolicy; +class StrongMemberTag; +class UntracedMemberTag; +class WeakMemberTag; // Pre-C++17 custom implementation of std::void_t. template @@ -25,18 +35,6 @@ using void_t = typename make_void::type; template struct IsWeak : std::false_type {}; -template class U> -struct IsSubclassOfTemplate { - private: - template - static std::true_type SubclassCheck(U*); - static std::false_type SubclassCheck(...); - - public: - static constexpr bool value = - decltype(SubclassCheck(std::declval()))::value; -}; - // IsTraceMethodConst is used to verify that all Trace methods are marked as // const. It is equivalent to IsTraceable but for a non-const object. template @@ -91,16 +89,56 @@ struct IsGarbageCollectedType< static_assert(sizeof(T), "T must be fully defined"); }; +template +struct IsSubclassOfBasicMemberTemplate { + private: + template + static std::true_type SubclassCheck( + BasicMember*); + static std::false_type SubclassCheck(...); + + public: + static constexpr bool value = + decltype(SubclassCheck(std::declval()))::value; +}; + +template ::value> +struct IsMemberType : std::false_type {}; + template -constexpr bool IsGarbageCollectedTypeV = - internal::IsGarbageCollectedType::value; +struct IsMemberType : std::true_type {}; + +template ::value> +struct IsWeakMemberType : std::false_type {}; + +template +struct IsWeakMemberType : std::true_type {}; + +template ::value> +struct IsUntracedMemberType : std::false_type {}; + +template +struct IsUntracedMemberType : std::true_type {}; + +} // namespace internal template constexpr bool IsGarbageCollectedMixinTypeV = internal::IsGarbageCollectedMixinType::value; - -} // namespace internal - +template +constexpr bool IsGarbageCollectedTypeV = + internal::IsGarbageCollectedType::value; +template +constexpr bool IsMemberTypeV = internal::IsMemberType::value; +template +constexpr bool IsUntracedMemberTypeV = internal::IsUntracedMemberType::value; +template +constexpr bool IsWeakMemberTypeV = internal::IsWeakMemberType::value; template constexpr bool IsWeakV = internal::IsWeak::value; diff --git a/include/cppgc/visitor.h b/include/cppgc/visitor.h index 01f5f20e52..74024c3d0e 100644 --- a/include/cppgc/visitor.h +++ b/include/cppgc/visitor.h @@ -190,7 +190,7 @@ class V8_EXPORT Visitor { static_assert(internal::IsAllocatedOnCompactableSpace::value, "Only references to objects allocated on compactable spaces " "should be registered as movable slots."); - static_assert(!internal::IsGarbageCollectedMixinTypeV, + static_assert(!IsGarbageCollectedMixinTypeV, "Mixin types do not support compaction."); HandleMovableReference(reinterpret_cast(slot)); } diff --git a/test/unittests/heap/cppgc/member-unittest.cc b/test/unittests/heap/cppgc/member-unittest.cc index 64934d69cd..6d2161112b 100644 --- a/test/unittests/heap/cppgc/member-unittest.cc +++ b/test/unittests/heap/cppgc/member-unittest.cc @@ -30,6 +30,27 @@ struct DerivedGCed : GCed { static_assert(!IsWeakV>, "Member is always strong."); static_assert(IsWeakV>, "WeakMember is always weak."); +static_assert(IsMemberTypeV>, "Member must be Member."); +static_assert(!IsMemberTypeV>, + "WeakMember must not be Member."); +static_assert(!IsMemberTypeV>, + "UntracedMember must not be Member."); +static_assert(!IsMemberTypeV, "int must not be Member."); +static_assert(!IsWeakMemberTypeV>, + "Member must not be WeakMember."); +static_assert(IsWeakMemberTypeV>, + "WeakMember must be WeakMember."); +static_assert(!IsWeakMemberTypeV>, + "UntracedMember must not be WeakMember."); +static_assert(!IsWeakMemberTypeV, "int must not be WeakMember."); +static_assert(!IsUntracedMemberTypeV>, + "Member must not be UntracedMember."); +static_assert(!IsUntracedMemberTypeV>, + "WeakMember must not be UntracedMember."); +static_assert(IsUntracedMemberTypeV>, + "UntracedMember must be UntracedMember."); +static_assert(!IsUntracedMemberTypeV, "int must not be UntracedMember."); + struct CustomWriteBarrierPolicy { static size_t InitializingWriteBarriersTriggered; static size_t AssigningWriteBarriersTriggered;