diff options
author | Andreas Kling <kling@serenityos.org> | 2020-04-05 11:11:07 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-04-05 11:19:00 +0200 |
commit | 1d468ed6d32675e6a48a62ce7e3ea2a15b9ca777 (patch) | |
tree | 0802da0fb4127bd1f44656408df10361c59d0743 /AK | |
parent | 058c614110da17336fdf0f4204bc9c030b3821ce (diff) | |
download | serenity-1d468ed6d32675e6a48a62ce7e3ea2a15b9ca777.zip |
AK: Stop allowing implicit downcast with RefPtr and NonnullRefPtr
We were allowing this dangerous kind of thing:
RefPtr<Base> base;
RefPtr<Derived> derived = base;
This patch changes the {Nonnull,}RefPtr constructors so this is no
longer possible.
To downcast one of these pointers, there is now static_ptr_cast<T>:
RefPtr<Derived> derived = static_ptr_cast<Derived>(base);
Fixing this exposed a ton of cowboy-downcasts in various places,
which we're now forced to fix. :^)
Diffstat (limited to 'AK')
-rw-r--r-- | AK/NonnullRefPtr.h | 6 | ||||
-rw-r--r-- | AK/RefPtr.h | 21 |
2 files changed, 20 insertions, 7 deletions
diff --git a/AK/NonnullRefPtr.h b/AK/NonnullRefPtr.h index 426c4f5dca..3710f07534 100644 --- a/AK/NonnullRefPtr.h +++ b/AK/NonnullRefPtr.h @@ -68,7 +68,7 @@ public: template<typename U> RETURN_TYPESTATE(unconsumed) NonnullRefPtr(const U& object) - : m_ptr(&const_cast<T&>(static_cast<const T&>(object))) + : m_ptr(&const_cast<U&>(object)) { m_ptr->ref(); } @@ -85,7 +85,7 @@ public: template<typename U> RETURN_TYPESTATE(unconsumed) NonnullRefPtr(NonnullRefPtr<U>&& other) - : m_ptr(static_cast<T*>(&other.leak_ref())) + : m_ptr(&other.leak_ref()) { } RETURN_TYPESTATE(unconsumed) @@ -97,7 +97,7 @@ public: template<typename U> RETURN_TYPESTATE(unconsumed) NonnullRefPtr(const NonnullRefPtr<U>& other) - : m_ptr(const_cast<T*>(static_cast<const T*>((other.ptr())))) + : m_ptr(const_cast<U*>(other.ptr())) { m_ptr->ref(); } diff --git a/AK/RefPtr.h b/AK/RefPtr.h index 6e5a9554b5..3c69456526 100644 --- a/AK/RefPtr.h +++ b/AK/RefPtr.h @@ -71,20 +71,20 @@ public: } template<typename U> RefPtr(const NonnullRefPtr<U>& other) - : m_ptr(static_cast<T*>(const_cast<U*>(other.ptr()))) + : m_ptr(const_cast<U*>(other.ptr())) { ASSERT(m_ptr); m_ptr->ref(); } template<typename U> RefPtr(NonnullRefPtr<U>&& other) - : m_ptr(static_cast<T*>(&other.leak_ref())) + : m_ptr(&other.leak_ref()) { ASSERT(m_ptr); } template<typename U> RefPtr(RefPtr<U>&& other) - : m_ptr(static_cast<T*>(other.leak_ref())) + : m_ptr(other.leak_ref()) { } RefPtr(const RefPtr& other) @@ -94,7 +94,7 @@ public: } template<typename U> RefPtr(const RefPtr<U>& other) - : m_ptr(static_cast<T*>(const_cast<U*>(other.ptr()))) + : m_ptr(const_cast<U*>(other.ptr())) { ref_if_not_null(m_ptr); } @@ -282,6 +282,19 @@ struct Traits<RefPtr<T>> : public GenericTraits<RefPtr<T>> { static bool equals(const RefPtr<T>& a, const RefPtr<T>& b) { return a.ptr() == b.ptr(); } }; +template<typename T, typename U> +inline NonnullRefPtr<T> static_ptr_cast(const NonnullRefPtr<U>& ptr) +{ + return NonnullRefPtr<T>(static_cast<const T&>(*ptr)); +} + +template<typename T, typename U> +inline RefPtr<T> static_ptr_cast(const RefPtr<U>& ptr) +{ + return RefPtr<T>(static_cast<const T*>(ptr.ptr())); +} + } using AK::RefPtr; +using AK::static_ptr_cast; |