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. :^)
This commit is contained in:
Andreas Kling 2020-04-05 11:11:07 +02:00
parent 058c614110
commit 1d468ed6d3
Notes: sideshowbarker 2024-07-19 07:54:24 +09:00
11 changed files with 68 additions and 54 deletions

View File

@ -68,7 +68,7 @@ public:
template<typename U> template<typename U>
RETURN_TYPESTATE(unconsumed) RETURN_TYPESTATE(unconsumed)
NonnullRefPtr(const U& object) NonnullRefPtr(const U& object)
: m_ptr(&const_cast<T&>(static_cast<const T&>(object))) : m_ptr(&const_cast<U&>(object))
{ {
m_ptr->ref(); m_ptr->ref();
} }
@ -85,7 +85,7 @@ public:
template<typename U> template<typename U>
RETURN_TYPESTATE(unconsumed) RETURN_TYPESTATE(unconsumed)
NonnullRefPtr(NonnullRefPtr<U>&& other) NonnullRefPtr(NonnullRefPtr<U>&& other)
: m_ptr(static_cast<T*>(&other.leak_ref())) : m_ptr(&other.leak_ref())
{ {
} }
RETURN_TYPESTATE(unconsumed) RETURN_TYPESTATE(unconsumed)
@ -97,7 +97,7 @@ public:
template<typename U> template<typename U>
RETURN_TYPESTATE(unconsumed) RETURN_TYPESTATE(unconsumed)
NonnullRefPtr(const NonnullRefPtr<U>& other) 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(); m_ptr->ref();
} }

View File

@ -71,20 +71,20 @@ public:
} }
template<typename U> template<typename U>
RefPtr(const NonnullRefPtr<U>& other) 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); ASSERT(m_ptr);
m_ptr->ref(); m_ptr->ref();
} }
template<typename U> template<typename U>
RefPtr(NonnullRefPtr<U>&& other) RefPtr(NonnullRefPtr<U>&& other)
: m_ptr(static_cast<T*>(&other.leak_ref())) : m_ptr(&other.leak_ref())
{ {
ASSERT(m_ptr); ASSERT(m_ptr);
} }
template<typename U> template<typename U>
RefPtr(RefPtr<U>&& other) RefPtr(RefPtr<U>&& other)
: m_ptr(static_cast<T*>(other.leak_ref())) : m_ptr(other.leak_ref())
{ {
} }
RefPtr(const RefPtr& other) RefPtr(const RefPtr& other)
@ -94,7 +94,7 @@ public:
} }
template<typename U> template<typename U>
RefPtr(const RefPtr<U>& other) 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); 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(); } 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::RefPtr;
using AK::static_ptr_cast;

View File

@ -51,5 +51,5 @@ private:
BoardListModel(); BoardListModel();
JsonArray m_boards; JsonArray m_boards;
RefPtr<Core::HttpJob> m_pending_job; RefPtr<Core::NetworkJob> m_pending_job;
}; };

View File

@ -63,5 +63,5 @@ private:
String m_board { "g" }; String m_board { "g" };
JsonArray m_catalog; JsonArray m_catalog;
RefPtr<Core::HttpJob> m_pending_job; RefPtr<Core::NetworkJob> m_pending_job;
}; };

View File

