Start adding extern logic for functions. (#3809)

This starts propagating is_extern on import, and warns when merging an
imported non-extern declaration with a local non-extern declaration.
Note this doesn't address import conflicts yet (i.e., two libraries
define an equivalent name) because they don't call merge logic.

On merge, I'm only setting values when new_is_definition because I think
it better matches the comment and resulting behavior. Note I now set
them even for bad redefinitions; I think this matches the comment, and
there's not a perfect choice here. I could change the flow back if
preferred.

Note this puts a spotlight on invalid nodes on imported decls, which I
think I'm going to need to address now. This isn't addressed by
ImportRef logic directly because the Function's decl_id is a
FunctionDecl, rather than the ImportRef that led to it. While I could
add the ImportRef link to each decl, I think adjusting the associated
NodeId is a better approach.
This commit is contained in:
Jon Ross-Perkins
2024-03-27 22:40:28 +00:00
committed by GitHub
parent 6c458ffe7e
commit a79027120a
11 changed files with 748 additions and 163 deletions
+15 -7
View File
@@ -165,14 +165,22 @@ static auto BuildFunctionDecl(Context& context,
}
// Check whether this is a redeclaration.
auto existing_id =
auto prev_id =
context.decl_name_stack().LookupOrAddName(name_context, lookup_result_id);
if (existing_id.is_valid()) {
if (auto existing_function_decl =
context.insts().Get(existing_id).TryAs<SemIR::FunctionDecl>()) {
if (MergeFunctionRedecl(context, node_id, function_info,
if (prev_id.is_valid()) {
auto prev_inst = context.insts().Get(prev_id);
bool prev_is_import = false;
if (prev_inst.Is<SemIR::ImportRefUsed>()) {
prev_inst =
context.insts().Get(context.constant_values().Get(prev_id).inst_id());
prev_is_import = true;
}
if (auto existing_function_decl = prev_inst.TryAs<SemIR::FunctionDecl>()) {
if (MergeFunctionRedecl(context, node_id, function_info, is_definition,
existing_function_decl->function_id,
is_definition)) {
prev_is_import)) {
// When merging, use the existing function rather than adding a new one.
function_decl.function_id = existing_function_decl->function_id;
}
@@ -180,7 +188,7 @@ static auto BuildFunctionDecl(Context& context,
// This is a redeclaration of something other than a function. This
// includes the case where an associated function redeclares another
// associated function.
context.DiagnoseDuplicateName(function_info.decl_id, existing_id);
context.DiagnoseDuplicateName(function_info.decl_id, prev_id);
}
}