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

Code before:
    context.TODO(AddImportIRInst(context.sem_ir(), clang_decl->getLocation()),
                 "Unsupported: field declaration has unhandled type or kind");
    return SemIR::ErrorInst::InstId;
  }

  context.TODO(AddImportIRInst(context.sem_ir(), clang_decl->getLocation()),
               llvm::formatv("Unsupported: Declaration type {0}",
                             clang_decl->getDeclKindName()));
  return SemIR::ErrorInst::InstId;
}

// Attempts to import a set of declarations. Returns `false` if an error was
// produced, `true` otherwise.
static auto ImportDeclSet(Context& context, SemIR::LocId loc_id,
                          ImportWorklist& decls) -> bool {
  // Walk the dependency graph in depth-first order, and import declarations
  // once we've imported all of their dependencies.
  while (!decls.worklist.empty()) {
    auto& item = decls.worklist.back();
    if (!item.added_dependencies) {
      // We might have already imported this declaration as a dependency of
      // another declaration in the worklist. If so, don't visit it again.
      if (IsClangDeclImported(context, item.decl)) {
        decls.worklist.pop_back();
        continue;
      }

      // First time visiting this declaration (preorder): add its dependencies
      // to the work list.
      item.added_dependencies = true;
      AddDependentUnimportedDecls(context, item.decl, decls);
    } else {
      // Second time visiting this declaration (postorder): its dependencies are
      // already imported, so we can import it now.
      auto* decl = decls.worklist.pop_back_val().decl;
      auto inst_id = ImportDeclAfterDependencies(context, loc_id, decl);
      CARBON_CHECK(inst_id.has_value());
      if (inst_id == SemIR::ErrorInst::InstId) {
        return false;
      }
      CARBON_CHECK(IsClangDeclImported(context, decl));
    }
  }

  return true;
}

// Imports a declaration from Clang to Carbon. If successful, returns the
// instruction for the new Carbon declaration. All unimported dependencies are
// imported first.
static auto ImportDeclAndDependencies(Context& context, SemIR::LocId loc_id,

Review comment (refactor):
How often would you expect this to happen? Could it end up happening linear-ish number of times?

Mostly wondering if it would be worthwhile to do the check before adding to the worklist rather than here. Ah, but we already do that. Maybe mention in this comment that even though we avoid adding already imported declarations, we can still end up with duplicates where both got added before either was imported?

Code after:
        existing_inst_id.has_value()) {
      return existing_inst_id;
    }
    context.TODO(AddImportIRInst(context.sem_ir(), clang_decl->getLocation()),
                 "Unsupported: field declaration has unhandled type or kind");
    return SemIR::ErrorInst::InstId;
  }

  context.TODO(AddImportIRInst(context.sem_ir(), clang_decl->getLocation()),
               llvm::formatv("Unsupported: Declaration type {0}",
                             clang_decl->getDeclKindName()));
  return SemIR::ErrorInst::InstId;
}

// Attempts to import a set of declarations. Returns `false` if an error was
// produced, `true` otherwise.
static auto ImportDeclSet(Context& context, SemIR::LocId loc_id,
                          ImportWorklist& worklist) -> bool {
  // Walk the dependency graph in depth-first order, and import declarations
  // once we've imported all of their dependencies.
  while (!worklist.empty()) {
    auto& item = worklist.back();
    if (!item.added_dependencies) {
      // Skip items we've already imported. We checked this when initially
      // adding the item to the worklist, but it might have been added to the
      // worklist twice before the first time we visited it. For example, this
      // happens for `fn F(a: Cpp.T, b: Cpp.T)`.
      if (IsClangDeclImported(context, item.decl)) {
        worklist.pop_back();
        continue;
      }

      // First time visiting this declaration (preorder): add its dependencies
      // to the work list.
      item.added_dependencies = true;
      AddDependentUnimportedDecls(context, item.decl, worklist);
    } else {
      // Second time visiting this declaration (postorder): its dependencies are
      // already imported, so we can import it now.
      auto* decl = worklist.pop_back_val().decl;
      auto inst_id = ImportDeclAfterDependencies(context, loc_id, decl);
      CARBON_CHECK(inst_id.has_value());
      if (inst_id == SemIR::ErrorInst::InstId) {
        return false;
      }
      CARBON_CHECK(IsClangDeclImported(context, decl));
    }
  }

  return true;
}