@ -307,8 +307,8 @@ KResult TmpFSInode::add_child(InodeIdentifier child_id, const StringView& name,
String owned_name = name; String owned_name = name;
FS::DirectoryEntry entry = { owned_name.characters(), owned_name.length(), child_id, 0 }; FS::DirectoryEntry entry = { owned_name.characters(), owned_name.length(), child_id, 0 };
RefPtr<Inode> child_tmp = fs().get_inode(child_id); auto child_tmp = fs().get_inode(child_id);
NonnullRefPtr<TmpFSInode> child = static_cast<NonnullRefPtr<TmpFSInode>>(child_tmp.release_nonnull()); auto child = static_ptr_cast<TmpFSInode>(child_tmp.release_nonnull());
m_children.set(owned_name, { entry, move(child) }); m_children.set(owned_name, { entry, move(child) });
set_metadata_dirty(true); set_metadata_dirty(true);

View File

@ -137,11 +137,11 @@ class Declaration : public Statement {
class FunctionNode { class FunctionNode {
public: public:
const FlyString& name() const { return m_name; } const FlyString& name() const { return m_name; }
const ScopeNode& body() const { return *m_body; } const Statement& body() const { return *m_body; }
const Vector<FlyString>& parameters() const { return m_parameters; }; const Vector<FlyString>& parameters() const { return m_parameters; };
protected: protected:
FunctionNode(const FlyString& name, NonnullRefPtr<ScopeNode> body, Vector<FlyString> parameters = {}) FunctionNode(const FlyString& name, NonnullRefPtr<Statement> body, Vector<FlyString> parameters = {})
: m_name(name) : m_name(name)
, m_body(move(body)) , m_body(move(body))
, m_parameters(move(parameters)) , m_parameters(move(parameters))
@ -152,7 +152,7 @@ protected:
private: private:
FlyString m_name; FlyString m_name;
NonnullRefPtr<ScopeNode> m_body; NonnullRefPtr<Statement> m_body;
const Vector<FlyString> m_parameters; const Vector<FlyString> m_parameters;
}; };
@ -162,7 +162,7 @@ class FunctionDeclaration final
public: public:
static bool must_have_name() { return true; } static bool must_have_name() { return true; }
FunctionDeclaration(String name, NonnullRefPtr<ScopeNode> body, Vector<FlyString> parameters = {}) FunctionDeclaration(String name, NonnullRefPtr<Statement> body, Vector<FlyString> parameters = {})
: FunctionNode(move(name), move(body), move(parameters)) : FunctionNode(move(name), move(body), move(parameters))
{ {
} }
@ -179,7 +179,7 @@ class FunctionExpression final : public Expression
public: public:
static bool must_have_name() { return false; } static bool must_have_name() { return false; }
FunctionExpression(const FlyString& name, NonnullRefPtr<ScopeNode> body, Vector<FlyString> parameters = {}) FunctionExpression(const FlyString& name, NonnullRefPtr<Statement> body, Vector<FlyString> parameters = {})
: FunctionNode(name, move(body), move(parameters)) : FunctionNode(name, move(body), move(parameters))
{ {
} }
@ -241,14 +241,14 @@ private:
class WhileStatement : public Statement { class WhileStatement : public Statement {
public: public:
WhileStatement(NonnullRefPtr<Expression> test, NonnullRefPtr<ScopeNode> body) WhileStatement(NonnullRefPtr<Expression> test, NonnullRefPtr<Statement> body)
: m_test(move(test)) : m_test(move(test))
, m_body(move(body)) , m_body(move(body))
{ {
} }
const Expression& test() const { return *m_test; } const Expression& test() const { return *m_test; }
const ScopeNode& body() const { return *m_body; } const Statement& body() const { return *m_body; }
virtual Value execute(Interpreter&) const override; virtual Value execute(Interpreter&) const override;
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
@ -257,19 +257,19 @@ private:
virtual const char* class_name() const override { return "WhileStatement"; } virtual const char* class_name() const override { return "WhileStatement"; }
NonnullRefPtr<Expression> m_test; NonnullRefPtr<Expression> m_test;
NonnullRefPtr<ScopeNode> m_body; NonnullRefPtr<Statement> m_body;
}; };
class DoWhileStatement : public Statement { class DoWhileStatement : public Statement {
public: public:
DoWhileStatement(NonnullRefPtr<Expression> test, NonnullRefPtr<ScopeNode> body) DoWhileStatement(NonnullRefPtr<Expression> test, NonnullRefPtr<Statement> body)
: m_test(move(test)) : m_test(move(test))
, m_body(move(body)) , m_body(move(body))
{ {
} }
const Expression& test() const { return *m_test; } const Expression& test() const { return *m_test; }
const ScopeNode& body() const { return *m_body; } const Statement& body() const { return *m_body; }
virtual Value execute(Interpreter&) const override; virtual Value execute(Interpreter&) const override;
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
@ -278,12 +278,12 @@ private:
virtual const char* class_name() const override { return "DoWhileStatement"; } virtual const char* class_name() const override { return "DoWhileStatement"; }
NonnullRefPtr<Expression> m_test; NonnullRefPtr<Expression> m_test;
NonnullRefPtr<ScopeNode> m_body; NonnullRefPtr<Statement> m_body;
}; };
class ForStatement : public Statement { class ForStatement : public Statement {
public: public:
ForStatement(RefPtr<ASTNode> init, RefPtr<Expression> test, RefPtr<Expression> update, NonnullRefPtr<ScopeNode> body) ForStatement(RefPtr<ASTNode> init, RefPtr<Expression> test, RefPtr<Expression> update, NonnullRefPtr<Statement> body)
: m_init(move(init)) : m_init(move(init))
, m_test(move(test)) , m_test(move(test))
, m_update(move(update)) , m_update(move(update))
@ -294,7 +294,7 @@ public:
const ASTNode* init() const { return m_init; } const ASTNode* init() const { return m_init; }
const Expression* test() const { return m_test; } const Expression* test() const { return m_test; }
const Expression* update() const { return m_update; } const Expression* update() const { return m_update; }
const ScopeNode& body() const { return *m_body; } const Statement& body() const { return *m_body; }
virtual Value execute(Interpreter&) const override; virtual Value execute(Interpreter&) const override;
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
@ -305,7 +305,7 @@ private:
RefPtr<ASTNode> m_init; RefPtr<ASTNode> m_init;
RefPtr<Expression> m_test; RefPtr<Expression> m_test;
RefPtr<Expression> m_update; RefPtr<Expression> m_update;
NonnullRefPtr<ScopeNode> m_body; NonnullRefPtr<Statement> m_body;
}; };
enum class BinaryOp { enum class BinaryOp {
@ -569,7 +569,7 @@ private:
virtual const char* class_name() const override { return "UpdateExpression"; } virtual const char* class_name() const override { return "UpdateExpression"; }
UpdateOp m_op; UpdateOp m_op;
NonnullRefPtr<Identifier> m_argument; NonnullRefPtr<Expression> m_argument;
bool m_prefixed; bool m_prefixed;
}; };

View File

@ -33,7 +33,7 @@
namespace JS { namespace JS {
ScriptFunction::ScriptFunction(const ScopeNode& body, Vector<FlyString> parameters) ScriptFunction::ScriptFunction(const Statement& body, Vector<FlyString> parameters)
: m_body(body) : m_body(body)
, m_parameters(move(parameters)) , m_parameters(move(parameters))
{ {

View File

@ -32,10 +32,10 @@ namespace JS {
class ScriptFunction final : public Function { class ScriptFunction final : public Function {
public: public:
ScriptFunction(const ScopeNode& body, Vector<FlyString> parameters = {}); ScriptFunction(const Statement& body, Vector<FlyString> parameters = {});
virtual ~ScriptFunction(); virtual ~ScriptFunction();
const ScopeNode& body() const { return m_body; } const Statement& body() const { return m_body; }
const Vector<FlyString>& parameters() const { return m_parameters; }; const Vector<FlyString>& parameters() const { return m_parameters; };
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;
@ -48,7 +48,7 @@ private:
static Value length_getter(Interpreter&); static Value length_getter(Interpreter&);
static void length_setter(Interpreter&, Value); static void length_setter(Interpreter&, Value);
NonnullRefPtr<ScopeNode> m_body; NonnullRefPtr<Statement> m_body;
const Vector<FlyString> m_parameters; const Vector<FlyString> m_parameters;
}; };

View File

@ -221,7 +221,7 @@ void Document::layout()
if (!m_layout_root) { if (!m_layout_root) {
LayoutTreeBuilder tree_builder; LayoutTreeBuilder tree_builder;
m_layout_root = tree_builder.build(*this); m_layout_root = static_ptr_cast<LayoutDocument>(tree_builder.build(*this));
} }
m_layout_root->layout(); m_layout_root->layout();
m_layout_root->set_needs_display(); m_layout_root->set_needs_display();

View File

@ -153,39 +153,40 @@ NonnullRefPtr<StyleValue> parse_css_value(const StringView& string)
return StringStyleValue::create(string); return StringStyleValue::create(string);
} }
RefPtr<StyleValue> parse_line_width(const StringView& part) RefPtr<LengthStyleValue> parse_line_width(const StringView& part)
{ {
NonnullRefPtr<StyleValue> value = parse_css_value(part); NonnullRefPtr<StyleValue> value = parse_css_value(part);
if (value->is_length()) if (value->is_length())
return value; return static_ptr_cast<LengthStyleValue>(value);
return nullptr; return nullptr;
} }
RefPtr<StyleValue> parse_color(const StringView& part) RefPtr<ColorStyleValue> parse_color(const StringView& part)
{ {
NonnullRefPtr<StyleValue> value = parse_css_value(part); NonnullRefPtr<StyleValue> value = parse_css_value(part);
if (value->is_color()) if (value->is_color())
return value; return static_ptr_cast<ColorStyleValue>(value);
return nullptr; return nullptr;
} }
RefPtr<StyleValue> parse_line_style(const StringView& part) RefPtr<StringStyleValue> parse_line_style(const StringView& part)
{ {
NonnullRefPtr<StyleValue> value = parse_css_value(part); NonnullRefPtr<StyleValue> parsed_value = parse_css_value(part);
if (value->is_string()) { if (!parsed_value->is_string())
if (value->to_string() == "dotted") return nullptr;
return value; auto value = static_ptr_cast<StringStyleValue>(parsed_value);
if (value->to_string() == "dashed") if (value->to_string() == "dotted")
return value; return value;
if (value->to_string() == "solid") if (value->to_string() == "dashed")
return value; return value;
if (value->to_string() == "double") if (value->to_string() == "solid")
return value; return value;
if (value->to_string() == "groove") if (value->to_string() == "double")
return value; return value;
if (value->to_string() == "ridge") if (value->to_string() == "groove")
return value; return value;
} if (value->to_string() == "ridge")
return value;
return nullptr; return nullptr;
} }

View File

@ -36,8 +36,8 @@ RefPtr<StyleDeclaration> parse_css_declaration(const StringView&);
NonnullRefPtr<StyleValue> parse_css_value(const StringView&); NonnullRefPtr<StyleValue> parse_css_value(const StringView&);
Optional<Selector> parse_selector(const StringView&); Optional<Selector> parse_selector(const StringView&);
RefPtr<StyleValue> parse_line_width(const StringView&); RefPtr<LengthStyleValue> parse_line_width(const StringView&);
RefPtr<StyleValue> parse_color(const StringView&); RefPtr<ColorStyleValue> parse_color(const StringView&);
RefPtr<StyleValue> parse_line_style(const StringView&); RefPtr<StringStyleValue> parse_line_style(const StringView&);
} }