Handle "gaps" in C++ vtables. (#7206)

Not every entry in a C++ vtable corresponds to a function that we want
to import. For the holes, leave a `SemIR::InstId::None` in the vtable.
Also mark vtables that extend a C++ vtable as being non-Carbon-native so
we don't try to lower them (and crash on the `None` entries).

In particular, we leave holes for destructors, since we don't have
destructor declarations on the Carbon side that need to override them.
This commit is contained in:
Richard Smith
2026-05-14 00:38:24 +00:00
committed by GitHub
parent bd918fb33b
commit c9d8b59bbd
6 changed files with 128 additions and 93 deletions
+16 -3
View File
@@ -183,12 +183,24 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,
llvm::SmallVector<SemIR::InstId> vtable;
Set<SemIR::FunctionId> implemented_impls;
bool carbon_native_vtable = true;
if (base_vtable_id.has_value()) {
auto base_vtable_inst_block = context.inst_blocks().Get(
context.vtables().Get(base_vtable_id).virtual_functions_id);
const auto& base_vtable = context.vtables().Get(base_vtable_id);
carbon_native_vtable = base_vtable.carbon_native_vtable;
auto base_vtable_inst_block =
context.inst_blocks().Get(base_vtable.virtual_functions_id);
// TODO: Avoid quadratic search. Perhaps build a map from `NameId` to the
// elements of the top of `vtable_stack`.
for (auto base_vtable_entry_id : base_vtable_inst_block) {
if (!base_vtable_entry_id.has_value()) {
// Foreign vtables may have holes in them for information that we don't
// use. Just skip those entries.
CARBON_CHECK(
!context.vtables().Get(base_vtable_id).carbon_native_vtable);
vtable.push_back(SemIR::InstId::None);
continue;
}
auto [derived_vtable_entry_id, derived_vtable_entry_const_id, fn_id,
specific_id] =
DecomposeVirtualFunction(context.sem_ir(), base_vtable_entry_id,
@@ -265,7 +277,8 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,
return context.vtables().Add(
{{.class_id = class_id,
.virtual_functions_id = context.inst_blocks().Add(vtable)}});
.virtual_functions_id = context.inst_blocks().Add(vtable),
.carbon_native_vtable = carbon_native_vtable}});
}
// Checks that the specified finished class definition is valid and builds and