diff --git a/Meta/Lagom/ClangPlugins/LibJSGCPluginAction.cpp b/Meta/Lagom/ClangPlugins/LibJSGCPluginAction.cpp index 9f018c09cb5..5cb18a9bb4f 100644 --- a/Meta/Lagom/ClangPlugins/LibJSGCPluginAction.cpp +++ b/Meta/Lagom/ClangPlugins/LibJSGCPluginAction.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2024, Matthew Olsson + * Copyright (c) 2025, Idan Horowitz * * SPDX-License-Identifier: BSD-2-Clause */ @@ -130,8 +131,13 @@ static std::optional validate_qualified_type(clang::QualType con return {}; auto const* record_decl = record_type->getAsCXXRecordDecl(); - if (!record_decl->hasDefinition()) - return {}; + if (!record_decl->hasDefinition()) { + // If we don't have a definition (this is a forward declaration), assume that the type inherits from + // GC::Cell instead of not checking it at all. If it does inherit from GC:Cell, this will make sure it's + // visited. If it does not, any attempt to visit it will fail compilation on the visit call itself, + // ensuring it's no longer wrapped in a GC::Ptr. + return QualTypeGCInfo { outer_type, true }; + } return QualTypeGCInfo { outer_type, record_inherits_from_cell(*record_decl) }; } else if (auto const* record = type->getAsCXXRecordDecl()) { diff --git a/Tests/ClangPlugins/LibJSGCTests/missing_member_in_visit_edges.cpp b/Tests/ClangPlugins/LibJSGCTests/missing_member_in_visit_edges.cpp index f2b5fac8026..11621fbb939 100644 --- a/Tests/ClangPlugins/LibJSGCTests/missing_member_in_visit_edges.cpp +++ b/Tests/ClangPlugins/LibJSGCTests/missing_member_in_visit_edges.cpp @@ -8,6 +8,8 @@ #include +class ForwardDeclaredObject; + class TestClass : public JS::Object { JS_OBJECT(TestClass, JS::Object); @@ -21,4 +23,7 @@ class TestClass : public JS::Object { // expected-error@+1 {{GC-allocated member is not visited in TestClass::visit_edges}} JS::Value m_value; + + // expected-error@+1 {{GC-allocated member is not visited in TestClass::visit_edges}} + GC::Ptr m_forward_declared_object; };