Repository: carbon-language/carbon-lang
File: toolchain/check/check_unit.cpp (C++)

Code before:
    auto parse_kind = context_.parse_tree().node_kind(node_id);
    switch (parse_kind) {
#define CARBON_PARSE_NODE_KIND(Name)                              \
  case Parse::NodeKind::Name: {                                   \
    result = HandleParseNode(context_, Parse::Name##Id(node_id)); \
    break;                                                        \
  }
#include "toolchain/parse/node_kind.def"
    }

    if (!result) {
      CARBON_CHECK(
          unit_and_imports_->err_tracker.seen_error(),
          "HandleParseNode for `{0}` returned false without diagnosing.",
          parse_kind);
      return false;
    }
    traversal.Handle(parse_kind);
  }
  return true;
}

auto CheckUnit::CheckRequiredDeclarations() -> void {
  for (const auto& function : context_.functions().array_ref()) {
    if (!function.first_owning_decl_id.has_value() &&
        function.extern_library_id == this->context_.sem_ir().library_id()) {
      CARBON_DIAGNOSTIC(MissingDeclarationInApi, Error,
                        "no owning function declaration or definition found "
                        "for declaration in non-owning file");
      emitter_.Emit(function.non_owning_decl_id, MissingDeclarationInApi);
    }
  }
}

auto CheckUnit::CheckRequiredDefinitions() -> void {
  CARBON_DIAGNOSTIC(MissingDefinitionInImpl, Error,
                    "no definition found for declaration in impl file");
  // Note that more required definitions can be added during this loop.
  for (size_t i = 0; i != context_.definitions_required().size(); ++i) {
    SemIR::InstId decl_inst_id = context_.definitions_required()[i];
    SemIR::Inst decl_inst = context_.insts().Get(decl_inst_id);
    CARBON_KIND_SWITCH(context_.insts().Get(decl_inst_id)) {
      case CARBON_KIND(SemIR::ClassDecl class_decl): {
        if (!context_.classes().Get(class_decl.class_id).is_defined()) {
          emitter_.Emit(decl_inst_id, MissingDefinitionInImpl);
        }
        break;
      }
      case CARBON_KIND(SemIR::FunctionDecl function_decl): {
        if (context_.functions().Get(function_decl.function_id).definition_id ==
            SemIR::InstId::None) {

Review comment (suggestion):
Can you add a cross-package test, such as:

```
// --- cross_package_extern.carbon

package OtherPackage library "[[@TEST_NAME]]";

extern library "cross_package" fn Extern();

// --- cross_package.carbon

library "[[@TEST_NAME]]";

// This call causes the function to be imported.
fn F() { OtherPackage.Extern(); }
```

Note here that the library name matches but the package name does not.

I suspect this is going to warn. Maybe this should be a TODO that the code needs to verify the function comes from the same package? (seems fine to split out PRs)

Code after:
      context_.TODO(node_id, "handle invalid parse trees in `check`");
      return false;
    }

    bool result;
    auto parse_kind = context_.parse_tree().node_kind(node_id);
    switch (parse_kind) {
#define CARBON_PARSE_NODE_KIND(Name)                              \
  case Parse::NodeKind::Name: {                                   \
    result = HandleParseNode(context_, Parse::Name##Id(node_id)); \
    break;                                                        \
  }
#include "toolchain/parse/node_kind.def"
    }

    if (!result) {
      CARBON_CHECK(
          unit_and_imports_->err_tracker.seen_error(),
          "HandleParseNode for `{0}` returned false without diagnosing.",
          parse_kind);
      return false;
    }
    traversal.Handle(parse_kind);
  }
  return true;
}

auto CheckUnit::CheckRequiredDeclarations() -> void {
  for (const auto& function : context_.functions().array_ref()) {
    if (!function.first_owning_decl_id.has_value() &&
        function.extern_library_id == context_.sem_ir().library_id()) {
      auto function_loc_id =
          context_.insts().GetLocId(function.non_owning_decl_id);
      CARBON_CHECK(function_loc_id.is_import_ir_inst_id());
      auto import_ir_id = context_.sem_ir()
                              .import_ir_insts()
                              .Get(function_loc_id.import_ir_inst_id())
                              .ir_id;
      auto& import_ir = context_.import_irs().Get(import_ir_id);
      if (import_ir.sem_ir->package_id().has_value() !=
          context_.sem_ir().package_id().has_value()) {
        continue;
      }

      CARBON_DIAGNOSTIC(
          MissingOwningDeclarationInApi, Error,
          "owning declaration required for non-owning declaration");
      if (!import_ir.sem_ir->package_id().has_value() &&
          !context_.sem_ir().package_id().has_value()) {
        emitter_.Emit(function.non_owning_decl_id,
                      MissingOwningDeclarationInApi);