Repository: carbon-language/carbon-lang
File: toolchain/sem_ir/function.h (C/C++)

Code before:
  // this function.
  VirtualModifier virtual_modifier;

  // The implicit self parameter, if any, in implicit_param_patterns_id from
  // EntityWithParamsBase.
  InstId self_param_id = SemIR::InstId::None;

  // The following member is set on the first call to the function, or at the
  // point where the function is defined.

  // The following members are set at the end of a builtin function definition.

  // If this is a builtin function, the corresponding builtin kind.
  BuiltinFunctionKind builtin_function_kind = BuiltinFunctionKind::None;

  // The following members are accumulated throughout the function definition.

  // A list of the statically reachable code blocks in the body of the
  // function, in lexical order. The first block is the entry block. This will
  // be empty for declarations that don't have a visible definition.
  llvm::SmallVector<InstBlockId> body_block_ids = {};

  // If the function is imported from C++, points to the Clang declaration in
  // the AST. Used for mangling. The AST is owned by `CompileSubcommand` so we
  // expect it to be live from `Function` creation to mangling.
  const clang::NamedDecl* cpp_clang_decl = nullptr;
};

// A function. See EntityWithParamsBase regarding the inheritance here.
struct Function : public EntityWithParamsBase,
                  public FunctionFields,
                  public Printable<Function> {
  struct ParamPatternInfo {
    InstId inst_id;
    AnyParamPattern inst;
    EntityNameId entity_name_id;
  };

  auto Print(llvm::raw_ostream& out) const -> void {
    out << "{";
    PrintBaseFields(out);
    if (return_slot_pattern_id.has_value()) {
      out << ", return_slot_pattern: " << return_slot_pattern_id;
    }
    if (!body_block_ids.empty()) {
      out << llvm::formatv(
          ", body: [{0}]",
          llvm::make_range(body_block_ids.begin(), body_block_ids.end()));
    }
    out << "}";
  }

Review comment (bug):
The SemIR is intended to be stored on disk, which would invalidate this pointer. Is there an easy way to get a more durable reference? Can you add a TODO to take another look at ensuring this can be easily serialized?

```suggestion
  // TODO: Ensure we can easily serialize/deserialize this.
  const clang::NamedDecl* cpp_clang_decl = nullptr;
```

Code after:
  // this function.
  VirtualModifier virtual_modifier;

  // The implicit self parameter, if any, in implicit_param_patterns_id from
  // EntityWithParamsBase.
  InstId self_param_id = SemIR::InstId::None;

  // The following member is set on the first call to the function, or at the
  // point where the function is defined.

  // The following members are set at the end of a builtin function definition.

  // If this is a builtin function, the corresponding builtin kind.
  BuiltinFunctionKind builtin_function_kind = BuiltinFunctionKind::None;

  // The following members are accumulated throughout the function definition.

  // A list of the statically reachable code blocks in the body of the
  // function, in lexical order. The first block is the entry block. This will
  // be empty for declarations that don't have a visible definition.
  llvm::SmallVector<InstBlockId> body_block_ids = {};

  // If the function is imported from C++, points to the Clang declaration in
  // the AST. Used for mangling. The AST is owned by `CompileSubcommand` so we
  // expect it to be live from `Function` creation to mangling.
  // TODO: #4666 Ensure we can easily serialize/deserialize this. Consider decl
  // ID to point into the AST.
  const clang::NamedDecl* cpp_decl = nullptr;
};

// A function. See EntityWithParamsBase regarding the inheritance here.
struct Function : public EntityWithParamsBase,
                  public FunctionFields,
                  public Printable<Function> {
  struct ParamPatternInfo {
    InstId inst_id;
    AnyParamPattern inst;
    EntityNameId entity_name_id;
  };

  auto Print(llvm::raw_ostream& out) const -> void {
    out << "{";
    PrintBaseFields(out);
    if (return_slot_pattern_id.has_value()) {
      out << ", return_slot_pattern: " << return_slot_pattern_id;
    }
    if (!body_block_ids.empty()) {
      out << llvm::formatv(
          ", body: [{0}]",
          llvm::make_range(body_block_ids.begin(), body_block_ids.end()));
    }