Repository: carbon-language/carbon-lang
File: toolchain/check/decl_name_stack.h (C/C++)

Code before:

    State state = State::Empty;

    // Whether there have been qualifiers in the name.
    bool has_qualifiers = false;

    // The scope which qualified names are added to. For unqualified names in
    // an unnamed scope, this will be `None` to indicate the current scope
    // should be used.
    SemIR::NameScopeId parent_scope_id;

    // The last location ID used.
    SemIR::LocId loc_id = SemIR::LocId::None;

    union {
      // The ID of a resolved qualifier, including both identifiers and
      // expressions. `None` indicates resolution failed.
      SemIR::InstId resolved_inst_id;

      // The ID of an unresolved identifier.
      SemIR::NameId unresolved_name_id = SemIR::NameId::None;
    };

    // When `state` is `Poisoned` (name is unresolved due to name poisoning),
    // the poisoning location.
    SemIR::LocId poisoning_loc_id;
  };

  // Information about a declaration name that has been temporarily removed from
  // the stack and will later be restored. Names can only be suspended once they
  // are finished.
  struct SuspendedName {
    // The declaration name information.
    NameContext name_context;

    // Suspended scopes. We only preallocate space for two of these, because
    // suspended names are usually used for classes and functions with
    // unqualified names, which only need at most two scopes -- one scope for
    // the parameter and one scope for the entity itself, and we can store quite
    // a few of these when processing a large class definition.
    llvm::SmallVector<ScopeStack::SuspendedScope, 2> scopes;
  };

  explicit DeclNameStack(Context* context) : context_(context) {}

  // Pushes processing of a new declaration name, which will be used
  // contextually, and prepares to enter scopes for that name. To pop this
  // state, `FinishName` and `PopScope` must be called, in that order.
  auto PushScopeAndStartName() -> void;

  // Creates and returns a name context corresponding to declaring an

Review comment (suggestion):
```suggestion
    SemIR::LocId poisoning_loc_id = SemIR::LocId::None;
```

Noted in the cpp file too, but I think using a default instead of always initializing to `None` would be consistent with other member init.

Code after:
    }

    // The current scope when this name began. This is the scope that we will
    // return to at the end of the declaration.
    ScopeIndex initial_scope_index;

    State state = State::Empty;

    // Whether there have been qualifiers in the name.
    bool has_qualifiers = false;

    // The scope which qualified names are added to. For unqualified names in
    // an unnamed scope, this will be `None` to indicate the current scope
    // should be used.
    SemIR::NameScopeId parent_scope_id;

    // The last location ID used.
    SemIR::LocId loc_id = SemIR::LocId::None;

    union {
      // The ID of a resolved qualifier, including both identifiers and
      // expressions. `None` indicates resolution failed.
      SemIR::InstId resolved_inst_id;

      // The ID of an unresolved identifier.
      SemIR::NameId unresolved_name_id = SemIR::NameId::None;
    };

    // When `state` is `Poisoned` (name is unresolved due to name poisoning),
    // the poisoning location.
    SemIR::LocId poisoning_loc_id = SemIR::LocId::None;
  };

  // Information about a declaration name that has been temporarily removed from
  // the stack and will later be restored. Names can only be suspended once they
  // are finished.
  struct SuspendedName {
    // The declaration name information.
    NameContext name_context;

    // Suspended scopes. We only preallocate space for two of these, because
    // suspended names are usually used for classes and functions with
    // unqualified names, which only need at most two scopes -- one scope for
    // the parameter and one scope for the entity itself, and we can store quite
    // a few of these when processing a large class definition.
    llvm::SmallVector<ScopeStack::SuspendedScope, 2> scopes;
  };

  explicit DeclNameStack(Context* context) : context_(context) {}

  // Pushes processing of a new declaration name, which will be used