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,
Ptr,
Ref,
Value,
};
struct QualTypeGCInfo {
@ -133,6 +134,9 @@ static std::optional<QualTypeGCInfo> validate_qualified_type(clang::QualType con
return {};
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 {};
@ -202,11 +206,11 @@ bool LibJSGCVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* record)
<< "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) {
auto diag_id = diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Error, "Specialization type must inherit from GC::Cell");
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);
}
} 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}}
GC::Ptr<JS::Object> m_object;
// expected-error@+1 {{GC-allocated member is not visited in TestClass::visit_edges}}
JS::Value m_value;
};