summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-05 11:11:07 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-05 11:19:00 +0200
commit1d468ed6d32675e6a48a62ce7e3ea2a15b9ca777 (patch)
tree0802da0fb4127bd1f44656408df10361c59d0743 /AK
parent058c614110da17336fdf0f4204bc9c030b3821ce (diff)
downloadserenity-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.h6
-rw-r--r--AK/RefPtr.h21
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;