Implement correctly overriding dependent virtual functions (#5804)

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
David Blaikie
2025-07-17 16:14:50 +00:00
committed by GitHub
co-authored by Jon Ross-Perkins
parent 9f67fa4b0f
commit 3bf98e9bc2
5 changed files with 1295 additions and 33 deletions
+8 -17
View File
@@ -174,9 +174,11 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,
context.vtables().Get(base_vtable_id).virtual_functions_id);
// TODO: Avoid quadratic search. Perhaps build a map from `NameId` to the
// elements of the top of `vtable_stack`.
for (auto fn_decl_id : base_vtable_inst_block) {
auto fn_decl = GetCalleeFunction(context.sem_ir(), fn_decl_id);
const auto& fn = context.functions().Get(fn_decl.function_id);
for (auto base_vtable_entry_id : base_vtable_inst_block) {
auto [derived_vtable_entry_id, fn_id, specific_id] =
DecomposeVirtualFunction(context.sem_ir(), base_vtable_entry_id,
base_class_specific_id);
const auto& fn = context.sem_ir().functions().Get(fn_id);
const auto* i = llvm::find_if(
vtable_contents, [&](SemIR::InstId override_fn_decl_id) -> bool {
const auto& override_fn = context.functions().Get(
@@ -190,25 +192,14 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,
if (i != vtable_contents.end()) {
auto& override_fn = context.functions().Get(
context.insts().GetAs<SemIR::FunctionDecl>(*i).function_id);
// TODO: Support generic base classes, rather than passing
// `SpecificId::None`. This'll need to `GetConstantValueInSpecific` for
// the base function, then extract the specific from that for use here.
CheckFunctionTypeMatches(context, override_fn, fn,
SemIR::SpecificId::None,
CheckFunctionTypeMatches(context, override_fn, fn, specific_id,
/*check_syntax=*/false,
/*check_self=*/false);
fn_decl_id = build_specific_function(*i);
derived_vtable_entry_id = build_specific_function(*i);
override_fn.virtual_index = vtable.size();
CARBON_CHECK(override_fn.virtual_index == fn.virtual_index);
} else {
// Remap the base's vtable entry to the appropriate constant usable in
// the context of the derived class (for the specific for the base
// class, for instance)..
fn_decl_id = context.sem_ir().constant_values().GetInstId(
GetConstantValueInSpecific(context.sem_ir(), base_class_specific_id,
fn_decl_id));
}
vtable.push_back(fn_decl_id);
vtable.push_back(derived_vtable_entry_id);
}
}