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

Code before:

  // Compute the class's object representation.
  auto object_repr_id = ImportClassObjectRepr(
      context, class_id, import_ir_inst_id, class_inst_id, clang_def);
  class_info.complete_type_witness_id = AddInst<SemIR::CompleteTypeWitness>(
      context, import_ir_inst_id,
      {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),
       .object_repr_type_inst_id = object_repr_id});

  class_info.body_block_id = context.inst_block_stack().Pop();
}

auto ImportCppClassDefinition(Context& context, SemIR::LocId loc_id,
                              SemIR::ClassId class_id,
                              SemIR::ClangDeclId clang_decl_id) -> bool {
  clang::ASTUnit* ast = context.sem_ir().cpp_ast();
  CARBON_CHECK(ast);

  auto* clang_decl = cast<clang::CXXRecordDecl>(
      context.sem_ir().clang_decls().Get(clang_decl_id).decl);
  auto class_inst_id = context.types().GetAsTypeInstId(
      context.classes().Get(class_id).first_owning_decl_id);

  // TODO: Map loc_id into a clang location and use it for diagnostics if
  // instantiation fails, instead of annotating the diagnostic with another
  // location.
  clang::SourceLocation loc = clang_decl->getLocation();
  Diagnostics::AnnotationScope annotate_diagnostics(
      &context.emitter(), [&](auto& builder) {
        CARBON_DIAGNOSTIC(InCppTypeCompletion, Note,
                          "while completing C++ class type {0}", SemIR::TypeId);
        builder.Note(loc_id, InCppTypeCompletion,
                     context.classes().Get(class_id).self_type_id);
      });

  // Ask Clang whether the type is complete. This triggers template
  // instantiation if necessary.
  clang::DiagnosticErrorTrap trap(ast->getDiagnostics());
  if (!ast->getSema().isCompleteType(
          loc, context.ast_context().getRecordType(clang_decl))) {
    // Type is incomplete. Nothing more to do, but tell the caller if we
    // produced an error.
    return !trap.hasErrorOccurred();
  }

  clang::CXXRecordDecl* clang_def = clang_decl->getDefinition();
  CARBON_CHECK(clang_def, "Complete type has no definition");

  if (clang_def->getNumVBases()) {
    // TODO: Handle virtual bases. We don't actually know where they go in the
    // layout. We may also want to use a different size in the layout for

Review comment (suggestion):
You might want to share this with `StartClassDefinition()`, especially if the logic will change over time.

Code after:

    layout.push_back(
        context.ast_context().toCharUnitsFromBits(offset).getQuantity());
    fields.push_back(
        {.name_id = field_name_id, .type_inst_id = field_type_inst_id});
  }

  // TODO: Add a field to prevent tail padding reuse if necessary.

  return AddTypeInst<SemIR::CustomLayoutType>(
      context, import_ir_inst_id,
      {.type_id = SemIR::TypeType::TypeId,
       .fields_id = context.struct_type_fields().Add(fields),
       .layout_id = context.custom_layouts().Add(layout)});
}

// Creates a class definition based on the information in the given Clang
// declaration, which is assumed to be for a class definition.
static auto BuildClassDefinition(Context& context,
                                 SemIR::ImportIRInstId import_ir_inst_id,
                                 SemIR::ClassId class_id,
                                 SemIR::TypeInstId class_inst_id,
                                 clang::CXXRecordDecl* clang_def) -> void {
  auto& class_info = context.classes().Get(class_id);
  CARBON_CHECK(!class_info.has_definition_started());
  class_info.definition_id = class_inst_id;

  context.inst_block_stack().Push();

  class_info.inheritance_kind = GetInheritanceKind(clang_def);

  // Compute the class's object representation.
  auto object_repr_id = ImportClassObjectRepr(
      context, class_id, import_ir_inst_id, class_inst_id, clang_def);
  class_info.complete_type_witness_id = AddInst<SemIR::CompleteTypeWitness>(
      context, import_ir_inst_id,
      {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),
       .object_repr_type_inst_id = object_repr_id});

  class_info.body_block_id = context.inst_block_stack().Pop();
}

auto ImportCppClassDefinition(Context& context, SemIR::LocId loc_id,
                              SemIR::ClassId class_id,
                              SemIR::ClangDeclId clang_decl_id) -> bool {
  clang::ASTUnit* ast = context.sem_ir().cpp_ast();
  CARBON_CHECK(ast);

  auto* clang_decl = cast<clang::CXXRecordDecl>(
      context.sem_ir().clang_decls().Get(clang_decl_id).decl);
  auto class_inst_id = context.types().GetAsTypeInstId(