diff --git a/rpcs3/util/shared_ptr.hpp b/rpcs3/util/shared_ptr.hpp index 35d5f98406..5d8eaf5db5 100644 --- a/rpcs3/util/shared_ptr.hpp +++ b/rpcs3/util/shared_ptr.hpp @@ -6,23 +6,47 @@ namespace stx { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundefined_var_template" +#endif + + // Not defined anywhere (and produces a useless warning) + template + extern X sample; + + // Checks whether the cast between two types is the same pointer template constexpr bool is_same_ptr() noexcept { - // I would like to make it a trait if there is some trick. - // And believe it shall possible with constexpr bit_cast. - // Otherwise I hope it will compile in null code anyway. - const auto u = reinterpret_cast(0x11223344556); - const volatile void* x = u; - return static_cast(u) == x; + if constexpr (std::is_void_v || std::is_void_v || std::is_same_v) + { + return true; + } + else if constexpr (std::is_convertible_v) + { + const auto u = &sample; + const volatile void* x = u; + return static_cast(u) == x; + } + else if constexpr (std::is_convertible_v) + { + const auto t = &sample; + const volatile void* x = t; + return static_cast(t) == x; + } + else + { + return false; + } } - // TODO template - constexpr bool is_same_ptr_v = true; + constexpr bool is_same_ptr_cast_v = std::is_convertible_v && is_same_ptr(); - template - constexpr bool is_same_ptr_cast_v = std::is_same_v || (std::is_convertible_v && is_same_ptr_v); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif template class single_ptr; @@ -100,6 +124,9 @@ namespace stx return std::launder(reinterpret_cast(reinterpret_cast(m_ptr) - sizeof(shared_counter))); } + template + friend class single_ptr; + template friend class shared_ptr; @@ -125,7 +152,6 @@ namespace stx single_ptr(single_ptr&& r) noexcept : m_ptr(r.m_ptr) { - ensure(is_same_ptr()); r.m_ptr = nullptr; } @@ -146,7 +172,6 @@ namespace stx template >> single_ptr& operator=(single_ptr&& r) noexcept { - ensure(is_same_ptr()); m_ptr = r.m_ptr; r.m_ptr = nullptr; return *this; @@ -216,11 +241,9 @@ namespace stx } // "Moving" "static cast" - template (std::declval())), typename = std::enable_if_t>> + template (std::declval())), typename = std::enable_if_t()>> explicit operator single_ptr() && noexcept { - ensure(is_same_ptr()); - single_ptr r; r.m_ptr = static_cast(std::exchange(m_ptr, nullptr)); return r; @@ -348,6 +371,9 @@ namespace stx return std::launder(reinterpret_cast(reinterpret_cast(m_ptr) - sizeof(shared_counter))); } + template + friend class shared_ptr; + template friend class atomic_ptr; @@ -369,7 +395,6 @@ namespace stx shared_ptr(const shared_ptr& r) noexcept : m_ptr(r.m_ptr) { - ensure(is_same_ptr()); if (m_ptr) d()->refs++; } @@ -384,7 +409,6 @@ namespace stx shared_ptr(shared_ptr&& r) noexcept : m_ptr(r.m_ptr) { - ensure(is_same_ptr()); r.m_ptr = nullptr; } @@ -392,7 +416,6 @@ namespace stx shared_ptr(single_ptr&& r) noexcept : m_ptr(r.m_ptr) { - ensure(is_same_ptr()); r.m_ptr = nullptr; } @@ -410,7 +433,6 @@ namespace stx template >> shared_ptr& operator=(const shared_ptr& r) noexcept { - ensure(is_same_ptr()); shared_ptr(r).swap(*this); return *this; } @@ -424,7 +446,6 @@ namespace stx template >> shared_ptr& operator=(shared_ptr&& r) noexcept { - ensure(is_same_ptr()); shared_ptr(std::move(r)).swap(*this); return *this; } @@ -432,7 +453,6 @@ namespace stx template >> shared_ptr& operator=(single_ptr&& r) noexcept { - ensure(is_same_ptr()); shared_ptr(std::move(r)).swap(*this); return *this; } @@ -450,11 +470,9 @@ namespace stx } // Converts to unique (single) ptr if reference is 1, otherwise returns null. Nullifies self. - template (std::declval())), typename = std::enable_if_t>> + template (std::declval())), typename = std::enable_if_t()>> explicit operator single_ptr() && noexcept { - ensure(is_same_ptr()); - const auto o = d(); if (m_ptr && !--o->refs) @@ -537,11 +555,9 @@ namespace stx } // Basic "static cast" support - template (std::declval())), typename = std::enable_if_t>> + template (std::declval())), typename = std::enable_if_t()>> explicit operator shared_ptr() const& noexcept { - ensure(is_same_ptr()); - if (m_ptr) { d()->refs++; @@ -553,11 +569,9 @@ namespace stx } // "Moving" "static cast" - template (std::declval())), typename = std::enable_if_t>> + template (std::declval())), typename = std::enable_if_t()>> explicit operator shared_ptr() && noexcept { - ensure(is_same_ptr()); - shared_ptr r; r.m_ptr = static_cast(std::exchange(m_ptr, nullptr)); return r; @@ -592,6 +606,9 @@ namespace stx return d(m_val); } + template + friend class atomic_ptr; + public: using pointer = T*; @@ -614,8 +631,6 @@ namespace stx atomic_ptr(const shared_ptr& r) noexcept : m_val(reinterpret_cast(r.m_ptr) << c_ref_size) { - ensure(is_same_ptr()); - // Obtain a ref + as many refs as an atomic_ptr can additionally reference if (m_val) d()->refs += c_ref_mask + 1; @@ -625,7 +640,6 @@ namespace stx atomic_ptr(shared_ptr&& r) noexcept : m_val(reinterpret_cast(r.m_ptr) << c_ref_size) { - ensure(is_same_ptr()); r.m_ptr = nullptr; if (m_val) @@ -636,7 +650,6 @@ namespace stx atomic_ptr(single_ptr&& r) noexcept : m_val(reinterpret_cast(r.m_ptr) << c_ref_size) { - ensure(is_same_ptr()); r.m_ptr = nullptr; if (m_val) @@ -668,7 +681,6 @@ namespace stx template >> atomic_ptr& operator=(const shared_ptr& r) noexcept { - ensure(is_same_ptr()); store(r); return *this; } @@ -676,7 +688,6 @@ namespace stx template >> atomic_ptr& operator=(shared_ptr&& r) noexcept { - ensure(is_same_ptr()); store(std::move(r)); return *this; } @@ -684,7 +695,6 @@ namespace stx template >> atomic_ptr& operator=(single_ptr&& r) noexcept { - ensure(is_same_ptr()); store(std::move(r)); return *this; } @@ -948,8 +958,6 @@ namespace stx template >> shared_type compare_and_swap(const shared_ptr& cmp, shared_type exch) { - ensure(is_same_ptr()); - shared_type old = cmp; if (compare_exchange(old, std::move(exch))) @@ -966,8 +974,6 @@ namespace stx template >> bool compare_and_swap_test(const shared_ptr& cmp, shared_type exch) { - ensure(is_same_ptr()); - const uptr _old = reinterpret_cast(cmp.m_ptr); const uptr _new = reinterpret_cast(exch.m_ptr); @@ -1007,8 +1013,6 @@ namespace stx template >> shared_type compare_and_swap(const single_ptr& cmp, shared_type exch) { - ensure(is_same_ptr()); - shared_type old = cmp; if (compare_exchange(old, std::move(exch)))