ClangPlugins: Check for unvisited JS::Value members

JS:Value members might hold a JS::Cell inside, so they must be visited
in ::visit_edges implementations as well.

Fixes #5958.
This commit is contained in:
Idan Horowitz 2025-08-23 19:07:29 +03:00 committed by Jelle Raaijmakers
commit 1eed5bdef7
Notes: github-actions[bot] 2025-08-23 19:22:19 +00:00
2 changed files with 9 additions and 2 deletions

View file

@ -90,6 +90,7 @@ enum class OuterType {
Root, Root,
Ptr, Ptr,
Ref, Ref,
Value,
}; };
struct QualTypeGCInfo { struct QualTypeGCInfo {
@ -133,6 +134,9 @@ static std::optional<QualTypeGCInfo> validate_qualified_type(clang::QualType con
return {}; return {};
return QualTypeGCInfo { outer_type, record_inherits_from_cell(*record_decl) }; return QualTypeGCInfo { outer_type, record_inherits_from_cell(*record_decl) };
} else if (auto const* record = type->getAsCXXRecordDecl()) {
if (record->getQualifiedNameAsString() == "JS::Value")
return QualTypeGCInfo { OuterType::Value, true };
} }
return {}; return {};
@ -202,11 +206,11 @@ bool LibJSGCVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* record)
<< "GC::Ptr"; << "GC::Ptr";
} }
} }
} else if (outer_type == OuterType::GCPtr || outer_type == OuterType::RawPtr) { } else if (outer_type == OuterType::GCPtr || outer_type == OuterType::RawPtr || outer_type == OuterType::Value) {
if (!base_type_inherits_from_cell) { if (!base_type_inherits_from_cell) {
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "Specialization type must inherit from GC::Cell"); auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "Specialization type must inherit from GC::Cell");
diag_engine.Report(field->getLocation(), diag_id); diag_engine.Report(field->getLocation(), diag_id);
} else if (outer_type == OuterType::GCPtr) { } else if (outer_type != OuterType::RawPtr) {
fields_that_need_visiting.push_back(field); fields_that_need_visiting.push_back(field);
} }
} else if (outer_type == OuterType::Root) { } else if (outer_type == OuterType::Root) {

View file

@ -18,4 +18,7 @@ class TestClass : public JS::Object {
// expected-error@+1 {{GC-allocated member is not visited in TestClass::visit_edges}} // expected-error@+1 {{GC-allocated member is not visited in TestClass::visit_edges}}
GC::Ptr<JS::Object> m_object; GC::Ptr<JS::Object> m_object;
// expected-error@+1 {{GC-allocated member is not visited in TestClass::visit_edges}}
JS::Value m_value;
}; };