//===-- lib/Semantics/resolve-names.cpp -----------------------------------===//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "resolve-names.h"
#include "assignment.h"
#include "definable.h"
#include "mod-file.h"
#include "pointer-assignment.h"
#include "program-tree.h"
#include "resolve-directives.h"
#include "resolve-names-utils.h"
#include "rewrite-parse-tree.h"
#include "flang/Common/Fortran.h"
#include "flang/Common/default-kinds.h"
#include "flang/Common/indirection.h"
#include "flang/Common/restorer.h"
#include "flang/Common/visit.h"
#include "flang/Evaluate/characteristics.h"
#include "flang/Evaluate/check-expression.h"
#include "flang/Evaluate/common.h"
#include "flang/Evaluate/fold-designator.h"
#include "flang/Evaluate/fold.h"
#include "flang/Evaluate/intrinsics.h"
#include "flang/Evaluate/tools.h"
#include "flang/Evaluate/type.h"
#include "flang/Parser/parse-tree-visitor.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Parser/tools.h"
#include "flang/Semantics/attr.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/scope.h"
#include "flang/Semantics/semantics.h"
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include "flang/Semantics/type.h"
#include "llvm/Support/raw_ostream.h"
#include <list>
#include <map>
#include <set>
#include <stack>

namespace Fortran::semantics {

using namespace parser::literals;

template <typename T> using Indirection = common::Indirection<T>;
using Message = parser::Message;
using Messages = parser::Messages;
using MessageFixedText = parser::MessageFixedText;
using MessageFormattedText = parser::MessageFormattedText;

class ResolveNamesVisitor;
class ScopeHandler;

// ImplicitRules maps initial character of identifier to the DeclTypeSpec
// representing the implicit type; std::nullopt if none.
// It also records the presence of IMPLICIT NONE statements.
// When inheritFromParent is set, defaults come from the parent rules.
class ImplicitRules {
public:
  ImplicitRules(SemanticsContext &context, ImplicitRules *parent)
      : parent_{parent}, context_{context} {
    inheritFromParent_ = parent != nullptr;
  }
  bool isImplicitNoneType() const;
  bool isImplicitNoneExternal() const;
  void set_isImplicitNoneType(bool x) { isImplicitNoneType_ = x; }
  void set_isImplicitNoneExternal(bool x) { isImplicitNoneExternal_ = x; }
  void set_inheritFromParent(bool x) { inheritFromParent_ = x; }
  // Get the implicit type for this name. May be null.
  const DeclTypeSpec *GetType(
      SourceName, bool respectImplicitNone = true) const;
  // Record the implicit type for the range of characters [fromLetter,
  // toLetter].
  void SetTypeMapping(const DeclTypeSpec &type, parser::Location fromLetter,
      parser::Location toLetter);

private:
  static char Incr(char ch);

  ImplicitRules *parent_;
  SemanticsContext &context_;
  bool inheritFromParent_{false}; // look in parent if not specified here
  bool isImplicitNoneType_{
      context_.IsEnabled(common::LanguageFeature::ImplicitNoneTypeAlways)};
  bool isImplicitNoneExternal_{false};
  // map_ contains the mapping between letters and types that were defined
  // by the IMPLICIT statements of the related scope. It does not contain
  // the default Fortran mappings nor the mapping defined in parents.
  std::map<char, common::Reference<const DeclTypeSpec>> map_;

  friend llvm::raw_ostream &operator<<(
      llvm::raw_ostream &, const ImplicitRules &);
  friend void ShowImplicitRule(
      llvm::raw_ostream &, const ImplicitRules &, char);
};

// scope -> implicit rules for that scope
using ImplicitRulesMap = std::map<const Scope *, ImplicitRules>;

// Track statement source locations and save messages.
class MessageHandler {
public:
  MessageHandler() { DIE("MessageHandler: default-constructed"); }
  explicit MessageHandler(SemanticsContext &c) : context_{&c} {}
  Messages &messages() { return context_->messages(); };
  const std::optional<SourceName> &currStmtSource() {
    return context_->location();
  }
  void set_currStmtSource(const std::optional<SourceName> &source) {
    context_->set_location(source);
  }

  // Emit a message associated with the current statement source.
  Message &Say(MessageFixedText &&);
  Message &Say(MessageFormattedText &&);
  // Emit a message about a SourceName
  Message &Say(const SourceName &, MessageFixedText &&);
  // Emit a formatted message associated with a source location.
  template <typename... A>
  Message &Say(const SourceName &source, MessageFixedText &&msg, A &&...args) {
    return context_->Say(source, std::move(msg), std::forward<A>(args)...);
  }

private:
  SemanticsContext *context_;
};

// Inheritance graph for the parse tree visitation classes that follow:
//   BaseVisitor
//   + AttrsVisitor
//   | + DeclTypeSpecVisitor
//   |   + ImplicitRulesVisitor
//   |     + ScopeHandler ------------------+
//   |       + ModuleVisitor -------------+ |
//   |       + GenericHandler -------+    | |
//   |       | + InterfaceVisitor    |    | |
//   |       +-+ SubprogramVisitor ==|==+ | |
//   + ArraySpecVisitor              |  | | |
//     + DeclarationVisitor <--------+  | | |
//       + ConstructVisitor             | | |
//         + ResolveNamesVisitor <------+-+-+

class BaseVisitor {
public:
  BaseVisitor() { DIE("BaseVisitor: default-constructed"); }
  BaseVisitor(
      SemanticsContext &c, ResolveNamesVisitor &v, ImplicitRulesMap &rules)
      : implicitRulesMap_{&rules}, this_{&v}, context_{&c}, messageHandler_{c} {
  }
  template <typename T> void Walk(const T &);

  MessageHandler &messageHandler() { return messageHandler_; }
  const std::optional<SourceName> &currStmtSource() {
    return context_->location();
  }
  SemanticsContext &context() const { return *context_; }
  evaluate::FoldingContext &GetFoldingContext() const {
    return context_->foldingContext();
  }
  bool IsIntrinsic(
      const SourceName &name, std::optional<Symbol::Flag> flag) const {
    if (!flag) {
      return context_->intrinsics().IsIntrinsic(name.ToString());
    } else if (flag == Symbol::Flag::Function) {
      return context_->intrinsics().IsIntrinsicFunction(name.ToString());
    } else if (flag == Symbol::Flag::Subroutine) {
      return context_->intrinsics().IsIntrinsicSubroutine(name.ToString());
    } else {
      DIE("expected Subroutine or Function flag");
    }
  }

  bool InModuleFile() const {
    return GetFoldingContext().moduleFileName().has_value();
  }

  // Make a placeholder symbol for a Name that otherwise wouldn't have one.
  // It is not in any scope and always has MiscDetails.
  void MakePlaceholder(const parser::Name &, MiscDetails::Kind);

  template <typename T> common::IfNoLvalue<T, T> FoldExpr(T &&expr) {
    return evaluate::Fold(GetFoldingContext(), std::move(expr));
  }

  template <typename T> MaybeExpr EvaluateExpr(const T &expr) {
    return FoldExpr(AnalyzeExpr(*context_, expr));
  }

  template <typename T>
  MaybeExpr EvaluateNonPointerInitializer(
      const Symbol &symbol, const T &expr, parser::CharBlock source) {
    if (!context().HasError(symbol)) {
      if (auto maybeExpr{AnalyzeExpr(*context_, expr)}) {
        auto restorer{GetFoldingContext().messages().SetLocation(source)};
        return evaluate::NonPointerInitializationExpr(
            symbol, std::move(*maybeExpr), GetFoldingContext());
      }
    }
    return std::nullopt;
  }

  template <typename T> MaybeIntExpr EvaluateIntExpr(const T &expr) {
    return semantics::EvaluateIntExpr(*context_, expr);
  }

  template <typename T>
  MaybeSubscriptIntExpr EvaluateSubscriptIntExpr(const T &expr) {
    if (MaybeIntExpr maybeIntExpr{EvaluateIntExpr(expr)}) {
      return FoldExpr(evaluate::ConvertToType<evaluate::SubscriptInteger>(
          std::move(*maybeIntExpr)));
    } else {
      return std::nullopt;
    }
  }

  template <typename... A> Message &Say(A &&...args) {
    return messageHandler_.Say(std::forward<A>(args)...);
  }
  template <typename... A>
  Message &Say(
      const parser::Name &name, MessageFixedText &&text, const A &...args) {
    return messageHandler_.Say(name.source, std::move(text), args...);
  }

protected:
  ImplicitRulesMap *implicitRulesMap_{nullptr};

private:
  ResolveNamesVisitor *this_;
  SemanticsContext *context_;
  MessageHandler messageHandler_;
};

// Provide Post methods to collect attributes into a member variable.
class AttrsVisitor : public virtual BaseVisitor {
public:
  bool BeginAttrs(); // always returns true
  Attrs GetAttrs();
  std::optional<common::CUDADataAttr> cudaDataAttr() { return cudaDataAttr_; }
  Attrs EndAttrs();
  bool SetPassNameOn(Symbol &);
  void SetBindNameOn(Symbol &);
  void Post(const parser::LanguageBindingSpec &);
  bool Pre(const parser::IntentSpec &);
  bool Pre(const parser::Pass &);

  bool CheckAndSet(Attr);

// Simple case: encountering CLASSNAME causes ATTRNAME to be set.
#define HANDLE_ATTR_CLASS(CLASSNAME, ATTRNAME) \
  bool Pre(const parser::CLASSNAME &) { \
    CheckAndSet(Attr::ATTRNAME); \
    return false; \
  }
  HANDLE_ATTR_CLASS(PrefixSpec::Elemental, ELEMENTAL)
  HANDLE_ATTR_CLASS(PrefixSpec::Impure, IMPURE)
  HANDLE_ATTR_CLASS(PrefixSpec::Module, MODULE)
  HANDLE_ATTR_CLASS(PrefixSpec::Non_Recursive, NON_RECURSIVE)
  HANDLE_ATTR_CLASS(PrefixSpec::Pure, PURE)
  HANDLE_ATTR_CLASS(PrefixSpec::Recursive, RECURSIVE)
  HANDLE_ATTR_CLASS(TypeAttrSpec::BindC, BIND_C)
  HANDLE_ATTR_CLASS(BindAttr::Deferred, DEFERRED)
  HANDLE_ATTR_CLASS(BindAttr::Non_Overridable, NON_OVERRIDABLE)
  HANDLE_ATTR_CLASS(Abstract, ABSTRACT)
  HANDLE_ATTR_CLASS(Allocatable, ALLOCATABLE)
  HANDLE_ATTR_CLASS(Asynchronous, ASYNCHRONOUS)
  HANDLE_ATTR_CLASS(Contiguous, CONTIGUOUS)
  HANDLE_ATTR_CLASS(External, EXTERNAL)
  HANDLE_ATTR_CLASS(Intrinsic, INTRINSIC)
  HANDLE_ATTR_CLASS(NoPass, NOPASS)
  HANDLE_ATTR_CLASS(Optional, OPTIONAL)
  HANDLE_ATTR_CLASS(Parameter, PARAMETER)
  HANDLE_ATTR_CLASS(Pointer, POINTER)
  HANDLE_ATTR_CLASS(Protected, PROTECTED)
  HANDLE_ATTR_CLASS(Save, SAVE)
  HANDLE_ATTR_CLASS(Target, TARGET)
  HANDLE_ATTR_CLASS(Value, VALUE)
  HANDLE_ATTR_CLASS(Volatile, VOLATILE)
#undef HANDLE_ATTR_CLASS
  bool Pre(const common::CUDADataAttr);

protected:
  std::optional<Attrs> attrs_;
  std::optional<common::CUDADataAttr> cudaDataAttr_;

  Attr AccessSpecToAttr(const parser::AccessSpec &x) {
    switch (x.v) {
    case parser::AccessSpec::Kind::Public:
      return Attr::PUBLIC;
    case parser::AccessSpec::Kind::Private:
      return Attr::PRIVATE;
    }
    llvm_unreachable("Switch covers all cases"); // suppress g++ warning
  }
  Attr IntentSpecToAttr(const parser::IntentSpec &x) {
    switch (x.v) {
    case parser::IntentSpec::Intent::In:
      return Attr::INTENT_IN;
    case parser::IntentSpec::Intent::Out:
      return Attr::INTENT_OUT;
    case parser::IntentSpec::Intent::InOut:
      return Attr::INTENT_INOUT;
    }
    llvm_unreachable("Switch covers all cases"); // suppress g++ warning
  }

private:
  bool IsDuplicateAttr(Attr);
  bool HaveAttrConflict(Attr, Attr, Attr);
  bool IsConflictingAttr(Attr);

  MaybeExpr bindName_; // from BIND(C, NAME="...")
  std::optional<SourceName> passName_; // from PASS(...)
};

// Find and create types from declaration-type-spec nodes.
class DeclTypeSpecVisitor : public AttrsVisitor {
public:
  using AttrsVisitor::Post;
  using AttrsVisitor::Pre;
  void Post(const parser::IntrinsicTypeSpec::DoublePrecision &);
  void Post(const parser::IntrinsicTypeSpec::DoubleComplex &);
  void Post(const parser::DeclarationTypeSpec::ClassStar &);
  void Post(const parser::DeclarationTypeSpec::TypeStar &);
  bool Pre(const parser::TypeGuardStmt &);
  void Post(const parser::TypeGuardStmt &);
  void Post(const parser::TypeSpec &);

  // Walk the parse tree of a type spec and return the DeclTypeSpec for it.
  template <typename T>
  const DeclTypeSpec *ProcessTypeSpec(const T &x, bool allowForward = false) {
    auto restorer{common::ScopedSet(state_, State{})};
    set_allowForwardReferenceToDerivedType(allowForward);
    BeginDeclTypeSpec();
    Walk(x);
    const auto *type{GetDeclTypeSpec()};
    EndDeclTypeSpec();
    return type;
  }

protected:
  struct State {
    bool expectDeclTypeSpec{false}; // should see decl-type-spec only when true
    const DeclTypeSpec *declTypeSpec{nullptr};
    struct {
      DerivedTypeSpec *type{nullptr};
      DeclTypeSpec::Category category{DeclTypeSpec::TypeDerived};
    } derived;
    bool allowForwardReferenceToDerivedType{false};
  };

  bool allowForwardReferenceToDerivedType() const {
    return state_.allowForwardReferenceToDerivedType;
  }
  void set_allowForwardReferenceToDerivedType(bool yes) {
    state_.allowForwardReferenceToDerivedType = yes;
  }

  const DeclTypeSpec *GetDeclTypeSpec();
  void BeginDeclTypeSpec();
  void EndDeclTypeSpec();
  void SetDeclTypeSpec(const DeclTypeSpec &);
  void SetDeclTypeSpecCategory(DeclTypeSpec::Category);
  DeclTypeSpec::Category GetDeclTypeSpecCategory() const {
    return state_.derived.category;
  }
  KindExpr GetKindParamExpr(
      TypeCategory, const std::optional<parser::KindSelector> &);
  void CheckForAbstractType(const Symbol &typeSymbol);

private:
  State state_;

  void MakeNumericType(TypeCategory, int kind);
};

// Visit ImplicitStmt and related parse tree nodes and updates implicit rules.
class ImplicitRulesVisitor : public DeclTypeSpecVisitor {
public:
  using DeclTypeSpecVisitor::Post;
  using DeclTypeSpecVisitor::Pre;
  using ImplicitNoneNameSpec = parser::ImplicitStmt::ImplicitNoneNameSpec;

  void Post(const parser::ParameterStmt &);
  bool Pre(const parser::ImplicitStmt &);
  bool Pre(const parser::LetterSpec &);
  bool Pre(const parser::ImplicitSpec &);
  void Post(const parser::ImplicitSpec &);

  const DeclTypeSpec *GetType(
      SourceName name, bool respectImplicitNoneType = true) {
    return implicitRules_->GetType(name, respectImplicitNoneType);
  }
  bool isImplicitNoneType() const {
    return implicitRules_->isImplicitNoneType();
  }
  bool isImplicitNoneType(const Scope &scope) const {
    return implicitRulesMap_->at(&scope).isImplicitNoneType();
  }
  bool isImplicitNoneExternal() const {
    return implicitRules_->isImplicitNoneExternal();
  }
  void set_inheritFromParent(bool x) {
    implicitRules_->set_inheritFromParent(x);
  }

protected:
  void BeginScope(const Scope &);
  void SetScope(const Scope &);

private:
  // implicit rules in effect for current scope
  ImplicitRules *implicitRules_{nullptr};
  std::optional<SourceName> prevImplicit_;
  std::optional<SourceName> prevImplicitNone_;
  std::optional<SourceName> prevImplicitNoneType_;
  std::optional<SourceName> prevParameterStmt_;

  bool HandleImplicitNone(const std::list<ImplicitNoneNameSpec> &nameSpecs);
};

// Track array specifications. They can occur in AttrSpec, EntityDecl,
// ObjectDecl, DimensionStmt, CommonBlockObject, BasedPointer, and
// ComponentDecl.
// 1. INTEGER, DIMENSION(10) :: x
// 2. INTEGER :: x(10)
// 3. ALLOCATABLE :: x(:)
// 4. DIMENSION :: x(10)
// 5. COMMON x(10)
// 6. POINTER(p,x(10))
class ArraySpecVisitor : public virtual BaseVisitor {
public:
  void Post(const parser::ArraySpec &);
  void Post(const parser::ComponentArraySpec &);
  void Post(const parser::CoarraySpec &);
  void Post(const parser::AttrSpec &) { PostAttrSpec(); }
  void Post(const parser::ComponentAttrSpec &) { PostAttrSpec(); }

protected:
  const ArraySpec &arraySpec();
  void set_arraySpec(const ArraySpec arraySpec) { arraySpec_ = arraySpec; }
  const ArraySpec &coarraySpec();
  void BeginArraySpec();
  void EndArraySpec();
  void ClearArraySpec() { arraySpec_.clear(); }
  void ClearCoarraySpec() { coarraySpec_.clear(); }

private:
  // arraySpec_/coarraySpec_ are populated from any ArraySpec/CoarraySpec
  ArraySpec arraySpec_;
  ArraySpec coarraySpec_;
  // When an ArraySpec is under an AttrSpec or ComponentAttrSpec, it is moved
  // into attrArraySpec_
  ArraySpec attrArraySpec_;
  ArraySpec attrCoarraySpec_;

  void PostAttrSpec();
};

// Manages a stack of function result information.  We defer the processing
// of a type specification that appears in the prefix of a FUNCTION statement
// until the function result variable appears in the specification part
// or the end of the specification part.  This allows for forward references
// in the type specification to resolve to local names.
class FuncResultStack {
public:
  explicit FuncResultStack(ScopeHandler &scopeHandler)
      : scopeHandler_{scopeHandler} {}
  ~FuncResultStack();

  struct FuncInfo {
    explicit FuncInfo(const Scope &s) : scope{s} {}
    const Scope &scope;
    // Parse tree of the type specification in the FUNCTION prefix
    const parser::DeclarationTypeSpec *parsedType{nullptr};
    // Name of the function RESULT in the FUNCTION suffix, if any
    const parser::Name *resultName{nullptr};
    // Result symbol
    Symbol *resultSymbol{nullptr};
    std::optional<SourceName> source;
    bool inFunctionStmt{false}; // true between Pre/Post of FunctionStmt
  };

  // Completes the definition of the top function's result.
  void CompleteFunctionResultType();
  // Completes the definition of a symbol if it is the top function's result.
  void CompleteTypeIfFunctionResult(Symbol &);

  FuncInfo *Top() { return stack_.empty() ? nullptr : &stack_.back(); }
  FuncInfo &Push(const Scope &scope) { return stack_.emplace_back(scope); }
  void Pop();

private:
  ScopeHandler &scopeHandler_;
  std::vector<FuncInfo> stack_;
};

// Manage a stack of Scopes
class ScopeHandler : public ImplicitRulesVisitor {
public:
  using ImplicitRulesVisitor::Post;
  using ImplicitRulesVisitor::Pre;

  Scope &currScope() { return DEREF(currScope_); }
  // The enclosing host procedure if current scope is in an internal procedure
  Scope *GetHostProcedure();
  // The innermost enclosing program unit scope, ignoring BLOCK and other
  // construct scopes.
  Scope &InclusiveScope();
  // The enclosing scope, skipping derived types.
  Scope &NonDerivedTypeScope();

  // Create a new scope and push it on the scope stack.
  void PushScope(Scope::Kind kind, Symbol *symbol);
  void PushScope(Scope &scope);
  void PopScope();
  void SetScope(Scope &);

  template <typename T> bool Pre(const parser::Statement<T> &x) {
    messageHandler().set_currStmtSource(x.source);
    currScope_->AddSourceRange(x.source);
    return true;
  }
  template <typename T> void Post(const parser::Statement<T> &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }

  // Special messages: already declared; referencing symbol's declaration;
  // about a type; two names & locations
  void SayAlreadyDeclared(const parser::Name &, Symbol &);
  void SayAlreadyDeclared(const SourceName &, Symbol &);
  void SayAlreadyDeclared(const SourceName &, const SourceName &);
  void SayWithReason(
      const parser::Name &, Symbol &, MessageFixedText &&, Message &&);
  void SayWithDecl(const parser::Name &, Symbol &, MessageFixedText &&);
  void SayLocalMustBeVariable(const parser::Name &, Symbol &);
  void SayDerivedType(const SourceName &, MessageFixedText &&, const Scope &);
  void Say2(const SourceName &, MessageFixedText &&, const SourceName &,
      MessageFixedText &&);
  void Say2(
      const SourceName &, MessageFixedText &&, Symbol &, MessageFixedText &&);
  void Say2(
      const parser::Name &, MessageFixedText &&, Symbol &, MessageFixedText &&);

  // Search for symbol by name in current, parent derived type, and
  // containing scopes
  Symbol *FindSymbol(const parser::Name &);
  Symbol *FindSymbol(const Scope &, const parser::Name &);
  // Search for name only in scope, not in enclosing scopes.
  Symbol *FindInScope(const Scope &, const parser::Name &);
  Symbol *FindInScope(const Scope &, const SourceName &);
  template <typename T> Symbol *FindInScope(const T &name) {
    return FindInScope(currScope(), name);
  }
  // Search for name in a derived type scope and its parents.
  Symbol *FindInTypeOrParents(const Scope &, const parser::Name &);
  Symbol *FindInTypeOrParents(const parser::Name &);
  Symbol *FindInScopeOrBlockConstructs(const Scope &, SourceName);
  Symbol *FindSeparateModuleProcedureInterface(const parser::Name &);
  void EraseSymbol(const parser::Name &);
  void EraseSymbol(const Symbol &symbol) { currScope().erase(symbol.name()); }
  // Make a new symbol with the name and attrs of an existing one
  Symbol &CopySymbol(const SourceName &, const Symbol &);

  // Make symbols in the current or named scope
  Symbol &MakeSymbol(Scope &, const SourceName &, Attrs);
  Symbol &MakeSymbol(const SourceName &, Attrs = Attrs{});
  Symbol &MakeSymbol(const parser::Name &, Attrs = Attrs{});
  Symbol &MakeHostAssocSymbol(const parser::Name &, const Symbol &);

  template <typename D>
  common::IfNoLvalue<Symbol &, D> MakeSymbol(
      const parser::Name &name, D &&details) {
    return MakeSymbol(name, Attrs{}, std::move(details));
  }

  template <typename D>
  common::IfNoLvalue<Symbol &, D> MakeSymbol(
      const parser::Name &name, const Attrs &attrs, D &&details) {
    return Resolve(name, MakeSymbol(name.source, attrs, std::move(details)));
  }

  template <typename D>
  common::IfNoLvalue<Symbol &, D> MakeSymbol(
      const SourceName &name, const Attrs &attrs, D &&details) {
    // Note: don't use FindSymbol here. If this is a derived type scope,
    // we want to detect whether the name is already declared as a component.
    auto *symbol{FindInScope(name)};
    if (!symbol) {
      symbol = &MakeSymbol(name, attrs);
      symbol->set_details(std::move(details));
      return *symbol;
    }
    if constexpr (std::is_same_v<DerivedTypeDetails, D>) {
      if (auto *d{symbol->detailsIf<GenericDetails>()}) {
        if (!d->specific()) {
          // derived type with same name as a generic
          auto *derivedType{d->derivedType()};
          if (!derivedType) {
            derivedType =
                &currScope().MakeSymbol(name, attrs, std::move(details));
            d->set_derivedType(*derivedType);
          } else if (derivedType->CanReplaceDetails(details)) {
            // was forward-referenced
            CheckDuplicatedAttrs(name, *symbol, attrs);
            SetExplicitAttrs(*derivedType, attrs);
            derivedType->set_details(std::move(details));
          } else {
            SayAlreadyDeclared(name, *derivedType);
          }
          return *derivedType;
        }
      }
    }
    if (symbol->CanReplaceDetails(details)) {
      // update the existing symbol
      CheckDuplicatedAttrs(name, *symbol, attrs);
      SetExplicitAttrs(*symbol, attrs);
      if constexpr (std::is_same_v<SubprogramDetails, D>) {
        // Dummy argument defined by explicit interface?
        details.set_isDummy(IsDummy(*symbol));
      }
      symbol->set_details(std::move(details));
      return *symbol;
    } else if constexpr (std::is_same_v<UnknownDetails, D>) {
      CheckDuplicatedAttrs(name, *symbol, attrs);
      SetExplicitAttrs(*symbol, attrs);
      return *symbol;
    } else {
      if (!CheckPossibleBadForwardRef(*symbol)) {
        if (name.empty() && symbol->name().empty()) {
          // report the error elsewhere
          return *symbol;
        }
        Symbol &errSym{*symbol};
        if (auto *d{symbol->detailsIf<GenericDetails>()}) {
          if (d->specific()) {
            errSym = *d->specific();
          } else if (d->derivedType()) {
            errSym = *d->derivedType();
          }
        }
        SayAlreadyDeclared(name, errSym);
      }
      // replace the old symbol with a new one with correct details
      EraseSymbol(*symbol);
      auto &result{MakeSymbol(name, attrs, std::move(details))};
      context().SetError(result);
      return result;
    }
  }

  void MakeExternal(Symbol &);

  // C815 duplicated attribute checking; returns false on error
  bool CheckDuplicatedAttr(SourceName, const Symbol &, Attr);
  bool CheckDuplicatedAttrs(SourceName, const Symbol &, Attrs);

  void SetExplicitAttr(Symbol &symbol, Attr attr) const {
    symbol.attrs().set(attr);
    symbol.implicitAttrs().reset(attr);
  }
  void SetExplicitAttrs(Symbol &symbol, Attrs attrs) const {
    symbol.attrs() |= attrs;
    symbol.implicitAttrs() &= ~attrs;
  }
  void SetImplicitAttr(Symbol &symbol, Attr attr) const {
    symbol.attrs().set(attr);
    symbol.implicitAttrs().set(attr);
  }
  void SetCUDADataAttr(
      SourceName, Symbol &, std::optional<common::CUDADataAttr>);

protected:
  FuncResultStack &funcResultStack() { return funcResultStack_; }

  // Apply the implicit type rules to this symbol.
  void ApplyImplicitRules(Symbol &, bool allowForwardReference = false);
  bool ImplicitlyTypeForwardRef(Symbol &);
  void AcquireIntrinsicProcedureFlags(Symbol &);
  const DeclTypeSpec *GetImplicitType(
      Symbol &, bool respectImplicitNoneType = true);
  void CheckEntryDummyUse(SourceName, Symbol *);
  bool ConvertToObjectEntity(Symbol &);
  bool ConvertToProcEntity(Symbol &, std::optional<SourceName> = std::nullopt);

  const DeclTypeSpec &MakeNumericType(
      TypeCategory, const std::optional<parser::KindSelector> &);
  const DeclTypeSpec &MakeNumericType(TypeCategory, int);
  const DeclTypeSpec &MakeLogicalType(
      const std::optional<parser::KindSelector> &);
  const DeclTypeSpec &MakeLogicalType(int);
  void NotePossibleBadForwardRef(const parser::Name &);
  std::optional<SourceName> HadForwardRef(const Symbol &) const;
  bool CheckPossibleBadForwardRef(const Symbol &);

  bool inSpecificationPart_{false};
  bool deferImplicitTyping_{false};
  bool inEquivalenceStmt_{false};

  // Some information is collected from a specification part for deferred
  // processing in DeclarationPartVisitor functions (e.g., CheckSaveStmts())
  // that are called by ResolveNamesVisitor::FinishSpecificationPart().  Since
  // specification parts can nest (e.g., INTERFACE bodies), the collected
  // information that is not contained in the scope needs to be packaged
  // and restorable.
  struct SpecificationPartState {
    std::set<SourceName> forwardRefs;
    // Collect equivalence sets and process at end of specification part
    std::vector<const std::list<parser::EquivalenceObject> *> equivalenceSets;
    // Names of all common block objects in the scope
    std::set<SourceName> commonBlockObjects;
    // Info about SAVE statements and attributes in current scope
    struct {
      std::optional<SourceName> saveAll; // "SAVE" without entity list
      std::set<SourceName> entities; // names of entities with save attr
      std::set<SourceName> commons; // names of common blocks with save attr
    } saveInfo;
  } specPartState_;

  // Some declaration processing can and should be deferred to
  // ResolveExecutionParts() to avoid prematurely creating implicitly-typed
  // local symbols that should be host associations.
  struct DeferredDeclarationState {
    // The content of each namelist group
    std::list<const parser::NamelistStmt::Group *> namelistGroups;
  };
  DeferredDeclarationState *GetDeferredDeclarationState(bool add = false) {
    if (!add && deferred_.find(&currScope()) == deferred_.end()) {
      return nullptr;
    } else {
      return &deferred_.emplace(&currScope(), DeferredDeclarationState{})
                  .first->second;
    }
  }

private:
  Scope *currScope_{nullptr};
  FuncResultStack funcResultStack_{*this};
  std::map<Scope *, DeferredDeclarationState> deferred_;
};

class ModuleVisitor : public virtual ScopeHandler {
public:
  bool Pre(const parser::AccessStmt &);
  bool Pre(const parser::Only &);
  bool Pre(const parser::Rename::Names &);
  bool Pre(const parser::Rename::Operators &);
  bool Pre(const parser::UseStmt &);
  void Post(const parser::UseStmt &);

  void BeginModule(const parser::Name &, bool isSubmodule);
  bool BeginSubmodule(const parser::Name &, const parser::ParentIdentifier &);
  void ApplyDefaultAccess();
  Symbol &AddGenericUse(GenericDetails &, const SourceName &, const Symbol &);
  void AddAndCheckModuleUse(SourceName, bool isIntrinsic);
  void CollectUseRenames(const parser::UseStmt &);
  void ClearUseRenames() { useRenames_.clear(); }
  void ClearUseOnly() { useOnly_.clear(); }
  void ClearModuleUses() {
    intrinsicUses_.clear();
    nonIntrinsicUses_.clear();
  }

private:
  // The location of the last AccessStmt without access-ids, if any.
  std::optional<SourceName> prevAccessStmt_;
  // The scope of the module during a UseStmt
  Scope *useModuleScope_{nullptr};
  // Names that have appeared in a rename clause of USE statements
  std::set<std::pair<SourceName, SourceName>> useRenames_;
  // Names that have appeared in an ONLY clause of a USE statement
  std::set<std::pair<SourceName, Scope *>> useOnly_;
  // Intrinsic and non-intrinsic (explicit or not) module names that
  // have appeared in USE statements; used for C1406 warnings.
  std::set<SourceName> intrinsicUses_;
  std::set<SourceName> nonIntrinsicUses_;

  Symbol &SetAccess(const SourceName &, Attr attr, Symbol * = nullptr);
  // A rename in a USE statement: local => use
  struct SymbolRename {
    Symbol *local{nullptr};
    Symbol *use{nullptr};
  };
  // Record a use from useModuleScope_ of use Name/Symbol as local Name/Symbol
  SymbolRename AddUse(const SourceName &localName, const SourceName &useName);
  SymbolRename AddUse(const SourceName &, const SourceName &, Symbol *);
  void DoAddUse(
      SourceName, SourceName, Symbol &localSymbol, const Symbol &useSymbol);
  void AddUse(const GenericSpecInfo &);
  // Record a name appearing as the target of a USE rename clause
  void AddUseRename(SourceName name, SourceName moduleName) {
    useRenames_.emplace(std::make_pair(name, moduleName));
  }
  bool IsUseRenamed(const SourceName &name) const {
    return useModuleScope_ && useModuleScope_->symbol() &&
        useRenames_.find({name, useModuleScope_->symbol()->name()}) !=
        useRenames_.end();
  }
  // Record a name appearing in a USE ONLY clause
  void AddUseOnly(const SourceName &name) {
    useOnly_.emplace(std::make_pair(name, useModuleScope_));
  }
  bool IsUseOnly(const SourceName &name) const {
    return useOnly_.find({name, useModuleScope_}) != useOnly_.end();
  }
  Scope *FindModule(const parser::Name &, std::optional<bool> isIntrinsic,
      Scope *ancestor = nullptr);
};

class GenericHandler : public virtual ScopeHandler {
protected:
  using ProcedureKind = parser::ProcedureStmt::Kind;
  void ResolveSpecificsInGeneric(Symbol &, bool isEndOfSpecificationPart);
  void DeclaredPossibleSpecificProc(Symbol &);

  // Mappings of generics to their as-yet specific proc names and kinds
  using SpecificProcMapType =
      std::multimap<Symbol *, std::pair<const parser::Name *, ProcedureKind>>;
  SpecificProcMapType specificsForGenericProcs_;
  // inversion of SpecificProcMapType: maps pending proc names to generics
  using GenericProcMapType = std::multimap<SourceName, Symbol *>;
  GenericProcMapType genericsForSpecificProcs_;
};

class InterfaceVisitor : public virtual ScopeHandler,
                         public virtual GenericHandler {
public:
  bool Pre(const parser::InterfaceStmt &);
  void Post(const parser::InterfaceStmt &);
  void Post(const parser::EndInterfaceStmt &);
  bool Pre(const parser::GenericSpec &);
  bool Pre(const parser::ProcedureStmt &);
  bool Pre(const parser::GenericStmt &);
  void Post(const parser::GenericStmt &);

  bool inInterfaceBlock() const;
  bool isGeneric() const;
  bool isAbstract() const;

protected:
  Symbol &GetGenericSymbol() { return DEREF(genericInfo_.top().symbol); }
  // Add to generic the symbol for the subprogram with the same name
  void CheckGenericProcedures(Symbol &);

private:
  // A new GenericInfo is pushed for each interface block and generic stmt
  struct GenericInfo {
    GenericInfo(bool isInterface, bool isAbstract = false)
        : isInterface{isInterface}, isAbstract{isAbstract} {}
    bool isInterface; // in interface block
    bool isAbstract; // in abstract interface block
    Symbol *symbol{nullptr}; // the generic symbol being defined
  };
  std::stack<GenericInfo> genericInfo_;
  const GenericInfo &GetGenericInfo() const { return genericInfo_.top(); }
  void SetGenericSymbol(Symbol &symbol) { genericInfo_.top().symbol = &symbol; }
  void AddSpecificProcs(const std::list<parser::Name> &, ProcedureKind);
  void ResolveNewSpecifics();
};

class SubprogramVisitor : public virtual ScopeHandler, public InterfaceVisitor {
public:
  bool HandleStmtFunction(const parser::StmtFunctionStmt &);
  bool Pre(const parser::SubroutineStmt &);
  bool Pre(const parser::FunctionStmt &);
  void Post(const parser::FunctionStmt &);
  bool Pre(const parser::EntryStmt &);
  void Post(const parser::EntryStmt &);
  bool Pre(const parser::InterfaceBody::Subroutine &);
  void Post(const parser::InterfaceBody::Subroutine &);
  bool Pre(const parser::InterfaceBody::Function &);
  void Post(const parser::InterfaceBody::Function &);
  bool Pre(const parser::Suffix &);
  bool Pre(const parser::PrefixSpec &);
  bool Pre(const parser::PrefixSpec::Attributes &);
  void Post(const parser::PrefixSpec::Launch_Bounds &);
  void Post(const parser::PrefixSpec::Cluster_Dims &);

  bool BeginSubprogram(const parser::Name &, Symbol::Flag,
      bool hasModulePrefix = false,
      const parser::LanguageBindingSpec * = nullptr,
      const ProgramTree::EntryStmtList * = nullptr);
  bool BeginMpSubprogram(const parser::Name &);
  void PushBlockDataScope(const parser::Name &);
  void EndSubprogram(std::optional<parser::CharBlock> stmtSource = std::nullopt,
      const std::optional<parser::LanguageBindingSpec> * = nullptr,
      const ProgramTree::EntryStmtList * = nullptr);

protected:
  // Set when we see a stmt function that is really an array element assignment
  bool misparsedStmtFuncFound_{false};

private:
  // Edits an existing symbol created for earlier calls to a subprogram or ENTRY
  // so that it can be replaced by a later definition.
  bool HandlePreviousCalls(const parser::Name &, Symbol &, Symbol::Flag);
  void CheckExtantProc(const parser::Name &, Symbol::Flag);
  // Create a subprogram symbol in the current scope and push a new scope.
  Symbol &PushSubprogramScope(const parser::Name &, Symbol::Flag,
      const parser::LanguageBindingSpec * = nullptr,
      bool hasModulePrefix = false);
  Symbol *GetSpecificFromGeneric(const parser::Name &);
  Symbol &PostSubprogramStmt();
  void CreateDummyArgument(SubprogramDetails &, const parser::Name &);
  void CreateEntry(const parser::EntryStmt &stmt, Symbol &subprogram);
  void PostEntryStmt(const parser::EntryStmt &stmt);
  void HandleLanguageBinding(Symbol *,
      std::optional<parser::CharBlock> stmtSource,
      const std::optional<parser::LanguageBindingSpec> *);
};

class DeclarationVisitor : public ArraySpecVisitor,
                           public virtual GenericHandler {
public:
  using ArraySpecVisitor::Post;
  using ScopeHandler::Post;
  using ScopeHandler::Pre;

  bool Pre(const parser::Initialization &);
  void Post(const parser::EntityDecl &);
  void Post(const parser::ObjectDecl &);
  void Post(const parser::PointerDecl &);
  bool Pre(const parser::BindStmt &) { return BeginAttrs(); }
  void Post(const parser::BindStmt &) { EndAttrs(); }
  bool Pre(const parser::BindEntity &);
  bool Pre(const parser::OldParameterStmt &);
  bool Pre(const parser::NamedConstantDef &);
  bool Pre(const parser::NamedConstant &);
  void Post(const parser::EnumDef &);
  bool Pre(const parser::Enumerator &);
  bool Pre(const parser::AccessSpec &);
  bool Pre(const parser::AsynchronousStmt &);
  bool Pre(const parser::ContiguousStmt &);
  bool Pre(const parser::ExternalStmt &);
  bool Pre(const parser::IntentStmt &);
  bool Pre(const parser::IntrinsicStmt &);
  bool Pre(const parser::OptionalStmt &);
  bool Pre(const parser::ProtectedStmt &);
  bool Pre(const parser::ValueStmt &);
  bool Pre(const parser::VolatileStmt &);
  bool Pre(const parser::AllocatableStmt &) {
    objectDeclAttr_ = Attr::ALLOCATABLE;
    return true;
  }
  void Post(const parser::AllocatableStmt &) { objectDeclAttr_ = std::nullopt; }
  bool Pre(const parser::TargetStmt &) {
    objectDeclAttr_ = Attr::TARGET;
    return true;
  }
  bool Pre(const parser::CUDAAttributesStmt &);
  void Post(const parser::TargetStmt &) { objectDeclAttr_ = std::nullopt; }
  void Post(const parser::DimensionStmt::Declaration &);
  void Post(const parser::CodimensionDecl &);
  bool Pre(const parser::TypeDeclarationStmt &);
  void Post(const parser::TypeDeclarationStmt &);
  void Post(const parser::IntegerTypeSpec &);
  void Post(const parser::IntrinsicTypeSpec::Real &);
  void Post(const parser::IntrinsicTypeSpec::Complex &);
  void Post(const parser::IntrinsicTypeSpec::Logical &);
  void Post(const parser::IntrinsicTypeSpec::Character &);
  void Post(const parser::CharSelector::LengthAndKind &);
  void Post(const parser::CharLength &);
  void Post(const parser::LengthSelector &);
  bool Pre(const parser::KindParam &);
  bool Pre(const parser::VectorTypeSpec &);
  void Post(const parser::VectorTypeSpec &);
  bool Pre(const parser::DeclarationTypeSpec::Type &);
  void Post(const parser::DeclarationTypeSpec::Type &);
  bool Pre(const parser::DeclarationTypeSpec::Class &);
  void Post(const parser::DeclarationTypeSpec::Class &);
  void Post(const parser::DeclarationTypeSpec::Record &);
  void Post(const parser::DerivedTypeSpec &);
  bool Pre(const parser::DerivedTypeDef &);
  bool Pre(const parser::DerivedTypeStmt &);
  void Post(const parser::DerivedTypeStmt &);
  bool Pre(const parser::TypeParamDefStmt &) { return BeginDecl(); }
  void Post(const parser::TypeParamDefStmt &);
  bool Pre(const parser::TypeAttrSpec::Extends &);
  bool Pre(const parser::PrivateStmt &);
  bool Pre(const parser::SequenceStmt &);
  bool Pre(const parser::ComponentDefStmt &) { return BeginDecl(); }
  void Post(const parser::ComponentDefStmt &) { EndDecl(); }
  void Post(const parser::ComponentDecl &);
  void Post(const parser::FillDecl &);
  bool Pre(const parser::ProcedureDeclarationStmt &);
  void Post(const parser::ProcedureDeclarationStmt &);
  bool Pre(const parser::DataComponentDefStmt &); // returns false
  bool Pre(const parser::ProcComponentDefStmt &);
  void Post(const parser::ProcComponentDefStmt &);
  bool Pre(const parser::ProcPointerInit &);
  void Post(const parser::ProcInterface &);
  void Post(const parser::ProcDecl &);
  bool Pre(const parser::TypeBoundProcedurePart &);
  void Post(const parser::TypeBoundProcedurePart &);
  void Post(const parser::ContainsStmt &);
  bool Pre(const parser::TypeBoundProcBinding &) { return BeginAttrs(); }
  void Post(const parser::TypeBoundProcBinding &) { EndAttrs(); }
  void Post(const parser::TypeBoundProcedureStmt::WithoutInterface &);
  void Post(const parser::TypeBoundProcedureStmt::WithInterface &);
  bool Pre(const parser::FinalProcedureStmt &);
  bool Pre(const parser::TypeBoundGenericStmt &);
  bool Pre(const parser::StructureDef &); // returns false
  bool Pre(const parser::Union::UnionStmt &);
  bool Pre(const parser::StructureField &);
  void Post(const parser::StructureField &);
  bool Pre(const parser::AllocateStmt &);
  void Post(const parser::AllocateStmt &);
  bool Pre(const parser::StructureConstructor &);
  bool Pre(const parser::NamelistStmt::Group &);
  bool Pre(const parser::IoControlSpec &);
  bool Pre(const parser::CommonStmt::Block &);
  bool Pre(const parser::CommonBlockObject &);
  void Post(const parser::CommonBlockObject &);
  bool Pre(const parser::EquivalenceStmt &);
  bool Pre(const parser::SaveStmt &);
  bool Pre(const parser::BasedPointer &);
  void Post(const parser::BasedPointer &);

  void PointerInitialization(
      const parser::Name &, const parser::InitialDataTarget &);
  void PointerInitialization(
      const parser::Name &, const parser::ProcPointerInit &);
  void NonPointerInitialization(
      const parser::Name &, const parser::ConstantExpr &);
  void CheckExplicitInterface(const parser::Name &);
  void CheckBindings(const parser::TypeBoundProcedureStmt::WithoutInterface &);

  const parser::Name *ResolveDesignator(const parser::Designator &);
  int GetVectorElementKind(
      TypeCategory category, const std::optional<parser::KindSelector> &kind);

protected:
  bool BeginDecl();
  void EndDecl();
  Symbol &DeclareObjectEntity(const parser::Name &, Attrs = Attrs{});
  // Make sure that there's an entity in an enclosing scope called Name
  Symbol &FindOrDeclareEnclosingEntity(const parser::Name &);
  // Declare a LOCAL/LOCAL_INIT entity. If there isn't a type specified
  // it comes from the entity in the containing scope, or implicit rules.
  // Return pointer to the new symbol, or nullptr on error.
  Symbol *DeclareLocalEntity(const parser::Name &);
  // Declare a statement entity (i.e., an implied DO loop index for
  // a DATA statement or an array constructor).  If there isn't an explict
  // type specified, implicit rules apply. Return pointer to the new symbol,
  // or nullptr on error.
  Symbol *DeclareStatementEntity(const parser::DoVariable &,
      const std::optional<parser::IntegerTypeSpec> &);
  Symbol &MakeCommonBlockSymbol(const parser::Name &);
  Symbol &MakeCommonBlockSymbol(const std::optional<parser::Name> &);
  bool CheckUseError(const parser::Name &);
  void CheckAccessibility(const SourceName &, bool, Symbol &);
  void CheckCommonBlocks();
  void CheckSaveStmts();
  void CheckEquivalenceSets();
  bool CheckNotInBlock(const char *);
  bool NameIsKnownOrIntrinsic(const parser::Name &);
  void FinishNamelists();

  // Each of these returns a pointer to a resolved Name (i.e. with symbol)
  // or nullptr in case of error.
  const parser::Name *ResolveStructureComponent(
      const parser::StructureComponent &);
  const parser::Name *ResolveDataRef(const parser::DataRef &);
  const parser::Name *ResolveName(const parser::Name &);
  bool PassesSharedLocalityChecks(const parser::Name &name, Symbol &symbol);
  Symbol *NoteInterfaceName(const parser::Name &);
  bool IsUplevelReference(const Symbol &);

  std::optional<SourceName> BeginCheckOnIndexUseInOwnBounds(
      const parser::DoVariable &name) {
    std::optional<SourceName> result{checkIndexUseInOwnBounds_};
    checkIndexUseInOwnBounds_ = name.thing.thing.source;
    return result;
  }
  void EndCheckOnIndexUseInOwnBounds(const std::optional<SourceName> &restore) {
    checkIndexUseInOwnBounds_ = restore;
  }
  void NoteScalarSpecificationArgument(const Symbol &symbol) {
    mustBeScalar_.emplace(symbol);
  }

private:
  // The attribute corresponding to the statement containing an ObjectDecl
  std::optional<Attr> objectDeclAttr_;
  // Info about current character type while walking DeclTypeSpec.
  // Also captures any "*length" specifier on an individual declaration.
  struct {
    std::optional<ParamValue> length;
    std::optional<KindExpr> kind;
  } charInfo_;
  // Info about current derived type or STRUCTURE while walking
  // DerivedTypeDef / StructureDef
  struct {
    const parser::Name *extends{nullptr}; // EXTENDS(name)
    bool privateComps{false}; // components are private by default
    bool privateBindings{false}; // bindings are private by default
    bool sawContains{false}; // currently processing bindings
    bool sequence{false}; // is a sequence type
    const Symbol *type{nullptr}; // derived type being defined
    bool isStructure{false}; // is a DEC STRUCTURE
  } derivedTypeInfo_;
  // In a ProcedureDeclarationStmt or ProcComponentDefStmt, this is
  // the interface name, if any.
  const parser::Name *interfaceName_{nullptr};
  // Map type-bound generic to binding names of its specific bindings
  std::multimap<Symbol *, const parser::Name *> genericBindings_;
  // Info about current ENUM
  struct EnumeratorState {
    // Enum value must hold inside a C_INT (7.6.2).
    std::optional<int> value{0};
  } enumerationState_;
  // Set for OldParameterStmt processing
  bool inOldStyleParameterStmt_{false};
  // Set when walking DATA & array constructor implied DO loop bounds
  // to warn about use of the implied DO intex therein.
  std::optional<SourceName> checkIndexUseInOwnBounds_;
  bool isVectorType_{false};
  UnorderedSymbolSet mustBeScalar_;

  bool HandleAttributeStmt(Attr, const std::list<parser::Name> &);
  Symbol &HandleAttributeStmt(Attr, const parser::Name &);
  Symbol &DeclareUnknownEntity(const parser::Name &, Attrs);
  Symbol &DeclareProcEntity(
      const parser::Name &, Attrs, const Symbol *interface);
  void SetType(const parser::Name &, const DeclTypeSpec &);
  std::optional<DerivedTypeSpec> ResolveDerivedType(const parser::Name &);
  std::optional<DerivedTypeSpec> ResolveExtendsType(
      const parser::Name &, const parser::Name *);
  Symbol *MakeTypeSymbol(const SourceName &, Details &&);
  Symbol *MakeTypeSymbol(const parser::Name &, Details &&);
  bool OkToAddComponent(const parser::Name &, const Symbol * = nullptr);
  ParamValue GetParamValue(
      const parser::TypeParamValue &, common::TypeParamAttr attr);
  void CheckCommonBlockDerivedType(
      const SourceName &, const Symbol &, UnorderedSymbolSet &);
  Attrs HandleSaveName(const SourceName &, Attrs);
  void AddSaveName(std::set<SourceName> &, const SourceName &);
  bool HandleUnrestrictedSpecificIntrinsicFunction(const parser::Name &);
  const parser::Name *FindComponent(const parser::Name *, const parser::Name &);
  void Initialization(const parser::Name &, const parser::Initialization &,
      bool inComponentDecl);
  bool PassesLocalityChecks(const parser::Name &name, Symbol &symbol);
  bool CheckForHostAssociatedImplicit(const parser::Name &);

  // Declare an object or procedure entity.
  // T is one of: EntityDetails, ObjectEntityDetails, ProcEntityDetails
  template <typename T>
  Symbol &DeclareEntity(const parser::Name &name, Attrs attrs) {
    Symbol &symbol{MakeSymbol(name, attrs)};
    if (context().HasError(symbol) || symbol.has<T>()) {
      return symbol; // OK or error already reported
    } else if (symbol.has<UnknownDetails>()) {
      symbol.set_details(T{});
      return symbol;
    } else if (auto *details{symbol.detailsIf<EntityDetails>()}) {
      symbol.set_details(T{std::move(*details)});
      return symbol;
    } else if (std::is_same_v<EntityDetails, T> &&
        (symbol.has<ObjectEntityDetails>() ||
            symbol.has<ProcEntityDetails>())) {
      return symbol; // OK
    } else if (auto *details{symbol.detailsIf<UseDetails>()}) {
      Say(name.source,
          "'%s' is use-associated from module '%s' and cannot be re-declared"_err_en_US,
          name.source, GetUsedModule(*details).name());
    } else if (auto *details{symbol.detailsIf<SubprogramNameDetails>()}) {
      if (details->kind() == SubprogramKind::Module) {
        Say2(name,
            "Declaration of '%s' conflicts with its use as module procedure"_err_en_US,
            symbol, "Module procedure definition"_en_US);
      } else if (details->kind() == SubprogramKind::Internal) {
        Say2(name,
            "Declaration of '%s' conflicts with its use as internal procedure"_err_en_US,
            symbol, "Internal procedure definition"_en_US);
      } else {
        DIE("unexpected kind");
      }
    } else if (std::is_same_v<ObjectEntityDetails, T> &&
        symbol.has<ProcEntityDetails>()) {
      SayWithDecl(
          name, symbol, "'%s' is already declared as a procedure"_err_en_US);
    } else if (std::is_same_v<ProcEntityDetails, T> &&
        symbol.has<ObjectEntityDetails>()) {
      if (FindCommonBlockContaining(symbol)) {
        SayWithDecl(name, symbol,
            "'%s' may not be a procedure as it is in a COMMON block"_err_en_US);
      } else {
        SayWithDecl(
            name, symbol, "'%s' is already declared as an object"_err_en_US);
      }
    } else if (!CheckPossibleBadForwardRef(symbol)) {
      SayAlreadyDeclared(name, symbol);
    }
    context().SetError(symbol);
    return symbol;
  }
  bool HasCycle(const Symbol &, const Symbol *interface);
  bool MustBeScalar(const Symbol &symbol) const {
    return mustBeScalar_.find(symbol) != mustBeScalar_.end();
  }
  void DeclareIntrinsic(const parser::Name &);
};

// Resolve construct entities and statement entities.
// Check that construct names don't conflict with other names.
class ConstructVisitor : public virtual DeclarationVisitor {
public:
  bool Pre(const parser::ConcurrentHeader &);
  bool Pre(const parser::LocalitySpec::Local &);
  bool Pre(const parser::LocalitySpec::LocalInit &);
  bool Pre(const parser::LocalitySpec::Shared &);
  bool Pre(const parser::AcSpec &);
  bool Pre(const parser::AcImpliedDo &);
  bool Pre(const parser::DataImpliedDo &);
  bool Pre(const parser::DataIDoObject &);
  bool Pre(const parser::DataStmtObject &);
  bool Pre(const parser::DataStmtValue &);
  bool Pre(const parser::DoConstruct &);
  void Post(const parser::DoConstruct &);
  bool Pre(const parser::ForallConstruct &);
  void Post(const parser::ForallConstruct &);
  bool Pre(const parser::ForallStmt &);
  void Post(const parser::ForallStmt &);
  bool Pre(const parser::BlockConstruct &);
  void Post(const parser::Selector &);
  void Post(const parser::AssociateStmt &);
  void Post(const parser::EndAssociateStmt &);
  bool Pre(const parser::Association &);
  void Post(const parser::SelectTypeStmt &);
  void Post(const parser::SelectRankStmt &);
  bool Pre(const parser::SelectTypeConstruct &);
  void Post(const parser::SelectTypeConstruct &);
  bool Pre(const parser::SelectTypeConstruct::TypeCase &);
  void Post(const parser::SelectTypeConstruct::TypeCase &);
  // Creates Block scopes with neither symbol name nor symbol details.
  bool Pre(const parser::SelectRankConstruct::RankCase &);
  void Post(const parser::SelectRankConstruct::RankCase &);
  bool Pre(const parser::TypeGuardStmt::Guard &);
  void Post(const parser::TypeGuardStmt::Guard &);
  void Post(const parser::SelectRankCaseStmt::Rank &);
  bool Pre(const parser::ChangeTeamStmt &);
  void Post(const parser::EndChangeTeamStmt &);
  void Post(const parser::CoarrayAssociation &);

  // Definitions of construct names
  bool Pre(const parser::WhereConstructStmt &x) { return CheckDef(x.t); }
  bool Pre(const parser::ForallConstructStmt &x) { return CheckDef(x.t); }
  bool Pre(const parser::CriticalStmt &x) { return CheckDef(x.t); }
  bool Pre(const parser::LabelDoStmt &) {
    return false; // error recovery
  }
  bool Pre(const parser::NonLabelDoStmt &x) { return CheckDef(x.t); }
  bool Pre(const parser::IfThenStmt &x) { return CheckDef(x.t); }
  bool Pre(const parser::SelectCaseStmt &x) { return CheckDef(x.t); }
  bool Pre(const parser::SelectRankConstruct &);
  void Post(const parser::SelectRankConstruct &);
  bool Pre(const parser::SelectRankStmt &x) {
    return CheckDef(std::get<0>(x.t));
  }
  bool Pre(const parser::SelectTypeStmt &x) {
    return CheckDef(std::get<0>(x.t));
  }

  // References to construct names
  void Post(const parser::MaskedElsewhereStmt &x) { CheckRef(x.t); }
  void Post(const parser::ElsewhereStmt &x) { CheckRef(x.v); }
  void Post(const parser::EndWhereStmt &x) { CheckRef(x.v); }
  void Post(const parser::EndForallStmt &x) { CheckRef(x.v); }
  void Post(const parser::EndCriticalStmt &x) { CheckRef(x.v); }
  void Post(const parser::EndDoStmt &x) { CheckRef(x.v); }
  void Post(const parser::ElseIfStmt &x) { CheckRef(x.t); }
  void Post(const parser::ElseStmt &x) { CheckRef(x.v); }
  void Post(const parser::EndIfStmt &x) { CheckRef(x.v); }
  void Post(const parser::CaseStmt &x) { CheckRef(x.t); }
  void Post(const parser::EndSelectStmt &x) { CheckRef(x.v); }
  void Post(const parser::SelectRankCaseStmt &x) { CheckRef(x.t); }
  void Post(const parser::TypeGuardStmt &x) { CheckRef(x.t); }
  void Post(const parser::CycleStmt &x) { CheckRef(x.v); }
  void Post(const parser::ExitStmt &x) { CheckRef(x.v); }

  void HandleImpliedAsynchronousInScope(const parser::Block &);

private:
  // R1105 selector -> expr | variable
  // expr is set in either case unless there were errors
  struct Selector {
    Selector() {}
    Selector(const SourceName &source, MaybeExpr &&expr)
        : source{source}, expr{std::move(expr)} {}
    operator bool() const { return expr.has_value(); }
    parser::CharBlock source;
    MaybeExpr expr;
  };
  // association -> [associate-name =>] selector
  struct Association {
    const parser::Name *name{nullptr};
    Selector selector;
  };
  std::vector<Association> associationStack_;
  Association *currentAssociation_{nullptr};

  template <typename T> bool CheckDef(const T &t) {
    return CheckDef(std::get<std::optional<parser::Name>>(t));
  }
  template <typename T> void CheckRef(const T &t) {
    CheckRef(std::get<std::optional<parser::Name>>(t));
  }
  bool CheckDef(const std::optional<parser::Name> &);
  void CheckRef(const std::optional<parser::Name> &);
  const DeclTypeSpec &ToDeclTypeSpec(evaluate::DynamicType &&);
  const DeclTypeSpec &ToDeclTypeSpec(
      evaluate::DynamicType &&, MaybeSubscriptIntExpr &&length);
  Symbol *MakeAssocEntity();
  void SetTypeFromAssociation(Symbol &);
  void SetAttrsFromAssociation(Symbol &);
  Selector ResolveSelector(const parser::Selector &);
  void ResolveIndexName(const parser::ConcurrentControl &control);
  void SetCurrentAssociation(std::size_t n);
  Association &GetCurrentAssociation();
  void PushAssociation();
  void PopAssociation(std::size_t count = 1);
};

// Create scopes for OpenACC constructs
class AccVisitor : public virtual DeclarationVisitor {
public:
  void AddAccSourceRange(const parser::CharBlock &);

  static bool NeedsScope(const parser::OpenACCBlockConstruct &);

  bool Pre(const parser::OpenACCBlockConstruct &);
  void Post(const parser::OpenACCBlockConstruct &);
  bool Pre(const parser::OpenACCCombinedConstruct &);
  void Post(const parser::OpenACCCombinedConstruct &);
  bool Pre(const parser::AccBeginBlockDirective &x) {
    AddAccSourceRange(x.source);
    return true;
  }
  void Post(const parser::AccBeginBlockDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }
  bool Pre(const parser::AccEndBlockDirective &x) {
    AddAccSourceRange(x.source);
    return true;
  }
  void Post(const parser::AccEndBlockDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }
  bool Pre(const parser::AccBeginLoopDirective &x) {
    AddAccSourceRange(x.source);
    return true;
  }
  void Post(const parser::AccBeginLoopDirective &x) {
    messageHandler().set_currStmtSource(std::nullopt);
  }
};

bool AccVisitor::NeedsScope(const parser::OpenACCBlockConstruct &x) {
  const auto &beginBlockDir{std::get<parser::AccBeginBlockDirective>(x.t)};
  const auto &beginDir{std::get<parser::AccBlockDirective>(beginBlockDir.t)};
  switch (beginDir.v) {
  case llvm::acc::Directive::ACCD_data:
  case llvm::acc::Directive::ACCD_host_data:
  case llvm::acc::Directive::ACCD_kernels:
  case llvm::acc::Directive::ACCD_parallel:
  case llvm::acc::Directive::ACCD_serial:
    return true;
  default:
    return false;
  }
}

void AccVisitor::AddAccSourceRange(const parser::CharBlock &source) {
  messageHandler().set_currStmtSource(source);
  currScope().AddSourceRange(source);
}

bool AccVisitor::Pre(const parser::OpenACCBlockConstruct &x) {
  if (NeedsScope(x)) {
    PushScope(Scope::Kind::OpenACCConstruct, nullptr);
  }
  return true;
}

void AccVisitor::Post(const parser::OpenACCBlockConstruct &x) {
  if (NeedsScope(x)) {
    PopScope();
  }
}

bool AccVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
  PushScope(Scope::Kind::OpenACCConstruct, nullptr);
  return true;
}

void AccVisitor::Post(const parser::OpenACCCombinedConstruct &x) { PopScope(); }

// Create scopes for OpenMP constructs
class OmpVisitor : public virtual DeclarationVisitor {
public:
  void AddOmpSourceRange(const parser::CharBlock &);

  static bool NeedsScope(const parser::OpenMPBlockConstruct &);

  bool Pre(const parser::OpenMPRequiresConstruct &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  bool Pre(const parser::OmpSimpleStandaloneDirective &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  bool Pre(const parser::OpenMPBlockConstruct &);
  void Post(const parser::OpenMPBlockConstruct &);
  bool Pre(const parser::OmpBeginBlockDirective &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  void Post(const parser::OmpBeginBlockDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }
  bool Pre(const parser::OmpEndBlockDirective &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  void Post(const parser::OmpEndBlockDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }

  bool Pre(const parser::OpenMPLoopConstruct &) {
    PushScope(Scope::Kind::OtherConstruct, nullptr);
    return true;
  }
  void Post(const parser::OpenMPLoopConstruct &) { PopScope(); }
  bool Pre(const parser::OmpBeginLoopDirective &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  void Post(const parser::OmpBeginLoopDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }
  bool Pre(const parser::OmpEndLoopDirective &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  void Post(const parser::OmpEndLoopDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }

  bool Pre(const parser::OpenMPSectionsConstruct &) {
    PushScope(Scope::Kind::OtherConstruct, nullptr);
    return true;
  }
  void Post(const parser::OpenMPSectionsConstruct &) { PopScope(); }
  bool Pre(const parser::OmpBeginSectionsDirective &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  void Post(const parser::OmpBeginSectionsDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }
  bool Pre(const parser::OmpEndSectionsDirective &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  void Post(const parser::OmpEndSectionsDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }
  bool Pre(const parser::OmpCriticalDirective &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  void Post(const parser::OmpCriticalDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }
  bool Pre(const parser::OmpEndCriticalDirective &x) {
    AddOmpSourceRange(x.source);
    return true;
  }
  void Post(const parser::OmpEndCriticalDirective &) {
    messageHandler().set_currStmtSource(std::nullopt);
  }
};

bool OmpVisitor::NeedsScope(const parser::OpenMPBlockConstruct &x) {
  const auto &beginBlockDir{std::get<parser::OmpBeginBlockDirective>(x.t)};
  const auto &beginDir{std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
  switch (beginDir.v) {
  case llvm::omp::Directive::OMPD_master:
  case llvm::omp::Directive::OMPD_ordered:
  case llvm::omp::Directive::OMPD_taskgroup:
    return false;
  default:
    return true;
  }
}

void OmpVisitor::AddOmpSourceRange(const parser::CharBlock &source) {
  messageHandler().set_currStmtSource(source);
  currScope().AddSourceRange(source);
}

bool OmpVisitor::Pre(const parser::OpenMPBlockConstruct &x) {
  if (NeedsScope(x)) {
    PushScope(Scope::Kind::OtherConstruct, nullptr);
  }
  return true;
}

void OmpVisitor::Post(const parser::OpenMPBlockConstruct &x) {
  if (NeedsScope(x)) {
    PopScope();
  }
}

// Walk the parse tree and resolve names to symbols.
class ResolveNamesVisitor : public virtual ScopeHandler,
                            public ModuleVisitor,
                            public SubprogramVisitor,
                            public ConstructVisitor,
                            public OmpVisitor,
                            public AccVisitor {
public:
  using AccVisitor::Post;
  using AccVisitor::Pre;
  using ArraySpecVisitor::Post;
  using ConstructVisitor::Post;
  using ConstructVisitor::Pre;
  using DeclarationVisitor::Post;
  using DeclarationVisitor::Pre;
  using ImplicitRulesVisitor::Post;
  using ImplicitRulesVisitor::Pre;
  using InterfaceVisitor::Post;
  using InterfaceVisitor::Pre;
  using ModuleVisitor::Post;
  using ModuleVisitor::Pre;
  using OmpVisitor::Post;
  using OmpVisitor::Pre;
  using ScopeHandler::Post;
  using ScopeHandler::Pre;
  using SubprogramVisitor::Post;
  using SubprogramVisitor::Pre;

  ResolveNamesVisitor(
      SemanticsContext &context, ImplicitRulesMap &rules, Scope &top)
      : BaseVisitor{context, *this, rules}, topScope_{top} {
    PushScope(top);
  }

  Scope &topScope() const { return topScope_; }

  // Default action for a parse tree node is to visit children.
  template <typename T> bool Pre(const T &) { return true; }
  template <typename T> void Post(const T &) {}

  bool Pre(const parser::SpecificationPart &);
  bool Pre(const parser::Program &);
  void Post(const parser::Program &);
  bool Pre(const parser::ImplicitStmt &);
  void Post(const parser::PointerObject &);
  void Post(const parser::AllocateObject &);
  bool Pre(const parser::PointerAssignmentStmt &);
  void Post(const parser::Designator &);
  void Post(const parser::SubstringInquiry &);
  template <typename A, typename B>
  void Post(const parser::LoopBounds<A, B> &x) {
    ResolveName(*parser::Unwrap<parser::Name>(x.name));
  }
  void Post(const parser::ProcComponentRef &);
  bool Pre(const parser::FunctionReference &);
  bool Pre(const parser::CallStmt &);
  bool Pre(const parser::ImportStmt &);
  void Post(const parser::TypeGuardStmt &);
  bool Pre(const parser::StmtFunctionStmt &);
  bool Pre(const parser::DefinedOpName &);
  bool Pre(const parser::ProgramUnit &);
  void Post(const parser::AssignStmt &);
  void Post(const parser::AssignedGotoStmt &);
  void Post(const parser::CompilerDirective &);

  // These nodes should never be reached: they are handled in ProgramUnit
  bool Pre(const parser::MainProgram &) {
    llvm_unreachable("This node is handled in ProgramUnit");
  }
  bool Pre(const parser::FunctionSubprogram &) {
    llvm_unreachable("This node is handled in ProgramUnit");
  }
  bool Pre(const parser::SubroutineSubprogram &) {
    llvm_unreachable("This node is handled in ProgramUnit");
  }
  bool Pre(const parser::SeparateModuleSubprogram &) {
    llvm_unreachable("This node is handled in ProgramUnit");
  }
  bool Pre(const parser::Module &) {
    llvm_unreachable("This node is handled in ProgramUnit");
  }
  bool Pre(const parser::Submodule &) {
    llvm_unreachable("This node is handled in ProgramUnit");
  }
  bool Pre(const parser::BlockData &) {
    llvm_unreachable("This node is handled in ProgramUnit");
  }

  void NoteExecutablePartCall(Symbol::Flag, SourceName, bool hasCUDAChevrons);

  friend void ResolveSpecificationParts(SemanticsContext &, const Symbol &);

private:
  // Kind of procedure we are expecting to see in a ProcedureDesignator
  std::optional<Symbol::Flag> expectedProcFlag_;
  std::optional<SourceName> prevImportStmt_;
  Scope &topScope_;

  void PreSpecificationConstruct(const parser::SpecificationConstruct &);
  void CreateCommonBlockSymbols(const parser::CommonStmt &);
  void CreateGeneric(const parser::GenericSpec &);
  void FinishSpecificationPart(const std::list<parser::DeclarationConstruct> &);
  void AnalyzeStmtFunctionStmt(const parser::StmtFunctionStmt &);
  void CheckImports();
  void CheckImport(const SourceName &, const SourceName &);
  void HandleCall(Symbol::Flag, const parser::Call &);
  void HandleProcedureName(Symbol::Flag, const parser::Name &);
  bool CheckImplicitNoneExternal(const SourceName &, const Symbol &);
  bool SetProcFlag(const parser::Name &, Symbol &, Symbol::Flag);
  void ResolveSpecificationParts(ProgramTree &);
  void AddSubpNames(ProgramTree &);
  bool BeginScopeForNode(const ProgramTree &);
  void EndScopeForNode(const ProgramTree &);
  void FinishSpecificationParts(const ProgramTree &);
  void FinishExecutionParts(const ProgramTree &);
  void FinishDerivedTypeInstantiation(Scope &);
  void ResolveExecutionParts(const ProgramTree &);
  void UseCUDABuiltinNames();
  void HandleDerivedTypesInImplicitStmts(const parser::ImplicitPart &,
      const std::list<parser::DeclarationConstruct> &);
};

// ImplicitRules implementation

bool ImplicitRules::isImplicitNoneType() const {
  if (isImplicitNoneType_) {
    return true;
  } else if (map_.empty() && inheritFromParent_) {
    return parent_->isImplicitNoneType();
  } else {
    return false; // default if not specified
  }
}

bool ImplicitRules::isImplicitNoneExternal() const {
  if (isImplicitNoneExternal_) {
    return true;
  } else if (inheritFromParent_) {
    return parent_->isImplicitNoneExternal();
  } else {
    return false; // default if not specified
  }
}

const DeclTypeSpec *ImplicitRules::GetType(
    SourceName name, bool respectImplicitNoneType) const {
  char ch{name.begin()[0]};
  if (isImplicitNoneType_ && respectImplicitNoneType) {
    return nullptr;
  } else if (auto it{map_.find(ch)}; it != map_.end()) {
    return &*it->second;
  } else if (inheritFromParent_) {
    return parent_->GetType(name, respectImplicitNoneType);
  } else if (ch >= 'i' && ch <= 'n') {
    return &context_.MakeNumericType(TypeCategory::Integer);
  } else if (ch >= 'a' && ch <= 'z') {
    return &context_.MakeNumericType(TypeCategory::Real);
  } else {
    return nullptr;
  }
}

void ImplicitRules::SetTypeMapping(const DeclTypeSpec &type,
    parser::Location fromLetter, parser::Location toLetter) {
  for (char ch = *fromLetter; ch; ch = ImplicitRules::Incr(ch)) {
    auto res{map_.emplace(ch, type)};
    if (!res.second) {
      context_.Say(parser::CharBlock{fromLetter},
          "More than one implicit type specified for '%c'"_err_en_US, ch);
    }
    if (ch == *toLetter) {
      break;
    }
  }
}

// Return the next char after ch in a way that works for ASCII or EBCDIC.
// Return '\0' for the char after 'z'.
char ImplicitRules::Incr(char ch) {
  switch (ch) {
  case 'i':
    return 'j';
  case 'r':
    return 's';
  case 'z':
    return '\0';
  default:
    return ch + 1;
  }
}

llvm::raw_ostream &operator<<(
    llvm::raw_ostream &o, const ImplicitRules &implicitRules) {
  o << "ImplicitRules:\n";
  for (char ch = 'a'; ch; ch = ImplicitRules::Incr(ch)) {
    ShowImplicitRule(o, implicitRules, ch);
  }
  ShowImplicitRule(o, implicitRules, '_');
  ShowImplicitRule(o, implicitRules, '$');
  ShowImplicitRule(o, implicitRules, '@');
  return o;
}
void ShowImplicitRule(
    llvm::raw_ostream &o, const ImplicitRules &implicitRules, char ch) {
  auto it{implicitRules.map_.find(ch)};
  if (it != implicitRules.map_.end()) {
    o << "  " << ch << ": " << *it->second << '\n';
  }
}

template <typename T> void BaseVisitor::Walk(const T &x) {
  parser::Walk(x, *this_);
}

void BaseVisitor::MakePlaceholder(
    const parser::Name &name, MiscDetails::Kind kind) {
  if (!name.symbol) {
    name.symbol = &context_->globalScope().MakeSymbol(
        name.source, Attrs{}, MiscDetails{kind});
  }
}

// AttrsVisitor implementation

bool AttrsVisitor::BeginAttrs() {
  CHECK(!attrs_ && !cudaDataAttr_);
  attrs_ = Attrs{};
  return true;
}
Attrs AttrsVisitor::GetAttrs() {
  CHECK(attrs_);
  return *attrs_;
}
Attrs AttrsVisitor::EndAttrs() {
  Attrs result{GetAttrs()};
  attrs_.reset();
  cudaDataAttr_.reset();
  passName_ = std::nullopt;
  bindName_.reset();
  return result;
}

bool AttrsVisitor::SetPassNameOn(Symbol &symbol) {
  if (!passName_) {
    return false;
  }
  common::visit(common::visitors{
                    [&](ProcEntityDetails &x) { x.set_passName(*passName_); },
                    [&](ProcBindingDetails &x) { x.set_passName(*passName_); },
                    [](auto &) { common::die("unexpected pass name"); },
                },
      symbol.details());
  return true;
}

void AttrsVisitor::SetBindNameOn(Symbol &symbol) {
  if ((!attrs_ || !attrs_->test(Attr::BIND_C)) &&
      !symbol.attrs().test(Attr::BIND_C)) {
    return;
  }
  std::optional<std::string> label{
      evaluate::GetScalarConstantValue<evaluate::Ascii>(bindName_)};
  // 18.9.2(2): discard leading and trailing blanks
  if (label) {
    symbol.SetIsExplicitBindName(true);
    auto first{label->find_first_not_of(" ")};
    if (first == std::string::npos) {
      // Empty NAME= means no binding at all (18.10.2p2)
      return;
    }
    auto last{label->find_last_not_of(" ")};
    label = label->substr(first, last - first + 1);
  } else if (ClassifyProcedure(symbol) == ProcedureDefinitionClass::Internal) {
    // BIND(C) does not give an implicit binding label to internal procedures.
    return;
  } else {
    label = symbol.name().ToString();
  }
  // Checks whether a symbol has two Bind names.
  std::string oldBindName;
  if (const auto *bindName{symbol.GetBindName()}) {
    oldBindName = *bindName;
  }
  symbol.SetBindName(std::move(*label));
  if (!oldBindName.empty()) {
    if (const std::string * newBindName{symbol.GetBindName()}) {
      if (oldBindName != *newBindName) {
        Say(symbol.name(),
            "The entity '%s' has multiple BIND names ('%s' and '%s')"_err_en_US,
            symbol.name(), oldBindName, *newBindName);
      }
    }
  }
}

void AttrsVisitor::Post(const parser::LanguageBindingSpec &x) {
  if (CheckAndSet(Attr::BIND_C)) {
    if (x.v) {
      bindName_ = EvaluateExpr(*x.v);
    }
  }
}
bool AttrsVisitor::Pre(const parser::IntentSpec &x) {
  CheckAndSet(IntentSpecToAttr(x));
  return false;
}
bool AttrsVisitor::Pre(const parser::Pass &x) {
  if (CheckAndSet(Attr::PASS)) {
    if (x.v) {
      passName_ = x.v->source;
      MakePlaceholder(*x.v, MiscDetails::Kind::PassName);
    }
  }
  return false;
}

// C730, C743, C755, C778, C1543 say no attribute or prefix repetitions
bool AttrsVisitor::IsDuplicateAttr(Attr attrName) {
  CHECK(attrs_);
  if (attrs_->test(attrName)) {
    Say(currStmtSource().value(),
        "Attribute '%s' cannot be used more than once"_warn_en_US,
        AttrToString(attrName));
    return true;
  }
  return false;
}

// See if attrName violates a constraint cause by a conflict.  attr1 and attr2
// name attributes that cannot be used on the same declaration
bool AttrsVisitor::HaveAttrConflict(Attr attrName, Attr attr1, Attr attr2) {
  CHECK(attrs_);
  if ((attrName == attr1 && attrs_->test(attr2)) ||
      (attrName == attr2 && attrs_->test(attr1))) {
    Say(currStmtSource().value(),
        "Attributes '%s' and '%s' conflict with each other"_err_en_US,
        AttrToString(attr1), AttrToString(attr2));
    return true;
  }
  return false;
}
// C759, C1543
bool AttrsVisitor::IsConflictingAttr(Attr attrName) {
  return HaveAttrConflict(attrName, Attr::INTENT_IN, Attr::INTENT_INOUT) ||
      HaveAttrConflict(attrName, Attr::INTENT_IN, Attr::INTENT_OUT) ||
      HaveAttrConflict(attrName, Attr::INTENT_INOUT, Attr::INTENT_OUT) ||
      HaveAttrConflict(attrName, Attr::PASS, Attr::NOPASS) || // C781
      HaveAttrConflict(attrName, Attr::PURE, Attr::IMPURE) ||
      HaveAttrConflict(attrName, Attr::PUBLIC, Attr::PRIVATE) ||
      HaveAttrConflict(attrName, Attr::RECURSIVE, Attr::NON_RECURSIVE);
}
bool AttrsVisitor::CheckAndSet(Attr attrName) {
  if (IsConflictingAttr(attrName) || IsDuplicateAttr(attrName)) {
    return false;
  }
  attrs_->set(attrName);
  return true;
}
bool AttrsVisitor::Pre(const common::CUDADataAttr x) {
  if (cudaDataAttr_.value_or(x) != x) {
    Say(currStmtSource().value(),
        "CUDA data attributes '%s' and '%s' may not both be specified"_err_en_US,
        common::EnumToString(*cudaDataAttr_), common::EnumToString(x));
  }
  cudaDataAttr_ = x;
  return false;
}

// DeclTypeSpecVisitor implementation

const DeclTypeSpec *DeclTypeSpecVisitor::GetDeclTypeSpec() {
  return state_.declTypeSpec;
}

void DeclTypeSpecVisitor::BeginDeclTypeSpec() {
  CHECK(!state_.expectDeclTypeSpec);
  CHECK(!state_.declTypeSpec);
  state_.expectDeclTypeSpec = true;
}
void DeclTypeSpecVisitor::EndDeclTypeSpec() {
  CHECK(state_.expectDeclTypeSpec);
  state_ = {};
}

void DeclTypeSpecVisitor::SetDeclTypeSpecCategory(
    DeclTypeSpec::Category category) {
  CHECK(state_.expectDeclTypeSpec);
  state_.derived.category = category;
}

bool DeclTypeSpecVisitor::Pre(const parser::TypeGuardStmt &) {
  BeginDeclTypeSpec();
  return true;
}
void DeclTypeSpecVisitor::Post(const parser::TypeGuardStmt &) {
  EndDeclTypeSpec();
}

void DeclTypeSpecVisitor::Post(const parser::TypeSpec &typeSpec) {
  // Record the resolved DeclTypeSpec in the parse tree for use by
  // expression semantics if the DeclTypeSpec is a valid TypeSpec.
  // The grammar ensures that it's an intrinsic or derived type spec,
  // not TYPE(*) or CLASS(*) or CLASS(T).
  if (const DeclTypeSpec * spec{state_.declTypeSpec}) {
    switch (spec->category()) {
    case DeclTypeSpec::Numeric:
    case DeclTypeSpec::Logical:
    case DeclTypeSpec::Character:
      typeSpec.declTypeSpec = spec;
      break;
    case DeclTypeSpec::TypeDerived:
      if (const DerivedTypeSpec * derived{spec->AsDerived()}) {
        CheckForAbstractType(derived->typeSymbol()); // C703
        typeSpec.declTypeSpec = spec;
      }
      break;
    default:
      CRASH_NO_CASE;
    }
  }
}

void DeclTypeSpecVisitor::Post(
    const parser::IntrinsicTypeSpec::DoublePrecision &) {
  MakeNumericType(TypeCategory::Real, context().doublePrecisionKind());
}
void DeclTypeSpecVisitor::Post(
    const parser::IntrinsicTypeSpec::DoubleComplex &) {
  MakeNumericType(TypeCategory::Complex, context().doublePrecisionKind());
}
void DeclTypeSpecVisitor::MakeNumericType(TypeCategory category, int kind) {
  SetDeclTypeSpec(context().MakeNumericType(category, kind));
}

void DeclTypeSpecVisitor::CheckForAbstractType(const Symbol &typeSymbol) {
  if (typeSymbol.attrs().test(Attr::ABSTRACT)) {
    Say("ABSTRACT derived type may not be used here"_err_en_US);
  }
}

void DeclTypeSpecVisitor::Post(const parser::DeclarationTypeSpec::ClassStar &) {
  SetDeclTypeSpec(context().globalScope().MakeClassStarType());
}
void DeclTypeSpecVisitor::Post(const parser::DeclarationTypeSpec::TypeStar &) {
  SetDeclTypeSpec(context().globalScope().MakeTypeStarType());
}

// Check that we're expecting to see a DeclTypeSpec (and haven't seen one yet)
// and save it in state_.declTypeSpec.
void DeclTypeSpecVisitor::SetDeclTypeSpec(const DeclTypeSpec &declTypeSpec) {
  CHECK(state_.expectDeclTypeSpec);
  CHECK(!state_.declTypeSpec);
  state_.declTypeSpec = &declTypeSpec;
}

KindExpr DeclTypeSpecVisitor::GetKindParamExpr(
    TypeCategory category, const std::optional<parser::KindSelector> &kind) {
  return AnalyzeKindSelector(context(), category, kind);
}

// MessageHandler implementation

Message &MessageHandler::Say(MessageFixedText &&msg) {
  return context_->Say(currStmtSource().value(), std::move(msg));
}
Message &MessageHandler::Say(MessageFormattedText &&msg) {
  return context_->Say(currStmtSource().value(), std::move(msg));
}
Message &MessageHandler::Say(const SourceName &name, MessageFixedText &&msg) {
  return Say(name, std::move(msg), name);
}

// ImplicitRulesVisitor implementation

void ImplicitRulesVisitor::Post(const parser::ParameterStmt &) {
  prevParameterStmt_ = currStmtSource();
}

bool ImplicitRulesVisitor::Pre(const parser::ImplicitStmt &x) {
  bool result{
      common::visit(common::visitors{
                        [&](const std::list<ImplicitNoneNameSpec> &y) {
                          return HandleImplicitNone(y);
                        },
                        [&](const std::list<parser::ImplicitSpec> &) {
                          if (prevImplicitNoneType_) {
                            Say("IMPLICIT statement after IMPLICIT NONE or "
                                "IMPLICIT NONE(TYPE) statement"_err_en_US);
                            return false;
                          }
                          implicitRules_->set_isImplicitNoneType(false);
                          return true;
                        },
                    },
          x.u)};
  prevImplicit_ = currStmtSource();
  return result;
}

bool ImplicitRulesVisitor::Pre(const parser::LetterSpec &x) {
  auto loLoc{std::get<parser::Location>(x.t)};
  auto hiLoc{loLoc};
  if (auto hiLocOpt{std::get<std::optional<parser::Location>>(x.t)}) {
    hiLoc = *hiLocOpt;
    if (*hiLoc < *loLoc) {
      Say(hiLoc, "'%s' does not follow '%s' alphabetically"_err_en_US,
          std::string(hiLoc, 1), std::string(loLoc, 1));
      return false;
    }
  }
  implicitRules_->SetTypeMapping(*GetDeclTypeSpec(), loLoc, hiLoc);
  return false;
}

bool ImplicitRulesVisitor::Pre(const parser::ImplicitSpec &) {
  BeginDeclTypeSpec();
  set_allowForwardReferenceToDerivedType(true);
  return true;
}

void ImplicitRulesVisitor::Post(const parser::ImplicitSpec &) {
  set_allowForwardReferenceToDerivedType(false);
  EndDeclTypeSpec();
}

void ImplicitRulesVisitor::SetScope(const Scope &scope) {
  implicitRules_ = &DEREF(implicitRulesMap_).at(&scope);
  prevImplicit_ = std::nullopt;
  prevImplicitNone_ = std::nullopt;
  prevImplicitNoneType_ = std::nullopt;
  prevParameterStmt_ = std::nullopt;
}
void ImplicitRulesVisitor::BeginScope(const Scope &scope) {
  // find or create implicit rules for this scope
  DEREF(implicitRulesMap_).try_emplace(&scope, context(), implicitRules_);
  SetScope(scope);
}

// TODO: for all of these errors, reference previous statement too
bool ImplicitRulesVisitor::HandleImplicitNone(
    const std::list<ImplicitNoneNameSpec> &nameSpecs) {
  if (prevImplicitNone_) {
    Say("More than one IMPLICIT NONE statement"_err_en_US);
    Say(*prevImplicitNone_, "Previous IMPLICIT NONE statement"_en_US);
    return false;
  }
  if (prevParameterStmt_) {
    Say("IMPLICIT NONE statement after PARAMETER statement"_err_en_US);
    return false;
  }
  prevImplicitNone_ = currStmtSource();
  bool implicitNoneTypeNever{
      context().IsEnabled(common::LanguageFeature::ImplicitNoneTypeNever)};
  if (nameSpecs.empty()) {
    if (!implicitNoneTypeNever) {
      prevImplicitNoneType_ = currStmtSource();
      implicitRules_->set_isImplicitNoneType(true);
      if (prevImplicit_) {
        Say("IMPLICIT NONE statement after IMPLICIT statement"_err_en_US);
        return false;
      }
    }
  } else {
    int sawType{0};
    int sawExternal{0};
    for (const auto noneSpec : nameSpecs) {
      switch (noneSpec) {
      case ImplicitNoneNameSpec::External:
        implicitRules_->set_isImplicitNoneExternal(true);
        ++sawExternal;
        break;
      case ImplicitNoneNameSpec::Type:
        if (!implicitNoneTypeNever) {
          prevImplicitNoneType_ = currStmtSource();
          implicitRules_->set_isImplicitNoneType(true);
          if (prevImplicit_) {
            Say("IMPLICIT NONE(TYPE) after IMPLICIT statement"_err_en_US);
            return false;
          }
          ++sawType;
        }
        break;
      }
    }
    if (sawType > 1) {
      Say("TYPE specified more than once in IMPLICIT NONE statement"_err_en_US);
      return false;
    }
    if (sawExternal > 1) {
      Say("EXTERNAL specified more than once in IMPLICIT NONE statement"_err_en_US);
      return false;
    }
  }
  return true;
}

// ArraySpecVisitor implementation

void ArraySpecVisitor::Post(const parser::ArraySpec &x) {
  CHECK(arraySpec_.empty());
  arraySpec_ = AnalyzeArraySpec(context(), x);
}
void ArraySpecVisitor::Post(const parser::ComponentArraySpec &x) {
  CHECK(arraySpec_.empty());
  arraySpec_ = AnalyzeArraySpec(context(), x);
}
void ArraySpecVisitor::Post(const parser::CoarraySpec &x) {
  CHECK(coarraySpec_.empty());
  coarraySpec_ = AnalyzeCoarraySpec(context(), x);
}

const ArraySpec &ArraySpecVisitor::arraySpec() {
  return !arraySpec_.empty() ? arraySpec_ : attrArraySpec_;
}
const ArraySpec &ArraySpecVisitor::coarraySpec() {
  return !coarraySpec_.empty() ? coarraySpec_ : attrCoarraySpec_;
}
void ArraySpecVisitor::BeginArraySpec() {
  CHECK(arraySpec_.empty());
  CHECK(coarraySpec_.empty());
  CHECK(attrArraySpec_.empty());
  CHECK(attrCoarraySpec_.empty());
}
void ArraySpecVisitor::EndArraySpec() {
  CHECK(arraySpec_.empty());
  CHECK(coarraySpec_.empty());
  attrArraySpec_.clear();
  attrCoarraySpec_.clear();
}
void ArraySpecVisitor::PostAttrSpec() {
  // Save dimension/codimension from attrs so we can process array/coarray-spec
  // on the entity-decl
  if (!arraySpec_.empty()) {
    if (attrArraySpec_.empty()) {
      attrArraySpec_ = arraySpec_;
      arraySpec_.clear();
    } else {
      Say(currStmtSource().value(),
          "Attribute 'DIMENSION' cannot be used more than once"_err_en_US);
    }
  }
  if (!coarraySpec_.empty()) {
    if (attrCoarraySpec_.empty()) {
      attrCoarraySpec_ = coarraySpec_;
      coarraySpec_.clear();
    } else {
      Say(currStmtSource().value(),
          "Attribute 'CODIMENSION' cannot be used more than once"_err_en_US);
    }
  }
}

// FuncResultStack implementation

FuncResultStack::~FuncResultStack() { CHECK(stack_.empty()); }

void FuncResultStack::CompleteFunctionResultType() {
  // If the function has a type in the prefix, process it now.
  FuncInfo *info{Top()};
  if (info && &info->scope == &scopeHandler_.currScope()) {
    if (info->parsedType && info->resultSymbol) {
      scopeHandler_.messageHandler().set_currStmtSource(info->source);
      if (const auto *type{
              scopeHandler_.ProcessTypeSpec(*info->parsedType, true)}) {
        Symbol &symbol{*info->resultSymbol};
        if (!scopeHandler_.context().HasError(symbol)) {
          if (symbol.GetType()) {
            scopeHandler_.Say(symbol.name(),
                "Function cannot have both an explicit type prefix and a RESULT suffix"_err_en_US);
            scopeHandler_.context().SetError(symbol);
          } else {
            symbol.SetType(*type);
          }
        }
      }
      info->parsedType = nullptr;
    }
  }
}

// Called from ConvertTo{Object/Proc}Entity to cope with any appearance
// of the function result in a specification expression.
void FuncResultStack::CompleteTypeIfFunctionResult(Symbol &symbol) {
  if (FuncInfo * info{Top()}) {
    if (info->resultSymbol == &symbol) {
      CompleteFunctionResultType();
    }
  }
}

void FuncResultStack::Pop() {
  if (!stack_.empty() && &stack_.back().scope == &scopeHandler_.currScope()) {
    stack_.pop_back();
  }
}

// ScopeHandler implementation

void ScopeHandler::SayAlreadyDeclared(const parser::Name &name, Symbol &prev) {
  SayAlreadyDeclared(name.source, prev);
}
void ScopeHandler::SayAlreadyDeclared(const SourceName &name, Symbol &prev) {
  if (context().HasError(prev)) {
    // don't report another error about prev
  } else {
    if (const auto *details{prev.detailsIf<UseDetails>()}) {
      Say(name, "'%s' is already declared in this scoping unit"_err_en_US)
          .Attach(details->location(),
              "It is use-associated with '%s' in module '%s'"_en_US,
              details->symbol().name(), GetUsedModule(*details).name());
    } else {
      SayAlreadyDeclared(name, prev.name());
    }
    context().SetError(prev);
  }
}
void ScopeHandler::SayAlreadyDeclared(
    const SourceName &name1, const SourceName &name2) {
  if (name1.begin() < name2.begin()) {
    SayAlreadyDeclared(name2, name1);
  } else {
    Say(name1, "'%s' is already declared in this scoping unit"_err_en_US)
        .Attach(name2, "Previous declaration of '%s'"_en_US, name2);
  }
}

void ScopeHandler::SayWithReason(const parser::Name &name, Symbol &symbol,
    MessageFixedText &&msg1, Message &&msg2) {
  bool isFatal{msg1.IsFatal()};
  Say(name, std::move(msg1), symbol.name()).Attach(std::move(msg2));
  context().SetError(symbol, isFatal);
}

void ScopeHandler::SayWithDecl(
    const parser::Name &name, Symbol &symbol, MessageFixedText &&msg) {
  auto &message{Say(name, std::move(msg), symbol.name())
                    .Attach(Message{symbol.name(),
                        symbol.test(Symbol::Flag::Implicit)
                            ? "Implicit declaration of '%s'"_en_US
                            : "Declaration of '%s'"_en_US,
                        name.source})};
  if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {
    if (auto usedAsProc{proc->usedAsProcedureHere()}) {
      if (usedAsProc->begin() != symbol.name().begin()) {
        message.Attach(Message{*usedAsProc, "Referenced as a procedure"_en_US});
      }
    }
  }
}

void ScopeHandler::SayLocalMustBeVariable(
    const parser::Name &name, Symbol &symbol) {
  SayWithDecl(name, symbol,
      "The name '%s' must be a variable to appear"
      " in a locality-spec"_err_en_US);
}

void ScopeHandler::SayDerivedType(
    const SourceName &name, MessageFixedText &&msg, const Scope &type) {
  const Symbol &typeSymbol{DEREF(type.GetSymbol())};
  Say(name, std::move(msg), name, typeSymbol.name())
      .Attach(typeSymbol.name(), "Declaration of derived type '%s'"_en_US,
          typeSymbol.name());
}
void ScopeHandler::Say2(const SourceName &name1, MessageFixedText &&msg1,
    const SourceName &name2, MessageFixedText &&msg2) {
  Say(name1, std::move(msg1)).Attach(name2, std::move(msg2), name2);
}
void ScopeHandler::Say2(const SourceName &name, MessageFixedText &&msg1,
    Symbol &symbol, MessageFixedText &&msg2) {
  bool isFatal{msg1.IsFatal()};
  Say2(name, std::move(msg1), symbol.name(), std::move(msg2));
  context().SetError(symbol, isFatal);
}
void ScopeHandler::Say2(const parser::Name &name, MessageFixedText &&msg1,
    Symbol &symbol, MessageFixedText &&msg2) {
  bool isFatal{msg1.IsFatal()};
  Say2(name.source, std::move(msg1), symbol.name(), std::move(msg2));
  context().SetError(symbol, isFatal);
}

// This is essentially GetProgramUnitContaining(), but it can return
// a mutable Scope &, it ignores statement functions, and it fails
// gracefully for error recovery (returning the original Scope).
template <typename T> static T &GetInclusiveScope(T &scope) {
  for (T *s{&scope}; !s->IsGlobal(); s = &s->parent()) {
    switch (s->kind()) {
    case Scope::Kind::Module:
    case Scope::Kind::MainProgram:
    case Scope::Kind::Subprogram:
    case Scope::Kind::BlockData:
      if (!s->IsStmtFunction()) {
        return *s;
      }
      break;
    default:;
    }
  }
  return scope;
}

Scope &ScopeHandler::InclusiveScope() { return GetInclusiveScope(currScope()); }

Scope *ScopeHandler::GetHostProcedure() {
  Scope &parent{InclusiveScope().parent()};
  switch (parent.kind()) {
  case Scope::Kind::Subprogram:
    return &parent;
  case Scope::Kind::MainProgram:
    return &parent;
  default:
    return nullptr;
  }
}

Scope &ScopeHandler::NonDerivedTypeScope() {
  return currScope_->IsDerivedType() ? currScope_->parent() : *currScope_;
}

void ScopeHandler::PushScope(Scope::Kind kind, Symbol *symbol) {
  PushScope(currScope().MakeScope(kind, symbol));
}
void ScopeHandler::PushScope(Scope &scope) {
  currScope_ = &scope;
  auto kind{currScope_->kind()};
  if (kind != Scope::Kind::BlockConstruct &&
      kind != Scope::Kind::OtherConstruct) {
    BeginScope(scope);
  }
  // The name of a module or submodule cannot be "used" in its scope,
  // as we read 19.3.1(2), so we allow the name to be used as a local
  // identifier in the module or submodule too.  Same with programs
  // (14.1(3)) and BLOCK DATA.
  if (!currScope_->IsDerivedType() && kind != Scope::Kind::Module &&
      kind != Scope::Kind::MainProgram && kind != Scope::Kind::BlockData) {
    if (auto *symbol{scope.symbol()}) {
      // Create a dummy symbol so we can't create another one with the same
      // name. It might already be there if we previously pushed the scope.
      SourceName name{symbol->name()};
      if (!FindInScope(scope, name)) {
        auto &newSymbol{MakeSymbol(name)};
        if (kind == Scope::Kind::Subprogram) {
          // Allow for recursive references.  If this symbol is a function
          // without an explicit RESULT(), this new symbol will be discarded
          // and replaced with an object of the same name.
          newSymbol.set_details(HostAssocDetails{*symbol});
        } else {
          newSymbol.set_details(MiscDetails{MiscDetails::Kind::ScopeName});
        }
      }
    }
  }
}
void ScopeHandler::PopScope() {
  CHECK(currScope_ && !currScope_->IsGlobal());
  // Entities that are not yet classified as objects or procedures are now
  // assumed to be objects.
  // TODO: Statement functions
  for (auto &pair : currScope()) {
    ConvertToObjectEntity(*pair.second);
  }
  funcResultStack_.Pop();
  // If popping back into a global scope, pop back to the main global scope.
  SetScope(currScope_->parent().IsGlobal() ? context().globalScope()
                                           : currScope_->parent());
}
void ScopeHandler::SetScope(Scope &scope) {
  currScope_ = &scope;
  ImplicitRulesVisitor::SetScope(InclusiveScope());
}

Symbol *ScopeHandler::FindSymbol(const parser::Name &name) {
  return FindSymbol(currScope(), name);
}
Symbol *ScopeHandler::FindSymbol(const Scope &scope, const parser::Name &name) {
  if (scope.IsDerivedType()) {
    if (Symbol * symbol{scope.FindComponent(name.source)}) {
      if (symbol->has<TypeParamDetails>()) {
        return Resolve(name, symbol);
      }
    }
    return FindSymbol(scope.parent(), name);
  } else {
    // In EQUIVALENCE statements only resolve names in the local scope, see
    // 19.5.1.4, paragraph 2, item (10)
    return Resolve(name,
        inEquivalenceStmt_ ? FindInScope(scope, name)
                           : scope.FindSymbol(name.source));
  }
}

Symbol &ScopeHandler::MakeSymbol(
    Scope &scope, const SourceName &name, Attrs attrs) {
  if (Symbol * symbol{FindInScope(scope, name)}) {
    CheckDuplicatedAttrs(name, *symbol, attrs);
    SetExplicitAttrs(*symbol, attrs);
    return *symbol;
  } else {
    const auto pair{scope.try_emplace(name, attrs, UnknownDetails{})};
    CHECK(pair.second); // name was not found, so must be able to add
    return *pair.first->second;
  }
}
Symbol &ScopeHandler::MakeSymbol(const SourceName &name, Attrs attrs) {
  return MakeSymbol(currScope(), name, attrs);
}
Symbol &ScopeHandler::MakeSymbol(const parser::Name &name, Attrs attrs) {
  return Resolve(name, MakeSymbol(name.source, attrs));
}
Symbol &ScopeHandler::MakeHostAssocSymbol(
    const parser::Name &name, const Symbol &hostSymbol) {
  Symbol &symbol{*NonDerivedTypeScope()
                      .try_emplace(name.source, HostAssocDetails{hostSymbol})
                      .first->second};
  name.symbol = &symbol;
  symbol.attrs() = hostSymbol.attrs(); // TODO: except PRIVATE, PUBLIC?
  // These attributes can be redundantly reapplied without error
  // on the host-associated name, at most once (C815).
  symbol.implicitAttrs() =
      symbol.attrs() & Attrs{Attr::ASYNCHRONOUS, Attr::VOLATILE};
  // SAVE statement in the inner scope will create a new symbol.
  // If the host variable is used via host association,
  // we have to propagate whether SAVE is implicit in the host scope.
  // Otherwise, verifications that do not allow explicit SAVE
  // attribute would fail.
  symbol.implicitAttrs() |= hostSymbol.implicitAttrs() & Attrs{Attr::SAVE};
  symbol.flags() = hostSymbol.flags();
  return symbol;
}
Symbol &ScopeHandler::CopySymbol(const SourceName &name, const Symbol &symbol) {
  CHECK(!FindInScope(name));
  return MakeSymbol(currScope(), name, symbol.attrs());
}

// Look for name only in scope, not in enclosing scopes.
Symbol *ScopeHandler::FindInScope(
    const Scope &scope, const parser::Name &name) {
  return Resolve(name, FindInScope(scope, name.source));
}
Symbol *ScopeHandler::FindInScope(const Scope &scope, const SourceName &name) {
  // all variants of names, e.g. "operator(.ne.)" for "operator(/=)"
  for (const std::string &n : GetAllNames(context(), name)) {
    auto it{scope.find(SourceName{n})};
    if (it != scope.end()) {
      return &*it->second;
    }
  }
  return nullptr;
}

// Find a component or type parameter by name in a derived type or its parents.
Symbol *ScopeHandler::FindInTypeOrParents(
    const Scope &scope, const parser::Name &name) {
  return Resolve(name, scope.FindComponent(name.source));
}
Symbol *ScopeHandler::FindInTypeOrParents(const parser::Name &name) {
  return FindInTypeOrParents(currScope(), name);
}
Symbol *ScopeHandler::FindInScopeOrBlockConstructs(
    const Scope &scope, SourceName name) {
  if (Symbol * symbol{FindInScope(scope, name)}) {
    return symbol;
  }
  for (const Scope &child : scope.children()) {
    if (child.kind() == Scope::Kind::BlockConstruct) {
      if (Symbol * symbol{FindInScopeOrBlockConstructs(child, name)}) {
        return symbol;
      }
    }
  }
  return nullptr;
}

void ScopeHandler::EraseSymbol(const parser::Name &name) {
  currScope().erase(name.source);
  name.symbol = nullptr;
}

static bool NeedsType(const Symbol &symbol) {
  return !symbol.GetType() &&
      common::visit(common::visitors{
                        [](const EntityDetails &) { return true; },
                        [](const ObjectEntityDetails &) { return true; },
                        [](const AssocEntityDetails &) { return true; },
                        [&](const ProcEntityDetails &p) {
                          return symbol.test(Symbol::Flag::Function) &&
                              !symbol.attrs().test(Attr::INTRINSIC) &&
                              !p.type() && !p.procInterface();
                        },
                        [](const auto &) { return false; },
                    },
          symbol.details());
}

void ScopeHandler::ApplyImplicitRules(
    Symbol &symbol, bool allowForwardReference) {
  funcResultStack_.CompleteTypeIfFunctionResult(symbol);
  if (context().HasError(symbol) || !NeedsType(symbol)) {
    return;
  }
  if (const DeclTypeSpec * type{GetImplicitType(symbol)}) {
    symbol.set(Symbol::Flag::Implicit);
    symbol.SetType(*type);
    return;
  }
  if (symbol.has<ProcEntityDetails>() && !symbol.attrs().test(Attr::EXTERNAL)) {
    std::optional<Symbol::Flag> functionOrSubroutineFlag;
    if (symbol.test(Symbol::Flag::Function)) {
      functionOrSubroutineFlag = Symbol::Flag::Function;
    } else if (symbol.test(Symbol::Flag::Subroutine)) {
      functionOrSubroutineFlag = Symbol::Flag::Subroutine;
    }
    if (IsIntrinsic(symbol.name(), functionOrSubroutineFlag)) {
      // type will be determined in expression semantics
      AcquireIntrinsicProcedureFlags(symbol);
      return;
    }
  }
  if (allowForwardReference && ImplicitlyTypeForwardRef(symbol)) {
    return;
  }
  if (const auto *entity{symbol.detailsIf<EntityDetails>()};
      entity && entity->isDummy()) {
    // Dummy argument, no declaration or reference; if it turns
    // out to be a subroutine, it's fine, and if it is a function
    // or object, it'll be caught later.
    return;
  }
  if (deferImplicitTyping_) {
    return;
  }
  if (!context().HasError(symbol)) {
    Say(symbol.name(), "No explicit type declared for '%s'"_err_en_US);
    context().SetError(symbol);
  }
}

// Extension: Allow forward references to scalar integer dummy arguments
// or variables in COMMON to appear in specification expressions under
// IMPLICIT NONE(TYPE) when what would otherwise have been their implicit
// type is default INTEGER.
bool ScopeHandler::ImplicitlyTypeForwardRef(Symbol &symbol) {
  if (!inSpecificationPart_ || context().HasError(symbol) ||
      !(IsDummy(symbol) || FindCommonBlockContaining(symbol)) ||
      symbol.Rank() != 0 ||
      !context().languageFeatures().IsEnabled(
          common::LanguageFeature::ForwardRefImplicitNone)) {
    return false;
  }
  const DeclTypeSpec *type{
      GetImplicitType(symbol, false /*ignore IMPLICIT NONE*/)};
  if (!type || !type->IsNumeric(TypeCategory::Integer)) {
    return false;
  }
  auto kind{evaluate::ToInt64(type->numericTypeSpec().kind())};
  if (!kind || *kind != context().GetDefaultKind(TypeCategory::Integer)) {
    return false;
  }
  if (!ConvertToObjectEntity(symbol)) {
    return false;
  }
  // TODO: check no INTENT(OUT) if dummy?
  if (context().ShouldWarn(common::LanguageFeature::ForwardRefImplicitNone)) {
    Say(symbol.name(),
        "'%s' was used without (or before) being explicitly typed"_warn_en_US,
        symbol.name());
  }
  symbol.set(Symbol::Flag::Implicit);
  symbol.SetType(*type);
  return true;
}

// Ensure that the symbol for an intrinsic procedure is marked with
// the INTRINSIC attribute.  Also set PURE &/or ELEMENTAL as
// appropriate.
void ScopeHandler::AcquireIntrinsicProcedureFlags(Symbol &symbol) {
  SetImplicitAttr(symbol, Attr::INTRINSIC);
  switch (context().intrinsics().GetIntrinsicClass(symbol.name().ToString())) {
  case evaluate::IntrinsicClass::elementalFunction:
  case evaluate::IntrinsicClass::elementalSubroutine:
    SetExplicitAttr(symbol, Attr::ELEMENTAL);
    SetExplicitAttr(symbol, Attr::PURE);
    break;
  case evaluate::IntrinsicClass::impureSubroutine:
    break;
  default:
    SetExplicitAttr(symbol, Attr::PURE);
  }
}

const DeclTypeSpec *ScopeHandler::GetImplicitType(
    Symbol &symbol, bool respectImplicitNoneType) {
  const Scope *scope{&symbol.owner()};
  if (scope->IsGlobal()) {
    scope = &currScope();
  }
  scope = &GetInclusiveScope(*scope);
  const auto *type{implicitRulesMap_->at(scope).GetType(
      symbol.name(), respectImplicitNoneType)};
  if (type) {
    if (const DerivedTypeSpec * derived{type->AsDerived()}) {
      // Resolve any forward-referenced derived type; a quick no-op else.
      auto &instantiatable{*const_cast<DerivedTypeSpec *>(derived)};
      instantiatable.Instantiate(currScope());
    }
  }
  return type;
}

void ScopeHandler::CheckEntryDummyUse(SourceName source, Symbol *symbol) {
  if (!inSpecificationPart_ && symbol &&
      symbol->test(Symbol::Flag::EntryDummyArgument)) {
    Say(source,
        "Dummy argument '%s' may not be used before its ENTRY statement"_err_en_US,
        symbol->name());
    symbol->set(Symbol::Flag::EntryDummyArgument, false);
  }
}

// Convert symbol to be a ObjectEntity or return false if it can't be.
bool ScopeHandler::ConvertToObjectEntity(Symbol &symbol) {
  if (symbol.has<ObjectEntityDetails>()) {
    // nothing to do
  } else if (symbol.has<UnknownDetails>()) {
    // These are attributes that a name could have picked up from
    // an attribute statement or type declaration statement.
    if (symbol.attrs().HasAny({Attr::EXTERNAL, Attr::INTRINSIC})) {
      return false;
    }
    symbol.set_details(ObjectEntityDetails{});
  } else if (auto *details{symbol.detailsIf<EntityDetails>()}) {
    if (symbol.attrs().HasAny({Attr::EXTERNAL, Attr::INTRINSIC})) {
      return false;
    }
    funcResultStack_.CompleteTypeIfFunctionResult(symbol);
    symbol.set_details(ObjectEntityDetails{std::move(*details)});
  } else if (auto *useDetails{symbol.detailsIf<UseDetails>()}) {
    return useDetails->symbol().has<ObjectEntityDetails>();
  } else if (auto *hostDetails{symbol.detailsIf<HostAssocDetails>()}) {
    return hostDetails->symbol().has<ObjectEntityDetails>();
  } else {
    return false;
  }
  return true;
}
// Convert symbol to be a ProcEntity or return false if it can't be.
bool ScopeHandler::ConvertToProcEntity(
    Symbol &symbol, std::optional<SourceName> usedHere) {
  if (symbol.has<ProcEntityDetails>()) {
  } else if (symbol.has<UnknownDetails>()) {
    symbol.set_details(ProcEntityDetails{});
  } else if (auto *details{symbol.detailsIf<EntityDetails>()}) {
    if (IsFunctionResult(symbol) &&
        !(IsPointer(symbol) && symbol.attrs().test(Attr::EXTERNAL))) {
      // Don't turn function result into a procedure pointer unless both
      // POINTER and EXTERNAL
      return false;
    }
    funcResultStack_.CompleteTypeIfFunctionResult(symbol);
    symbol.set_details(ProcEntityDetails{std::move(*details)});
    if (symbol.GetType() && !symbol.test(Symbol::Flag::Implicit)) {
      CHECK(!symbol.test(Symbol::Flag::Subroutine));
      symbol.set(Symbol::Flag::Function);
    }
  } else if (auto *useDetails{symbol.detailsIf<UseDetails>()}) {
    return useDetails->symbol().has<ProcEntityDetails>();
  } else if (auto *hostDetails{symbol.detailsIf<HostAssocDetails>()}) {
    return hostDetails->symbol().has<ProcEntityDetails>();
  } else {
    return false;
  }
  auto &proc{symbol.get<ProcEntityDetails>()};
  if (usedHere && !proc.usedAsProcedureHere()) {
    proc.set_usedAsProcedureHere(*usedHere);
  }
  return true;
}

const DeclTypeSpec &ScopeHandler::MakeNumericType(
    TypeCategory category, const std::optional<parser::KindSelector> &kind) {
  KindExpr value{GetKindParamExpr(category, kind)};
  if (auto known{evaluate::ToInt64(value)}) {
    return MakeNumericType(category, static_cast<int>(*known));
  } else {
    return currScope_->MakeNumericType(category, std::move(value));
  }
}

const DeclTypeSpec &ScopeHandler::MakeNumericType(
    TypeCategory category, int kind) {
  return context().MakeNumericType(category, kind);
}

const DeclTypeSpec &ScopeHandler::MakeLogicalType(
    const std::optional<parser::KindSelector> &kind) {
  KindExpr value{GetKindParamExpr(TypeCategory::Logical, kind)};
  if (auto known{evaluate::ToInt64(value)}) {
    return MakeLogicalType(static_cast<int>(*known));
  } else {
    return currScope_->MakeLogicalType(std::move(value));
  }
}

const DeclTypeSpec &ScopeHandler::MakeLogicalType(int kind) {
  return context().MakeLogicalType(kind);
}

void ScopeHandler::NotePossibleBadForwardRef(const parser::Name &name) {
  if (inSpecificationPart_ && !deferImplicitTyping_ && name.symbol) {
    auto kind{currScope().kind()};
    if ((kind == Scope::Kind::Subprogram && !currScope().IsStmtFunction()) ||
        kind == Scope::Kind::BlockConstruct) {
      bool isHostAssociated{&name.symbol->owner() == &currScope()
              ? name.symbol->has<HostAssocDetails>()
              : name.symbol->owner().Contains(currScope())};
      if (isHostAssociated) {
        specPartState_.forwardRefs.insert(name.source);
      }
    }
  }
}

std::optional<SourceName> ScopeHandler::HadForwardRef(
    const Symbol &symbol) const {
  auto iter{specPartState_.forwardRefs.find(symbol.name())};
  if (iter != specPartState_.forwardRefs.end()) {
    return *iter;
  }
  return std::nullopt;
}

bool ScopeHandler::CheckPossibleBadForwardRef(const Symbol &symbol) {
  if (!context().HasError(symbol)) {
    if (auto fwdRef{HadForwardRef(symbol)}) {
      const Symbol *outer{symbol.owner().FindSymbol(symbol.name())};
      if (outer && symbol.has<UseDetails>() &&
          &symbol.GetUltimate() == &outer->GetUltimate()) {
        // e.g. IMPORT of host's USE association
        return false;
      }
      Say(*fwdRef,
          "Forward reference to '%s' is not allowed in the same specification part"_err_en_US,
          *fwdRef)
          .Attach(symbol.name(), "Later declaration of '%s'"_en_US, *fwdRef);
      context().SetError(symbol);
      return true;
    }
    if ((IsDummy(symbol) || FindCommonBlockContaining(symbol)) &&
        isImplicitNoneType() && symbol.test(Symbol::Flag::Implicit) &&
        !context().HasError(symbol)) {
      // Dummy or COMMON was implicitly typed despite IMPLICIT NONE(TYPE) in
      // ApplyImplicitRules() due to use in a specification expression,
      // and no explicit type declaration appeared later.
      Say(symbol.name(), "No explicit type declared for '%s'"_err_en_US);
      context().SetError(symbol);
      return true;
    }
  }
  return false;
}

void ScopeHandler::MakeExternal(Symbol &symbol) {
  if (!symbol.attrs().test(Attr::EXTERNAL)) {
    SetImplicitAttr(symbol, Attr::EXTERNAL);
    if (symbol.attrs().test(Attr::INTRINSIC)) { // C840
      Say(symbol.name(),
          "Symbol '%s' cannot have both EXTERNAL and INTRINSIC attributes"_err_en_US,
          symbol.name());
    }
  }
}

bool ScopeHandler::CheckDuplicatedAttr(
    SourceName name, const Symbol &symbol, Attr attr) {
  if (attr == Attr::SAVE) {
    // checked elsewhere
  } else if (symbol.attrs().test(attr)) { // C815
    if (symbol.implicitAttrs().test(attr)) {
      // Implied attribute is now confirmed explicitly
    } else {
      Say(name, "%s attribute was already specified on '%s'"_err_en_US,
          EnumToString(attr), name);
      return false;
    }
  }
  return true;
}

bool ScopeHandler::CheckDuplicatedAttrs(
    SourceName name, const Symbol &symbol, Attrs attrs) {
  bool ok{true};
  attrs.IterateOverMembers(
      [&](Attr x) { ok &= CheckDuplicatedAttr(name, symbol, x); });
  return ok;
}

void ScopeHandler::SetCUDADataAttr(SourceName source, Symbol &symbol,
    std::optional<common::CUDADataAttr> attr) {
  if (attr) {
    ConvertToObjectEntity(symbol);
    if (auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {
      if (*attr != object->cudaDataAttr().value_or(*attr)) {
        Say(source,
            "'%s' already has another CUDA data attribute ('%s')"_err_en_US,
            symbol.name(),
            std::string{common::EnumToString(*object->cudaDataAttr())}.c_str());
      } else {
        object->set_cudaDataAttr(attr);
      }
    } else {
      Say(source,
          "'%s' is not an object and may not have a CUDA data attribute"_err_en_US,
          symbol.name());
    }
  }
}

// ModuleVisitor implementation

bool ModuleVisitor::Pre(const parser::Only &x) {
  common::visit(common::visitors{
                    [&](const Indirection<parser::GenericSpec> &generic) {
                      GenericSpecInfo genericSpecInfo{generic.value()};
                      AddUseOnly(genericSpecInfo.symbolName());
                      AddUse(genericSpecInfo);
                    },
                    [&](const parser::Name &name) {
                      AddUseOnly(name.source);
                      Resolve(name, AddUse(name.source, name.source).use);
                    },
                    [&](const parser::Rename &rename) { Walk(rename); },
                },
      x.u);
  return false;
}

void ModuleVisitor::CollectUseRenames(const parser::UseStmt &useStmt) {
  auto doRename{[&](const parser::Rename &rename) {
    if (const auto *names{std::get_if<parser::Rename::Names>(&rename.u)}) {
      AddUseRename(std::get<1>(names->t).source, useStmt.moduleName.source);
    }
  }};
  common::visit(
      common::visitors{
          [&](const std::list<parser::Rename> &renames) {
            for (const auto &rename : renames) {
              doRename(rename);
            }
          },
          [&](const std::list<parser::Only> &onlys) {
            for (const auto &only : onlys) {
              if (const auto *rename{std::get_if<parser::Rename>(&only.u)}) {
                doRename(*rename);
              }
            }
          },
      },
      useStmt.u);
}

bool ModuleVisitor::Pre(const parser::Rename::Names &x) {
  const auto &localName{std::get<0>(x.t)};
  const auto &useName{std::get<1>(x.t)};
  SymbolRename rename{AddUse(localName.source, useName.source)};
  Resolve(useName, rename.use);
  Resolve(localName, rename.local);
  return false;
}
bool ModuleVisitor::Pre(const parser::Rename::Operators &x) {
  const parser::DefinedOpName &local{std::get<0>(x.t)};
  const parser::DefinedOpName &use{std::get<1>(x.t)};
  GenericSpecInfo localInfo{local};
  GenericSpecInfo useInfo{use};
  if (IsIntrinsicOperator(context(), local.v.source)) {
    Say(local.v,
        "Intrinsic operator '%s' may not be used as a defined operator"_err_en_US);
  } else if (IsLogicalConstant(context(), local.v.source)) {
    Say(local.v,
        "Logical constant '%s' may not be used as a defined operator"_err_en_US);
  } else {
    SymbolRename rename{AddUse(localInfo.symbolName(), useInfo.symbolName())};
    useInfo.Resolve(rename.use);
    localInfo.Resolve(rename.local);
  }
  return false;
}

// Set useModuleScope_ to the Scope of the module being used.
bool ModuleVisitor::Pre(const parser::UseStmt &x) {
  std::optional<bool> isIntrinsic;
  if (x.nature) {
    isIntrinsic = *x.nature == parser::UseStmt::ModuleNature::Intrinsic;
  } else if (currScope().IsModule() && currScope().symbol() &&
      currScope().symbol()->attrs().test(Attr::INTRINSIC)) {
    // Intrinsic modules USE only other intrinsic modules
    isIntrinsic = true;
  }
  useModuleScope_ = FindModule(x.moduleName, isIntrinsic);
  if (!useModuleScope_) {
    return false;
  }
  AddAndCheckModuleUse(x.moduleName.source,
      useModuleScope_->parent().kind() == Scope::Kind::IntrinsicModules);
  // use the name from this source file
  useModuleScope_->symbol()->ReplaceName(x.moduleName.source);
  return true;
}

void ModuleVisitor::Post(const parser::UseStmt &x) {
  if (const auto *list{std::get_if<std::list<parser::Rename>>(&x.u)}) {
    // Not a use-only: collect the names that were used in renames,
    // then add a use for each public name that was not renamed.
    std::set<SourceName> useNames;
    for (const auto &rename : *list) {
      common::visit(common::visitors{
                        [&](const parser::Rename::Names &names) {
                          useNames.insert(std::get<1>(names.t).source);
                        },
                        [&](const parser::Rename::Operators &ops) {
                          useNames.insert(std::get<1>(ops.t).v.source);
                        },
                    },
          rename.u);
    }
    for (const auto &[name, symbol] : *useModuleScope_) {
      if (symbol->attrs().test(Attr::PUBLIC) && !IsUseRenamed(symbol->name()) &&
          (!symbol->implicitAttrs().test(Attr::INTRINSIC) ||
              symbol->has<UseDetails>()) &&
          !symbol->has<MiscDetails>() && useNames.count(name) == 0) {
        SourceName location{x.moduleName.source};
        if (auto *localSymbol{FindInScope(name)}) {
          DoAddUse(location, localSymbol->name(), *localSymbol, *symbol);
        } else {
          DoAddUse(location, location, CopySymbol(name, *symbol), *symbol);
        }
      }
    }
  }
  useModuleScope_ = nullptr;
}

ModuleVisitor::SymbolRename ModuleVisitor::AddUse(
    const SourceName &localName, const SourceName &useName) {
  return AddUse(localName, useName, FindInScope(*useModuleScope_, useName));
}

ModuleVisitor::SymbolRename ModuleVisitor::AddUse(
    const SourceName &localName, const SourceName &useName, Symbol *useSymbol) {
  if (!useModuleScope_) {
    return {}; // error occurred finding module
  }
  if (!useSymbol) {
    Say(useName, "'%s' not found in module '%s'"_err_en_US, MakeOpName(useName),
        useModuleScope_->GetName().value());
    return {};
  }
  if (useSymbol->attrs().test(Attr::PRIVATE) &&
      !FindModuleFileContaining(currScope())) {
    // Privacy is not enforced in module files so that generic interfaces
    // can be resolved to private specific procedures in specification
    // expressions.
    Say(useName, "'%s' is PRIVATE in '%s'"_err_en_US, MakeOpName(useName),
        useModuleScope_->GetName().value());
    return {};
  }
  auto &localSymbol{MakeSymbol(localName)};
  DoAddUse(useName, localName, localSymbol, *useSymbol);
  return {&localSymbol, useSymbol};
}

// symbol must be either a Use or a Generic formed by merging two uses.
// Convert it to a UseError with this additional location.
static bool ConvertToUseError(
    Symbol &symbol, const SourceName &location, const Scope &module) {
  const auto *useDetails{symbol.detailsIf<UseDetails>()};
  if (!useDetails) {
    if (auto *genericDetails{symbol.detailsIf<GenericDetails>()}) {
      if (!genericDetails->uses().empty()) {
        useDetails = &genericDetails->uses().at(0)->get<UseDetails>();
      }
    }
  }
  if (useDetails) {
    symbol.set_details(
        UseErrorDetails{*useDetails}.add_occurrence(location, module));
    return true;
  } else {
    return false;
  }
}

void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
    Symbol &originalLocal, const Symbol &useSymbol) {
  Symbol *localSymbol{&originalLocal};
  if (auto *details{localSymbol->detailsIf<UseErrorDetails>()}) {
    details->add_occurrence(location, *useModuleScope_);
    return;
  }
  const Symbol &useUltimate{useSymbol.GetUltimate()};
  if (localSymbol->has<UnknownDetails>()) {
    localSymbol->set_details(UseDetails{localName, useSymbol});
    localSymbol->attrs() =
        useSymbol.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE, Attr::SAVE};
    localSymbol->implicitAttrs() =
        localSymbol->attrs() & Attrs{Attr::ASYNCHRONOUS, Attr::VOLATILE};
    localSymbol->flags() = useSymbol.flags();
    return;
  }

  Symbol &localUltimate{localSymbol->GetUltimate()};
  if (&localUltimate == &useUltimate) {
    // use-associating the same symbol again -- ok
    return;
  }

  // There are many possible combinations of symbol types that could arrive
  // with the same (local) name vie USE association from distinct modules.
  // Fortran allows a generic interface to share its name with a derived type,
  // or with the name of a non-generic procedure (which should be one of the
  // generic's specific procedures).  Implementing all these possibilities is
  // complicated.
  // Error cases are converted into UseErrorDetails symbols to trigger error
  // messages when/if bad combinations are actually used later in the program.
  // The error cases are:
  //   - two distinct derived types
  //   - two distinct non-generic procedures
  //   - a generic and a non-generic that is not already one of its specifics
  //   - anything other than a derived type, non-generic procedure, or
  //     generic procedure being combined with something other than an
  //     prior USE association of itself

  auto *localGeneric{localUltimate.detailsIf<GenericDetails>()};
  const auto *useGeneric{useUltimate.detailsIf<GenericDetails>()};

  Symbol *localDerivedType{nullptr};
  if (localUltimate.has<DerivedTypeDetails>()) {
    localDerivedType = &localUltimate;
  } else if (localGeneric) {
    if (auto *dt{localGeneric->derivedType()};
        dt && !dt->attrs().test(Attr::PRIVATE)) {
      localDerivedType = dt;
    }
  }
  const Symbol *useDerivedType{nullptr};
  if (useUltimate.has<DerivedTypeDetails>()) {
    useDerivedType = &useUltimate;
  } else if (useGeneric) {
    if (const auto *dt{useGeneric->derivedType()};
        dt && !dt->attrs().test(Attr::PRIVATE)) {
      useDerivedType = dt;
    }
  }

  Symbol *localProcedure{nullptr};
  if (localGeneric) {
    if (localGeneric->specific() &&
        !localGeneric->specific()->attrs().test(Attr::PRIVATE)) {
      localProcedure = localGeneric->specific();
    }
  } else if (IsProcedure(localUltimate)) {
    localProcedure = &localUltimate;
  }
  const Symbol *useProcedure{nullptr};
  if (useGeneric) {
    if (useGeneric->specific() &&
        !useGeneric->specific()->attrs().test(Attr::PRIVATE)) {
      useProcedure = useGeneric->specific();
    }
  } else if (IsProcedure(useUltimate)) {
    useProcedure = &useUltimate;
  }

  // Creates a UseErrorDetails symbol in the current scope for a
  // current UseDetails symbol, but leaves the UseDetails in the
  // scope's name map.
  auto CreateLocalUseError{[&]() {
    EraseSymbol(*localSymbol);
    UseErrorDetails details{localSymbol->get<UseDetails>()};
    details.add_occurrence(location, *useModuleScope_);
    Symbol *newSymbol{&MakeSymbol(localName, Attrs{}, std::move(details))};
    // Restore *localSymbol in currScope
    auto iter{currScope().find(localName)};
    CHECK(iter != currScope().end() && &*iter->second == newSymbol);
    iter->second = MutableSymbolRef{*localSymbol};
    return newSymbol;
  }};

  // When two derived types arrived, try to combine them.
  const Symbol *combinedDerivedType{nullptr};
  if (!useDerivedType) {
    combinedDerivedType = localDerivedType;
  } else if (!localDerivedType) {
    combinedDerivedType = useDerivedType;
  } else {
    const Scope *localScope{localDerivedType->scope()};
    const Scope *useScope{useDerivedType->scope()};
    if (localScope && useScope && localScope->derivedTypeSpec() &&
        useScope->derivedTypeSpec() &&
        evaluate::AreSameDerivedType(
            *localScope->derivedTypeSpec(), *useScope->derivedTypeSpec())) {
      combinedDerivedType = localDerivedType;
    } else {
      // Create a local UseErrorDetails for the ambiguous derived type
      if (localGeneric) {
        combinedDerivedType = CreateLocalUseError();
      } else {
        ConvertToUseError(*localSymbol, location, *useModuleScope_);
        combinedDerivedType = localSymbol;
      }
    }
    if (!localGeneric && !useGeneric) {
      return; // both symbols are derived types; done
    }
  }

  auto AreSameProcedure{[&](const Symbol &p1, const Symbol &p2) {
    if (&p1 == &p2) {
      return true;
    } else if (p1.name() != p2.name()) {
      return false;
    } else if (p1.attrs().test(Attr::INTRINSIC) ||
        p2.attrs().test(Attr::INTRINSIC)) {
      return p1.attrs().test(Attr::INTRINSIC) &&
          p2.attrs().test(Attr::INTRINSIC);
    } else if (!IsProcedure(p1) || !IsProcedure(p2)) {
      return false;
    } else if (IsPointer(p1) || IsPointer(p2)) {
      return false;
    } else if (const auto *subp{p1.detailsIf<SubprogramDetails>()};
               subp && !subp->isInterface()) {
      return false; // defined in module, not an external
    } else if (const auto *subp{p2.detailsIf<SubprogramDetails>()};
               subp && !subp->isInterface()) {
      return false; // defined in module, not an external
    } else {
      // Both are external interfaces, perhaps to the same procedure
      auto class1{ClassifyProcedure(p1)};
      auto class2{ClassifyProcedure(p2)};
      if (class1 == ProcedureDefinitionClass::External &&
          class2 == ProcedureDefinitionClass::External) {
        auto chars1{evaluate::characteristics::Procedure::Characterize(
            p1, GetFoldingContext())};
        auto chars2{evaluate::characteristics::Procedure::Characterize(
            p2, GetFoldingContext())};
        // same procedure interface defined identically in two modules?
        return chars1 && chars2 && *chars1 == *chars2;
      } else {
        return false;
      }
    }
  }};

  // When two non-generic procedures arrived, try to combine them.
  const Symbol *combinedProcedure{nullptr};
  if (!localProcedure) {
    combinedProcedure = useProcedure;
  } else if (!useProcedure) {
    combinedProcedure = localProcedure;
  } else {
    if (AreSameProcedure(
            localProcedure->GetUltimate(), useProcedure->GetUltimate())) {
      if (!localGeneric && !useGeneric) {
        return; // both symbols are non-generic procedures
      }
      combinedProcedure = localProcedure;
    }
  }

  // Prepare to merge generics
  bool cantCombine{false};
  if (localGeneric) {
    if (useGeneric || useDerivedType) {
    } else if (&useUltimate == &BypassGeneric(localUltimate).GetUltimate()) {
      return; // nothing to do; used subprogram is local's specific
    } else if (useUltimate.attrs().test(Attr::INTRINSIC) &&
        useUltimate.name() == localSymbol->name()) {
      return; // local generic can extend intrinsic
    } else {
      for (const auto &ref : localGeneric->specificProcs()) {
        if (&ref->GetUltimate() == &useUltimate) {
          return; // used non-generic is already a specific of local generic
        }
      }
      cantCombine = true;
    }
  } else if (useGeneric) {
    if (localDerivedType) {
    } else if (&localUltimate == &BypassGeneric(useUltimate).GetUltimate() ||
        (localSymbol->attrs().test(Attr::INTRINSIC) &&
            localUltimate.name() == useUltimate.name())) {
      // Local is the specific of the used generic or an intrinsic with the
      // same name; replace it.
      EraseSymbol(*localSymbol);
      Symbol &newSymbol{MakeSymbol(localName,
          useUltimate.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE},
          UseDetails{localName, useUltimate})};
      newSymbol.flags() = useSymbol.flags();
      return;
    } else {
      for (const auto &ref : useGeneric->specificProcs()) {
        if (&ref->GetUltimate() == &localUltimate) {
          return; // local non-generic is already a specific of used generic
        }
      }
      cantCombine = true;
    }
  } else {
    cantCombine = true;
  }

  // If symbols are not combinable, create a use error.
  if (cantCombine) {
    if (!ConvertToUseError(*localSymbol, location, *useModuleScope_)) {
      Say(location,
          "Cannot use-associate '%s'; it is already declared in this scope"_err_en_US,
          localName)
          .Attach(localSymbol->name(), "Previous declaration of '%s'"_en_US,
              localName);
    }
    return;
  }

  // At this point, there must be at least one generic interface.
  CHECK(localGeneric || (useGeneric && (localDerivedType || localProcedure)));

  if (localGeneric) {
    // Create a local copy of a previously use-associated generic so that
    // it can be locally extended without corrupting the original.
    if (localSymbol->has<UseDetails>()) {
      GenericDetails generic;
      generic.CopyFrom(DEREF(localGeneric));
      EraseSymbol(*localSymbol);
      Symbol &newSymbol{MakeSymbol(
          localSymbol->name(), localSymbol->attrs(), std::move(generic))};
      newSymbol.flags() = localSymbol->flags();
      localGeneric = &newSymbol.get<GenericDetails>();
      localGeneric->AddUse(*localSymbol);
      localSymbol = &newSymbol;
    }
    if (useGeneric) {
      // Combine two use-associated generics
      localSymbol->attrs() =
          useSymbol.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE};
      localSymbol->flags() = useSymbol.flags();
      AddGenericUse(*localGeneric, localName, useUltimate);
      localGeneric->clear_derivedType();
      localGeneric->CopyFrom(*useGeneric);
    }
    localGeneric->clear_derivedType();
    if (combinedDerivedType) {
      localGeneric->set_derivedType(*const_cast<Symbol *>(combinedDerivedType));
    }
    localGeneric->clear_specific();
    if (combinedProcedure) {
      localGeneric->set_specific(*const_cast<Symbol *>(combinedProcedure));
    }
  } else {
    CHECK(localSymbol->has<UseDetails>());
    // Create a local copy of the use-associated generic, then extend it
    // with the combined derived type &/or non-generic procedure.
    GenericDetails generic;
    generic.CopyFrom(*useGeneric);
    EraseSymbol(*localSymbol);
    Symbol &newSymbol{MakeSymbol(localName,
        useUltimate.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE},
        std::move(generic))};
    newSymbol.flags() = useUltimate.flags();
    auto &newUseGeneric{newSymbol.get<GenericDetails>()};
    AddGenericUse(newUseGeneric, localName, useUltimate);
    newUseGeneric.AddUse(*localSymbol);
    if (combinedDerivedType) {
      newUseGeneric.set_derivedType(*const_cast<Symbol *>(combinedDerivedType));
    }
    if (combinedProcedure) {
      newUseGeneric.set_specific(*const_cast<Symbol *>(combinedProcedure));
    }
  }
}

void ModuleVisitor::AddUse(const GenericSpecInfo &info) {
  if (useModuleScope_) {
    const auto &name{info.symbolName()};
    auto rename{AddUse(name, name, FindInScope(*useModuleScope_, name))};
    info.Resolve(rename.use);
  }
}

// Create a UseDetails symbol for this USE and add it to generic
Symbol &ModuleVisitor::AddGenericUse(
    GenericDetails &generic, const SourceName &name, const Symbol &useSymbol) {
  Symbol &newSymbol{
      currScope().MakeSymbol(name, {}, UseDetails{name, useSymbol})};
  generic.AddUse(newSymbol);
  return newSymbol;
}

// Enforce F'2023 C1406 as a warning
void ModuleVisitor::AddAndCheckModuleUse(SourceName name, bool isIntrinsic) {
  if (isIntrinsic) {
    if (auto iter{nonIntrinsicUses_.find(name)};
        iter != nonIntrinsicUses_.end()) {
      if (context().ShouldWarn(common::LanguageFeature::MiscUseExtensions)) {
        Say(name,
            "Should not USE the intrinsic module '%s' in the same scope as a USE of the non-intrinsic module"_port_en_US,
            name)
            .Attach(*iter, "Previous USE of '%s'"_en_US, *iter);
      }
    }
    intrinsicUses_.insert(name);
  } else {
    if (auto iter{intrinsicUses_.find(name)}; iter != intrinsicUses_.end()) {
      if (context().ShouldWarn(common::LanguageFeature::MiscUseExtensions)) {
        Say(name,
            "Should not USE the non-intrinsic module '%s' in the same scope as a USE of the intrinsic module"_port_en_US,
            name)
            .Attach(*iter, "Previous USE of '%s'"_en_US, *iter);
      }
    }
    nonIntrinsicUses_.insert(name);
  }
}

bool ModuleVisitor::BeginSubmodule(
    const parser::Name &name, const parser::ParentIdentifier &parentId) {
  const auto &ancestorName{std::get<parser::Name>(parentId.t)};
  Scope *parentScope{nullptr};
  Scope *ancestor{FindModule(ancestorName, false /*not intrinsic*/)};
  if (ancestor) {
    if (const auto &parentName{
            std::get<std::optional<parser::Name>>(parentId.t)}) {
      parentScope = FindModule(*parentName, false /*not intrinsic*/, ancestor);
    } else {
      parentScope = ancestor;
    }
  }
  if (parentScope) {
    PushScope(*parentScope);
  } else {
    // Error recovery: there's no ancestor scope, so create a dummy one to
    // hold the submodule's scope.
    SourceName dummyName{context().GetTempName(currScope())};
    Symbol &dummySymbol{MakeSymbol(dummyName, Attrs{}, ModuleDetails{false})};
    PushScope(Scope::Kind::Module, &dummySymbol);
    parentScope = &currScope();
  }
  BeginModule(name, true);
  if (ancestor && !ancestor->AddSubmodule(name.source, currScope())) {
    Say(name, "Module '%s' already has a submodule named '%s'"_err_en_US,
        ancestorName.source, name.source);
  }
  return true;
}

void ModuleVisitor::BeginModule(const parser::Name &name, bool isSubmodule) {
  // Submodule symbols are not visible in their parents' scopes.
  Symbol &symbol{isSubmodule ? Resolve(name,
                                   currScope().MakeSymbol(name.source, Attrs{},
                                       ModuleDetails{true}))
                             : MakeSymbol(name, ModuleDetails{false})};
  auto &details{symbol.get<ModuleDetails>()};
  PushScope(Scope::Kind::Module, &symbol);
  details.set_scope(&currScope());
  prevAccessStmt_ = std::nullopt;
}

// Find a module or submodule by name and return its scope.
// If ancestor is present, look for a submodule of that ancestor module.
// May have to read a .mod file to find it.
// If an error occurs, report it and return nullptr.
Scope *ModuleVisitor::FindModule(const parser::Name &name,
    std::optional<bool> isIntrinsic, Scope *ancestor) {
  ModFileReader reader{context()};
  Scope *scope{
      reader.Read(name.source, isIntrinsic, ancestor, /*silent=*/false)};
  if (!scope) {
    return nullptr;
  }
  if (DoesScopeContain(scope, currScope())) { // 14.2.2(1)
    Say(name, "Module '%s' cannot USE itself"_err_en_US);
  }
  Resolve(name, scope->symbol());
  return scope;
}

void ModuleVisitor::ApplyDefaultAccess() {
  const auto *moduleDetails{
      DEREF(currScope().symbol()).detailsIf<ModuleDetails>()};
  CHECK(moduleDetails);
  Attr defaultAttr{
      DEREF(moduleDetails).isDefaultPrivate() ? Attr::PRIVATE : Attr::PUBLIC};
  for (auto &pair : currScope()) {
    Symbol &symbol{*pair.second};
    if (!symbol.attrs().HasAny({Attr::PUBLIC, Attr::PRIVATE})) {
      Attr attr{defaultAttr};
      if (auto *generic{symbol.detailsIf<GenericDetails>()}) {
        if (generic->derivedType()) {
          // If a generic interface has a derived type of the same
          // name that has an explicit accessibility attribute, then
          // the generic must have the same accessibility.
          if (generic->derivedType()->attrs().test(Attr::PUBLIC)) {
            attr = Attr::PUBLIC;
          } else if (generic->derivedType()->attrs().test(Attr::PRIVATE)) {
            attr = Attr::PRIVATE;
          }
        }
      }
      SetImplicitAttr(symbol, attr);
    }
  }
}

// InterfaceVistor implementation

bool InterfaceVisitor::Pre(const parser::InterfaceStmt &x) {
  bool isAbstract{std::holds_alternative<parser::Abstract>(x.u)};
  genericInfo_.emplace(/*isInterface*/ true, isAbstract);
  return BeginAttrs();
}

void InterfaceVisitor::Post(const parser::InterfaceStmt &) { EndAttrs(); }

void InterfaceVisitor::Post(const parser::EndInterfaceStmt &) {
  ResolveNewSpecifics();
  genericInfo_.pop();
}

// Create a symbol in genericSymbol_ for this GenericSpec.
bool InterfaceVisitor::Pre(const parser::GenericSpec &x) {
  if (auto *symbol{FindInScope(GenericSpecInfo{x}.symbolName())}) {
    SetGenericSymbol(*symbol);
  }
  return false;
}

bool InterfaceVisitor::Pre(const parser::ProcedureStmt &x) {
  if (!isGeneric()) {
    Say("A PROCEDURE statement is only allowed in a generic interface block"_err_en_US);
  } else {
    auto kind{std::get<parser::ProcedureStmt::Kind>(x.t)};
    const auto &names{std::get<std::list<parser::Name>>(x.t)};
    AddSpecificProcs(names, kind);
  }
  return false;
}

bool InterfaceVisitor::Pre(const parser::GenericStmt &) {
  genericInfo_.emplace(/*isInterface*/ false);
  return BeginAttrs();
}
void InterfaceVisitor::Post(const parser::GenericStmt &x) {
  auto attrs{EndAttrs()};
  if (Symbol * symbol{GetGenericInfo().symbol}) {
    SetExplicitAttrs(*symbol, attrs);
  }
  const auto &names{std::get<std::list<parser::Name>>(x.t)};
  AddSpecificProcs(names, ProcedureKind::Procedure);
  ResolveNewSpecifics();
  genericInfo_.pop();
}

bool InterfaceVisitor::inInterfaceBlock() const {
  return !genericInfo_.empty() && GetGenericInfo().isInterface;
}
bool InterfaceVisitor::isGeneric() const {
  return !genericInfo_.empty() && GetGenericInfo().symbol;
}
bool InterfaceVisitor::isAbstract() const {
  return !genericInfo_.empty() && GetGenericInfo().isAbstract;
}

void InterfaceVisitor::AddSpecificProcs(
    const std::list<parser::Name> &names, ProcedureKind kind) {
  if (Symbol * symbol{GetGenericInfo().symbol};
      symbol && symbol->has<GenericDetails>()) {
    for (const auto &name : names) {
      specificsForGenericProcs_.emplace(symbol, std::make_pair(&name, kind));
      genericsForSpecificProcs_.emplace(name.source, symbol);
    }
  }
}

// By now we should have seen all specific procedures referenced by name in
// this generic interface. Resolve those names to symbols.
void GenericHandler::ResolveSpecificsInGeneric(
    Symbol &generic, bool isEndOfSpecificationPart) {
  auto &details{generic.get<GenericDetails>()};
  UnorderedSymbolSet symbolsSeen;
  for (const Symbol &symbol : details.specificProcs()) {
    symbolsSeen.insert(symbol.GetUltimate());
  }
  auto range{specificsForGenericProcs_.equal_range(&generic)};
  SpecificProcMapType retain;
  for (auto it{range.first}; it != range.second; ++it) {
    const parser::Name *name{it->second.first};
    auto kind{it->second.second};
    const Symbol *symbol{isEndOfSpecificationPart
            ? FindSymbol(*name)
            : FindInScope(generic.owner(), *name)};
    ProcedureDefinitionClass defClass{ProcedureDefinitionClass::None};
    const Symbol *specific{symbol};
    const Symbol *ultimate{nullptr};
    if (symbol) {
      // Subtlety: when *symbol is a use- or host-association, the specific
      // procedure that is recorded in the GenericDetails below must be *symbol,
      // not the specific procedure shadowed by a generic, because that specific
      // procedure may be a symbol from another module and its name unavailable
      // to emit to a module file.
      const Symbol &bypassed{BypassGeneric(*symbol)};
      if (symbol == &symbol->GetUltimate()) {
        specific = &bypassed;
      }
      ultimate = &bypassed.GetUltimate();
      defClass = ClassifyProcedure(*ultimate);
    }
    std::optional<MessageFixedText> error;
    if (defClass == ProcedureDefinitionClass::Module) {
      // ok
    } else if (kind == ProcedureKind::ModuleProcedure) {
      error = "'%s' is not a module procedure"_err_en_US;
    } else {
      switch (defClass) {
      case ProcedureDefinitionClass::Intrinsic:
      case ProcedureDefinitionClass::External:
      case ProcedureDefinitionClass::Internal:
      case ProcedureDefinitionClass::Dummy:
      case ProcedureDefinitionClass::Pointer:
        break;
      case ProcedureDefinitionClass::None:
        error = "'%s' is not a procedure"_err_en_US;
        break;
      default:
        error =
            "'%s' is not a procedure that can appear in a generic interface"_err_en_US;
        break;
      }
    }
    if (error) {
      if (isEndOfSpecificationPart) {
        Say(*name, std::move(*error));
      } else {
        // possible forward reference, catch it later
        retain.emplace(&generic, std::make_pair(name, kind));
      }
    } else if (!ultimate) {
    } else if (symbolsSeen.insert(*ultimate).second /*true if added*/) {
      // When a specific procedure is a USE association, that association
      // is saved in the generic's specifics, not its ultimate symbol,
      // so that module file output of interfaces can distinguish them.
      details.AddSpecificProc(*specific, name->source);
    } else if (specific == ultimate) {
      Say(name->source,
          "Procedure '%s' is already specified in generic '%s'"_err_en_US,
          name->source, MakeOpName(generic.name()));
    } else {
      Say(name->source,
          "Procedure '%s' from module '%s' is already specified in generic '%s'"_err_en_US,
          ultimate->name(), ultimate->owner().GetName().value(),
          MakeOpName(generic.name()));
    }
  }
  specificsForGenericProcs_.erase(range.first, range.second);
  specificsForGenericProcs_.merge(std::move(retain));
}

void GenericHandler::DeclaredPossibleSpecificProc(Symbol &proc) {
  auto range{genericsForSpecificProcs_.equal_range(proc.name())};
  for (auto iter{range.first}; iter != range.second; ++iter) {
    ResolveSpecificsInGeneric(*iter->second, false);
  }
}

void InterfaceVisitor::ResolveNewSpecifics() {
  if (Symbol * generic{genericInfo_.top().symbol};
      generic && generic->has<GenericDetails>()) {
    ResolveSpecificsInGeneric(*generic, false);
  }
}

// Mixed interfaces are allowed by the standard.
// If there is a derived type with the same name, they must all be functions.
void InterfaceVisitor::CheckGenericProcedures(Symbol &generic) {
  ResolveSpecificsInGeneric(generic, true);
  auto &details{generic.get<GenericDetails>()};
  if (auto *proc{details.CheckSpecific()}) {
    Say(proc->name().begin() > generic.name().begin() ? proc->name()
                                                      : generic.name(),
        "'%s' should not be the name of both a generic interface and a procedure unless it is a specific procedure of the generic"_warn_en_US);
  }
  auto &specifics{details.specificProcs()};
  if (specifics.empty()) {
    if (details.derivedType()) {
      generic.set(Symbol::Flag::Function);
    }
    return;
  }
  const Symbol &firstSpecific{specifics.front()};
  bool isFunction{firstSpecific.test(Symbol::Flag::Function)};
  bool isBoth{false};
  for (const Symbol &specific : specifics) {
    if (isFunction != specific.test(Symbol::Flag::Function)) { // C1514
      auto &msg{Say(generic.name(),
          "Generic interface '%s' has both a function and a subroutine"_warn_en_US)};
      if (isFunction) {
        msg.Attach(firstSpecific.name(), "Function declaration"_en_US);
        msg.Attach(specific.name(), "Subroutine declaration"_en_US);
      } else {
        msg.Attach(firstSpecific.name(), "Subroutine declaration"_en_US);
        msg.Attach(specific.name(), "Function declaration"_en_US);
      }
      isFunction = false;
      isBoth = true;
      break;
    }
  }
  if (!isFunction && details.derivedType()) {
    SayDerivedType(generic.name(),
        "Generic interface '%s' may only contain functions due to derived type"
        " with same name"_err_en_US,
        *details.derivedType()->GetUltimate().scope());
  }
  if (!isBoth) {
    generic.set(isFunction ? Symbol::Flag::Function : Symbol::Flag::Subroutine);
  }
}

// SubprogramVisitor implementation

// Return false if it is actually an assignment statement.
bool SubprogramVisitor::HandleStmtFunction(const parser::StmtFunctionStmt &x) {
  const auto &name{std::get<parser::Name>(x.t)};
  const DeclTypeSpec *resultType{nullptr};
  // Look up name: provides return type or tells us if it's an array
  if (auto *symbol{FindSymbol(name)}) {
    Symbol &ultimate{symbol->GetUltimate()};
    if (ultimate.has<ObjectEntityDetails>() ||
        ultimate.has<AssocEntityDetails>() ||
        CouldBeDataPointerValuedFunction(&ultimate) ||
        (&symbol->owner() == &currScope() && IsFunctionResult(*symbol))) {
      misparsedStmtFuncFound_ = true;
      return false;
    }
    if (IsHostAssociated(*symbol, currScope())) {
      if (context().ShouldWarn(
              common::LanguageFeature::StatementFunctionExtensions)) {
        Say(name,
            "Name '%s' from host scope should have a type declaration before its local statement function definition"_port_en_US);
      }
      MakeSymbol(name, Attrs{}, UnknownDetails{});
    } else if (auto *entity{ultimate.detailsIf<EntityDetails>()};
               entity && !ultimate.has<ProcEntityDetails>()) {
      resultType = entity->type();
      ultimate.details() = UnknownDetails{}; // will be replaced below
    } else {
      misparsedStmtFuncFound_ = true;
    }
  }
  if (misparsedStmtFuncFound_) {
    Say(name,
        "'%s' has not been declared as an array or pointer-valued function"_err_en_US);
    return false;
  }
  auto &symbol{PushSubprogramScope(name, Symbol::Flag::Function)};
  symbol.set(Symbol::Flag::StmtFunction);
  EraseSymbol(symbol); // removes symbol added by PushSubprogramScope
  auto &details{symbol.get<SubprogramDetails>()};
  for (const auto &dummyName : std::get<std::list<parser::Name>>(x.t)) {
    ObjectEntityDetails dummyDetails{true};
    if (auto *dummySymbol{FindInScope(currScope().parent(), dummyName)}) {
      if (auto *d{dummySymbol->detailsIf<EntityDetails>()}) {
        if (d->type()) {
          dummyDetails.set_type(*d->type());
        }
      }
    }
    Symbol &dummy{MakeSymbol(dummyName, std::move(dummyDetails))};
    ApplyImplicitRules(dummy);
    details.add_dummyArg(dummy);
  }
  ObjectEntityDetails resultDetails;
  if (resultType) {
    resultDetails.set_type(*resultType);
  }
  resultDetails.set_funcResult(true);
  Symbol &result{MakeSymbol(name, std::move(resultDetails))};
  result.flags().set(Symbol::Flag::StmtFunction);
  ApplyImplicitRules(result);
  details.set_result(result);
  // The analysis of the expression that constitutes the body of the
  // statement function is deferred to FinishSpecificationPart() so that
  // all declarations and implicit typing are complete.
  PopScope();
  return true;
}

bool SubprogramVisitor::Pre(const parser::Suffix &suffix) {
  if (suffix.resultName) {
    if (IsFunction(currScope())) {
      if (FuncResultStack::FuncInfo * info{funcResultStack().Top()}) {
        if (info->inFunctionStmt) {
          info->resultName = &suffix.resultName.value();
        } else {
          // will check the result name in Post(EntryStmt)
        }
      }
    } else {
      Message &msg{Say(*suffix.resultName,
          "RESULT(%s) may appear only in a function"_err_en_US)};
      if (const Symbol * subprogram{InclusiveScope().symbol()}) {
        msg.Attach(subprogram->name(), "Containing subprogram"_en_US);
      }
    }
  }
  // LanguageBindingSpec deferred to Post(EntryStmt) or, for FunctionStmt,
  // all the way to EndSubprogram().
  return false;
}

bool SubprogramVisitor::Pre(const parser::PrefixSpec &x) {
  // Save this to process after UseStmt and ImplicitPart
  if (const auto *parsedType{std::get_if<parser::DeclarationTypeSpec>(&x.u)}) {
    if (FuncResultStack::FuncInfo * info{funcResultStack().Top()}) {
      if (info->parsedType) { // C1543
        Say(currStmtSource().value(),
            "FUNCTION prefix cannot specify the type more than once"_err_en_US);
      } else {
        info->parsedType = parsedType;
        info->source = currStmtSource();
      }
    } else {
      Say(currStmtSource().value(),
          "SUBROUTINE prefix cannot specify a type"_err_en_US);
    }
    return false;
  } else {
    return true;
  }
}

bool SubprogramVisitor::Pre(const parser::PrefixSpec::Attributes &attrs) {
  if (auto *subp{currScope().symbol()
              ? currScope().symbol()->detailsIf<SubprogramDetails>()
              : nullptr}) {
    for (auto attr : attrs.v) {
      if (auto current{subp->cudaSubprogramAttrs()}) {
        if (attr == *current ||
            (*current == common::CUDASubprogramAttrs::HostDevice &&
                (attr == common::CUDASubprogramAttrs::Host ||
                    attr == common::CUDASubprogramAttrs::Device))) {
          Say(currStmtSource().value(),
              "ATTRIBUTES(%s) appears more than once"_warn_en_US,
              common::EnumToString(attr));
        } else if ((attr == common::CUDASubprogramAttrs::Host ||
                       attr == common::CUDASubprogramAttrs::Device) &&
            (*current == common::CUDASubprogramAttrs::Host ||
                *current == common::CUDASubprogramAttrs::Device ||
                *current == common::CUDASubprogramAttrs::HostDevice)) {
          // HOST,DEVICE or DEVICE,HOST -> HostDevice
          subp->set_cudaSubprogramAttrs(
              common::CUDASubprogramAttrs::HostDevice);
        } else {
          Say(currStmtSource().value(),
              "ATTRIBUTES(%s) conflicts with earlier ATTRIBUTES(%s)"_err_en_US,
              common::EnumToString(attr), common::EnumToString(*current));
        }
      } else {
        subp->set_cudaSubprogramAttrs(attr);
      }
    }
  }
  return false;
}

void SubprogramVisitor::Post(const parser::PrefixSpec::Launch_Bounds &x) {
  std::vector<std::int64_t> bounds;
  bool ok{true};
  for (const auto &sicx : x.v) {
    if (auto value{evaluate::ToInt64(EvaluateExpr(sicx))}) {
      bounds.push_back(*value);
    } else {
      ok = false;
    }
  }
  if (!ok || bounds.size() < 2 || bounds.size() > 3) {
    Say(currStmtSource().value(),
        "Operands of LAUNCH_BOUNDS() must be 2 or 3 integer constants"_err_en_US);
  } else if (auto *subp{currScope().symbol()
                     ? currScope().symbol()->detailsIf<SubprogramDetails>()
                     : nullptr}) {
    if (subp->cudaLaunchBounds().empty()) {
      subp->set_cudaLaunchBounds(std::move(bounds));
    } else {
      Say(currStmtSource().value(),
          "LAUNCH_BOUNDS() may only appear once"_err_en_US);
    }
  }
}

void SubprogramVisitor::Post(const parser::PrefixSpec::Cluster_Dims &x) {
  std::vector<std::int64_t> dims;
  bool ok{true};
  for (const auto &sicx : x.v) {
    if (auto value{evaluate::ToInt64(EvaluateExpr(sicx))}) {
      dims.push_back(*value);
    } else {
      ok = false;
    }
  }
  if (!ok || dims.size() != 3) {
    Say(currStmtSource().value(),
        "Operands of CLUSTER_DIMS() must be three integer constants"_err_en_US);
  } else if (auto *subp{currScope().symbol()
                     ? currScope().symbol()->detailsIf<SubprogramDetails>()
                     : nullptr}) {
    if (subp->cudaClusterDims().empty()) {
      subp->set_cudaClusterDims(std::move(dims));
    } else {
      Say(currStmtSource().value(),
          "CLUSTER_DIMS() may only appear once"_err_en_US);
    }
  }
}

static bool HasModulePrefix(const std::list<parser::PrefixSpec> &prefixes) {
  for (const auto &prefix : prefixes) {
    if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) {
      return true;
    }
  }
  return false;
}

bool SubprogramVisitor::Pre(const parser::InterfaceBody::Subroutine &x) {
  const auto &stmtTuple{
      std::get<parser::Statement<parser::SubroutineStmt>>(x.t).statement.t};
  return BeginSubprogram(std::get<parser::Name>(stmtTuple),
      Symbol::Flag::Subroutine,
      HasModulePrefix(std::get<std::list<parser::PrefixSpec>>(stmtTuple)));
}
void SubprogramVisitor::Post(const parser::InterfaceBody::Subroutine &x) {
  const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(x.t)};
  EndSubprogram(stmt.source,
      &std::get<std::optional<parser::LanguageBindingSpec>>(stmt.statement.t));
}
bool SubprogramVisitor::Pre(const parser::InterfaceBody::Function &x) {
  const auto &stmtTuple{
      std::get<parser::Statement<parser::FunctionStmt>>(x.t).statement.t};
  return BeginSubprogram(std::get<parser::Name>(stmtTuple),
      Symbol::Flag::Function,
      HasModulePrefix(std::get<std::list<parser::PrefixSpec>>(stmtTuple)));
}
void SubprogramVisitor::Post(const parser::InterfaceBody::Function &x) {
  const auto &stmt{std::get<parser::Statement<parser::FunctionStmt>>(x.t)};
  const auto &maybeSuffix{
      std::get<std::optional<parser::Suffix>>(stmt.statement.t)};
  EndSubprogram(stmt.source, maybeSuffix ? &maybeSuffix->binding : nullptr);
}

bool SubprogramVisitor::Pre(const parser::SubroutineStmt &stmt) {
  BeginAttrs();
  Walk(std::get<std::list<parser::PrefixSpec>>(stmt.t));
  Walk(std::get<parser::Name>(stmt.t));
  Walk(std::get<std::list<parser::DummyArg>>(stmt.t));
  // Don't traverse the LanguageBindingSpec now; it's deferred to EndSubprogram.
  Symbol &symbol{PostSubprogramStmt()};
  SubprogramDetails &details{symbol.get<SubprogramDetails>()};
  for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {
    if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {
      CreateDummyArgument(details, *dummyName);
    } else {
      details.add_alternateReturn();
    }
  }
  return false;
}
bool SubprogramVisitor::Pre(const parser::FunctionStmt &) {
  FuncResultStack::FuncInfo &info{DEREF(funcResultStack().Top())};
  CHECK(!info.inFunctionStmt);
  info.inFunctionStmt = true;
  return BeginAttrs();
}
bool SubprogramVisitor::Pre(const parser::EntryStmt &) { return BeginAttrs(); }

void SubprogramVisitor::Post(const parser::FunctionStmt &stmt) {
  const auto &name{std::get<parser::Name>(stmt.t)};
  Symbol &symbol{PostSubprogramStmt()};
  SubprogramDetails &details{symbol.get<SubprogramDetails>()};
  for (const auto &dummyName : std::get<std::list<parser::Name>>(stmt.t)) {
    CreateDummyArgument(details, dummyName);
  }
  const parser::Name *funcResultName;
  FuncResultStack::FuncInfo &info{DEREF(funcResultStack().Top())};
  CHECK(info.inFunctionStmt);
  info.inFunctionStmt = false;
  bool distinctResultName{
      info.resultName && info.resultName->source != name.source};
  if (distinctResultName) {
    // Note that RESULT is ignored if it has the same name as the function.
    // The symbol created by PushScope() is retained as a place-holder
    // for error detection.
    funcResultName = info.resultName;
  } else {
    EraseSymbol(name); // was added by PushScope()
    funcResultName = &name;
  }
  if (details.isFunction()) {
    CHECK(context().HasError(currScope().symbol()));
  } else {
    // RESULT(x) can be the same explicitly-named RESULT(x) as an ENTRY
    // statement.
    Symbol *result{nullptr};
    if (distinctResultName) {
      if (auto iter{currScope().find(funcResultName->source)};
          iter != currScope().end()) {
        Symbol &entryResult{*iter->second};
        if (IsFunctionResult(entryResult)) {
          result = &entryResult;
        }
      }
    }
    if (result) {
      Resolve(*funcResultName, *result);
    } else {
      // add function result to function scope
      EntityDetails funcResultDetails;
      funcResultDetails.set_funcResult(true);
      result = &MakeSymbol(*funcResultName, std::move(funcResultDetails));
    }
    info.resultSymbol = result;
    details.set_result(*result);
  }
  // C1560.
  if (info.resultName && !distinctResultName) {
    Say(info.resultName->source,
        "The function name should not appear in RESULT; references to '%s' "
        "inside the function will be considered as references to the "
        "result only"_warn_en_US,
        name.source);
    // RESULT name was ignored above, the only side effect from doing so will be
    // the inability to make recursive calls. The related parser::Name is still
    // resolved to the created function result symbol because every parser::Name
    // should be resolved to avoid internal errors.
    Resolve(*info.resultName, info.resultSymbol);
  }
  name.symbol = &symbol; // must not be function result symbol
  // Clear the RESULT() name now in case an ENTRY statement in the implicit-part
  // has a RESULT() suffix.
  info.resultName = nullptr;
}

Symbol &SubprogramVisitor::PostSubprogramStmt() {
  Symbol &symbol{*currScope().symbol()};
  SetExplicitAttrs(symbol, EndAttrs());
  if (symbol.attrs().test(Attr::MODULE)) {
    symbol.attrs().set(Attr::EXTERNAL, false);
    symbol.implicitAttrs().set(Attr::EXTERNAL, false);
  }
  return symbol;
}

void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {
  if (const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)}) {
    Walk(suffix->binding);
  }
  PostEntryStmt(stmt);
  EndAttrs();
}

void SubprogramVisitor::CreateDummyArgument(
    SubprogramDetails &details, const parser::Name &name) {
  Symbol *dummy{FindInScope(name)};
  if (dummy) {
    if (IsDummy(*dummy)) {
      if (dummy->test(Symbol::Flag::EntryDummyArgument)) {
        dummy->set(Symbol::Flag::EntryDummyArgument, false);
      } else {
        Say(name,
            "'%s' appears more than once as a dummy argument name in this subprogram"_err_en_US,
            name.source);
        return;
      }
    } else {
      SayWithDecl(name, *dummy,
          "'%s' may not appear as a dummy argument name in this subprogram"_err_en_US);
      return;
    }
  } else {
    dummy = &MakeSymbol(name, EntityDetails{true});
  }
  details.add_dummyArg(DEREF(dummy));
}

void SubprogramVisitor::CreateEntry(
    const parser::EntryStmt &stmt, Symbol &subprogram) {
  const auto &entryName{std::get<parser::Name>(stmt.t)};
  Scope &outer{currScope().parent()};
  Symbol::Flag subpFlag{subprogram.test(Symbol::Flag::Function)
          ? Symbol::Flag::Function
          : Symbol::Flag::Subroutine};
  Attrs attrs;
  const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)};
  bool hasGlobalBindingName{outer.IsGlobal() && suffix && suffix->binding &&
      suffix->binding->v.has_value()};
  if (!hasGlobalBindingName) {
    if (Symbol * extant{FindSymbol(outer, entryName)}) {
      if (!HandlePreviousCalls(entryName, *extant, subpFlag)) {
        if (outer.IsTopLevel()) {
          Say2(entryName,
              "'%s' is already defined as a global identifier"_err_en_US,
              *extant, "Previous definition of '%s'"_en_US);
        } else {
          SayAlreadyDeclared(entryName, *extant);
        }
        return;
      }
      attrs = extant->attrs();
    }
  }
  bool badResultName{false};
  std::optional<SourceName> distinctResultName;
  if (suffix && suffix->resultName &&
      suffix->resultName->source != entryName.source) {
    distinctResultName = suffix->resultName->source;
    const parser::Name &resultName{*suffix->resultName};
    if (resultName.source == subprogram.name()) { // C1574
      Say2(resultName.source,
          "RESULT(%s) may not have the same name as the function"_err_en_US,
          subprogram, "Containing function"_en_US);
      badResultName = true;
    } else if (const Symbol * extant{FindSymbol(outer, resultName)}) { // C1574
      if (const auto *details{extant->detailsIf<SubprogramDetails>()}) {
        if (details->entryScope() == &currScope()) {
          Say2(resultName.source,
              "RESULT(%s) may not have the same name as an ENTRY in the function"_err_en_US,
              extant->name(), "Conflicting ENTRY"_en_US);
          badResultName = true;
        }
      }
    }
  }
  if (outer.IsModule() && !attrs.test(Attr::PRIVATE)) {
    attrs.set(Attr::PUBLIC);
  }
  Symbol *entrySymbol{nullptr};
  if (hasGlobalBindingName) {
    // Hide the entry's symbol in a new anonymous global scope so
    // that its name doesn't clash with anything.
    Symbol &symbol{MakeSymbol(outer, context().GetTempName(outer), Attrs{})};
    symbol.set_details(MiscDetails{MiscDetails::Kind::ScopeName});
    Scope &hidden{outer.MakeScope(Scope::Kind::Global, &symbol)};
    entrySymbol = &MakeSymbol(hidden, entryName.source, attrs);
  } else {
    entrySymbol = FindInScope(outer, entryName.source);
    if (entrySymbol) {
      if (auto *generic{entrySymbol->detailsIf<GenericDetails>()}) {
        if (auto *specific{generic->specific()}) {
          // Forward reference to ENTRY from a generic interface
          entrySymbol = specific;
          CheckDuplicatedAttrs(entryName.source, *entrySymbol, attrs);
          SetExplicitAttrs(*entrySymbol, attrs);
        }
      }
    } else {
      entrySymbol = &MakeSymbol(outer, entryName.source, attrs);
    }
  }
  SubprogramDetails entryDetails;
  entryDetails.set_entryScope(currScope());
  entrySymbol->set(subpFlag);
  if (subpFlag == Symbol::Flag::Function) {
    Symbol *result{nullptr};
    EntityDetails resultDetails;
    resultDetails.set_funcResult(true);
    if (distinctResultName) {
      if (!badResultName) {
        // RESULT(x) can be the same explicitly-named RESULT(x) as
        // the enclosing function or another ENTRY.
        if (auto iter{currScope().find(suffix->resultName->source)};
            iter != currScope().end()) {
          result = &*iter->second;
        }
        if (!result) {
          result = &MakeSymbol(
              *distinctResultName, Attrs{}, std::move(resultDetails));
        }
        Resolve(*suffix->resultName, *result);
      }
    } else {
      result = &MakeSymbol(entryName.source, Attrs{}, std::move(resultDetails));
    }
    if (result) {
      entryDetails.set_result(*result);
    }
  }
  if (subpFlag == Symbol::Flag::Subroutine ||
      (distinctResultName && !badResultName)) {
    Symbol &assoc{MakeSymbol(entryName.source)};
    assoc.set_details(HostAssocDetails{*entrySymbol});
    assoc.set(Symbol::Flag::Subroutine);
  }
  Resolve(entryName, *entrySymbol);
  std::set<SourceName> dummies;
  for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {
    if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {
      auto pair{dummies.insert(dummyName->source)};
      if (!pair.second) {
        Say(*dummyName,
            "'%s' appears more than once as a dummy argument name in this ENTRY statement"_err_en_US,
            dummyName->source);
        continue;
      }
      Symbol *dummy{FindInScope(*dummyName)};
      if (dummy) {
        if (!IsDummy(*dummy)) {
          evaluate::AttachDeclaration(
              Say(*dummyName,
                  "'%s' may not appear as a dummy argument name in this ENTRY statement"_err_en_US,
                  dummyName->source),
              *dummy);
          continue;
        }
      } else {
        dummy = &MakeSymbol(*dummyName, EntityDetails{true});
        dummy->set(Symbol::Flag::EntryDummyArgument);
      }
      entryDetails.add_dummyArg(DEREF(dummy));
    } else if (subpFlag == Symbol::Flag::Function) { // C1573
      Say(entryName,
          "ENTRY in a function may not have an alternate return dummy argument"_err_en_US);
      break;
    } else {
      entryDetails.add_alternateReturn();
    }
  }
  entrySymbol->set_details(std::move(entryDetails));
}

void SubprogramVisitor::PostEntryStmt(const parser::EntryStmt &stmt) {
  // The entry symbol should have already been created and resolved
  // in CreateEntry(), called by BeginSubprogram(), with one exception (below).
  const auto &name{std::get<parser::Name>(stmt.t)};
  Scope &inclusiveScope{InclusiveScope()};
  if (!name.symbol) {
    if (inclusiveScope.kind() != Scope::Kind::Subprogram) {
      Say(name.source,
          "ENTRY '%s' may appear only in a subroutine or function"_err_en_US,
          name.source);
    } else if (FindSeparateModuleSubprogramInterface(inclusiveScope.symbol())) {
      Say(name.source,
          "ENTRY '%s' may not appear in a separate module procedure"_err_en_US,
          name.source);
    } else {
      // C1571 - entry is nested, so was not put into the program tree; error
      // is emitted from MiscChecker in semantics.cpp.
    }
    return;
  }
  Symbol &entrySymbol{*name.symbol};
  if (context().HasError(entrySymbol)) {
    return;
  }
  if (!entrySymbol.has<SubprogramDetails>()) {
    SayAlreadyDeclared(name, entrySymbol);
    return;
  }
  SubprogramDetails &entryDetails{entrySymbol.get<SubprogramDetails>()};
  CHECK(entryDetails.entryScope() == &inclusiveScope);
  SetCUDADataAttr(name.source, entrySymbol, cudaDataAttr());
  entrySymbol.attrs() |= GetAttrs();
  SetBindNameOn(entrySymbol);
  for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {
    if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {
      if (Symbol * dummy{FindInScope(*dummyName)}) {
        if (dummy->test(Symbol::Flag::EntryDummyArgument)) {
          const auto *subp{dummy->detailsIf<SubprogramDetails>()};
          if (subp && subp->isInterface()) { // ok
          } else if (!dummy->has<EntityDetails>() &&
              !dummy->has<ObjectEntityDetails>() &&
              !dummy->has<ProcEntityDetails>()) {
            SayWithDecl(*dummyName, *dummy,
                "ENTRY dummy argument '%s' was previously declared as an item that may not be used as a dummy argument"_err_en_US);
          }
          dummy->set(Symbol::Flag::EntryDummyArgument, false);
        }
      }
    }
  }
}

Symbol *ScopeHandler::FindSeparateModuleProcedureInterface(
    const parser::Name &name) {
  auto *symbol{FindSymbol(name)};
  if (symbol && symbol->has<SubprogramNameDetails>()) {
    const Scope *parent{nullptr};
    if (currScope().IsSubmodule()) {
      parent = currScope().symbol()->get<ModuleDetails>().parent();
    }
    symbol = parent ? FindSymbol(*parent, name) : nullptr;
  }
  if (symbol) {
    if (auto *generic{symbol->detailsIf<GenericDetails>()}) {
      symbol = generic->specific();
    }
  }
  if (const Symbol * defnIface{FindSeparateModuleSubprogramInterface(symbol)}) {
    // Error recovery in case of multiple definitions
    symbol = const_cast<Symbol *>(defnIface);
  }
  if (!IsSeparateModuleProcedureInterface(symbol)) {
    Say(name, "'%s' was not declared a separate module procedure"_err_en_US);
    symbol = nullptr;
  }
  return symbol;
}

// A subprogram declared with MODULE PROCEDURE
bool SubprogramVisitor::BeginMpSubprogram(const parser::Name &name) {
  Symbol *symbol{FindSeparateModuleProcedureInterface(name)};
  if (!symbol) {
    return false;
  }
  if (symbol->owner() == currScope() && symbol->scope()) {
    // This is a MODULE PROCEDURE whose interface appears in its host.
    // Convert the module procedure's interface into a subprogram.
    SetScope(DEREF(symbol->scope()));
    symbol->get<SubprogramDetails>().set_isInterface(false);
    name.symbol = symbol;
  } else {
    // Copy the interface into a new subprogram scope.
    EraseSymbol(name);
    Symbol &newSymbol{MakeSymbol(name, SubprogramDetails{})};
    PushScope(Scope::Kind::Subprogram, &newSymbol);
    auto &newSubprogram{newSymbol.get<SubprogramDetails>()};
    newSubprogram.set_moduleInterface(*symbol);
    auto &subprogram{symbol->get<SubprogramDetails>()};
    if (const auto *name{subprogram.bindName()}) {
      newSubprogram.set_bindName(std::string{*name});
    }
    newSymbol.attrs() |= symbol->attrs();
    newSymbol.set(symbol->test(Symbol::Flag::Subroutine)
            ? Symbol::Flag::Subroutine
            : Symbol::Flag::Function);
    MapSubprogramToNewSymbols(*symbol, newSymbol, currScope());
  }
  return true;
}

// A subprogram or interface declared with SUBROUTINE or FUNCTION
bool SubprogramVisitor::BeginSubprogram(const parser::Name &name,
    Symbol::Flag subpFlag, bool hasModulePrefix,
    const parser::LanguageBindingSpec *bindingSpec,
    const ProgramTree::EntryStmtList *entryStmts) {
  if (hasModulePrefix && !currScope().IsModule() &&
      !currScope().IsSubmodule()) { // C1547
    Say(name,
        "'%s' is a MODULE procedure which must be declared within a "
        "MODULE or SUBMODULE"_err_en_US);
    return false;
  }
  Symbol *moduleInterface{nullptr};
  if (hasModulePrefix && !inInterfaceBlock()) {
    moduleInterface = FindSeparateModuleProcedureInterface(name);
    if (moduleInterface && &moduleInterface->owner() == &currScope()) {
      // Subprogram is MODULE FUNCTION or MODULE SUBROUTINE with an interface
      // previously defined in the same scope.
      if (GenericDetails *
          generic{DEREF(FindSymbol(name)).detailsIf<GenericDetails>()}) {
        generic->clear_specific();
        name.symbol = nullptr;
      } else {
        EraseSymbol(name);
      }
    }
  }
  Symbol &newSymbol{
      PushSubprogramScope(name, subpFlag, bindingSpec, hasModulePrefix)};
  if (moduleInterface) {
    newSymbol.get<SubprogramDetails>().set_moduleInterface(*moduleInterface);
    if (moduleInterface->attrs().test(Attr::PRIVATE)) {
      SetImplicitAttr(newSymbol, Attr::PRIVATE);
    } else if (moduleInterface->attrs().test(Attr::PUBLIC)) {
      SetImplicitAttr(newSymbol, Attr::PUBLIC);
    }
  }
  if (entryStmts) {
    for (const auto &ref : *entryStmts) {
      CreateEntry(*ref, newSymbol);
    }
  }
  return true;
}

void SubprogramVisitor::HandleLanguageBinding(Symbol *symbol,
    std::optional<parser::CharBlock> stmtSource,
    const std::optional<parser::LanguageBindingSpec> *binding) {
  if (binding && *binding && symbol) {
    // Finally process the BIND(C,NAME=name) now that symbols in the name
    // expression will resolve to local names if needed.
    auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)};
    auto originalStmtSource{messageHandler().currStmtSource()};
    messageHandler().set_currStmtSource(stmtSource);
    BeginAttrs();
    Walk(**binding);
    SetBindNameOn(*symbol);
    symbol->attrs() |= EndAttrs();
    messageHandler().set_currStmtSource(originalStmtSource);
  }
}

void SubprogramVisitor::EndSubprogram(
    std::optional<parser::CharBlock> stmtSource,
    const std::optional<parser::LanguageBindingSpec> *binding,
    const ProgramTree::EntryStmtList *entryStmts) {
  HandleLanguageBinding(currScope().symbol(), stmtSource, binding);
  if (entryStmts) {
    for (const auto &ref : *entryStmts) {
      const parser::EntryStmt &entryStmt{*ref};
      if (const auto &suffix{
              std::get<std::optional<parser::Suffix>>(entryStmt.t)}) {
        const auto &name{std::get<parser::Name>(entryStmt.t)};
        HandleLanguageBinding(name.symbol, name.source, &suffix->binding);
      }
    }
  }
  if (inInterfaceBlock() && currScope().symbol()) {
    DeclaredPossibleSpecificProc(*currScope().symbol());
  }
  PopScope();
}

bool SubprogramVisitor::HandlePreviousCalls(
    const parser::Name &name, Symbol &symbol, Symbol::Flag subpFlag) {
  // If the extant symbol is a generic, check its homonymous specific
  // procedure instead if it has one.
  if (auto *generic{symbol.detailsIf<GenericDetails>()}) {
    return generic->specific() &&
        HandlePreviousCalls(name, *generic->specific(), subpFlag);
  } else if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}; proc &&
             !proc->isDummy() &&
             !symbol.attrs().HasAny(Attrs{Attr::INTRINSIC, Attr::POINTER})) {
    // There's a symbol created for previous calls to this subprogram or
    // ENTRY's name.  We have to replace that symbol in situ to avoid the
    // obligation to rewrite symbol pointers in the parse tree.
    if (!symbol.test(subpFlag)) {
      auto other{subpFlag == Symbol::Flag::Subroutine
              ? Symbol::Flag::Function
              : Symbol::Flag::Subroutine};
      // External statements issue an explicit EXTERNAL attribute.
      if (symbol.attrs().test(Attr::EXTERNAL) &&
          !symbol.implicitAttrs().test(Attr::EXTERNAL)) {
        // Warn if external statement previously declared.
        Say(name,
            "EXTERNAL attribute was already specified on '%s'"_warn_en_US);
      } else if (symbol.test(other)) {
        Say2(name,
            subpFlag == Symbol::Flag::Function
                ? "'%s' was previously called as a subroutine"_err_en_US
                : "'%s' was previously called as a function"_err_en_US,
            symbol, "Previous call of '%s'"_en_US);
      } else {
        symbol.set(subpFlag);
      }
    }
    EntityDetails entity;
    if (proc->type()) {
      entity.set_type(*proc->type());
    }
    symbol.details() = std::move(entity);
    return true;
  } else {
    return symbol.has<UnknownDetails>() || symbol.has<SubprogramNameDetails>();
  }
}

void SubprogramVisitor::CheckExtantProc(
    const parser::Name &name, Symbol::Flag subpFlag) {
  if (auto *prev{FindSymbol(name)}) {
    if (IsDummy(*prev)) {
    } else if (auto *entity{prev->detailsIf<EntityDetails>()};
               IsPointer(*prev) && entity && !entity->type()) {
      // POINTER attribute set before interface
    } else if (inInterfaceBlock() && currScope() != prev->owner()) {
      // Procedures in an INTERFACE block do not resolve to symbols
      // in scopes between the global scope and the current scope.
    } else if (!HandlePreviousCalls(name, *prev, subpFlag)) {
      SayAlreadyDeclared(name, *prev);
    }
  }
}

Symbol &SubprogramVisitor::PushSubprogramScope(const parser::Name &name,
    Symbol::Flag subpFlag, const parser::LanguageBindingSpec *bindingSpec,
    bool hasModulePrefix) {
  Symbol *symbol{GetSpecificFromGeneric(name)};
  if (!symbol) {
    if (bindingSpec && currScope().IsGlobal() && bindingSpec->v) {
      // Create this new top-level subprogram with a binding label
      // in a new global scope, so that its symbol's name won't clash
      // with another symbol that has a distinct binding label.
      PushScope(Scope::Kind::Global,
          &MakeSymbol(context().GetTempName(currScope()), Attrs{},
              MiscDetails{MiscDetails::Kind::ScopeName}));
    }
    CheckExtantProc(name, subpFlag);
    symbol = &MakeSymbol(name, SubprogramDetails{});
  }
  symbol->ReplaceName(name.source);
  symbol->set(subpFlag);
  PushScope(Scope::Kind::Subprogram, symbol);
  if (subpFlag == Symbol::Flag::Function) {
    funcResultStack().Push(currScope());
  }
  if (inInterfaceBlock()) {
    auto &details{symbol->get<SubprogramDetails>()};
    details.set_isInterface();
    if (isAbstract()) {
      SetExplicitAttr(*symbol, Attr::ABSTRACT);
    } else if (hasModulePrefix) {
      SetExplicitAttr(*symbol, Attr::MODULE);
    } else {
      MakeExternal(*symbol);
    }
    if (isGeneric()) {
      Symbol &genericSymbol{GetGenericSymbol()};
      if (auto *details{genericSymbol.detailsIf<GenericDetails>()}) {
        details->AddSpecificProc(*symbol, name.source);
      } else {
        CHECK(context().HasError(genericSymbol));
      }
    }
    set_inheritFromParent(hasModulePrefix);
  }
  if (Symbol * found{FindSymbol(name)};
      found && found->has<HostAssocDetails>()) {
    found->set(subpFlag); // PushScope() created symbol
  }
  return *symbol;
}

void SubprogramVisitor::PushBlockDataScope(const parser::Name &name) {
  if (auto *prev{FindSymbol(name)}) {
    if (prev->attrs().test(Attr::EXTERNAL) && prev->has<ProcEntityDetails>()) {
      if (prev->test(Symbol::Flag::Subroutine) ||
          prev->test(Symbol::Flag::Function)) {
        Say2(name, "BLOCK DATA '%s' has been called"_err_en_US, *prev,
            "Previous call of '%s'"_en_US);
      }
      EraseSymbol(name);
    }
  }
  if (name.source.empty()) {
    // Don't let unnamed BLOCK DATA conflict with unnamed PROGRAM
    PushScope(Scope::Kind::BlockData, nullptr);
  } else {
    PushScope(Scope::Kind::BlockData, &MakeSymbol(name, SubprogramDetails{}));
  }
}

// If name is a generic, return specific subprogram with the same name.
Symbol *SubprogramVisitor::GetSpecificFromGeneric(const parser::Name &name) {
  // Search for the name but don't resolve it
  if (auto *symbol{currScope().FindSymbol(name.source)}) {
    if (symbol->has<SubprogramNameDetails>()) {
      if (inInterfaceBlock()) {
        // Subtle: clear any MODULE flag so that the new interface
        // symbol doesn't inherit it and ruin the ability to check it.
        symbol->attrs().reset(Attr::MODULE);
      }
    } else if (auto *details{symbol->detailsIf<GenericDetails>()}) {
      // found generic, want specific procedure
      auto *specific{details->specific()};
      Attrs moduleAttr;
      if (inInterfaceBlock()) {
        if (specific) {
          // Defining an interface in a generic of the same name which is
          // already shadowing another procedure.  In some cases, the shadowed
          // procedure is about to be replaced.
          if (specific->has<SubprogramNameDetails>() &&
              specific->attrs().test(Attr::MODULE)) {
            // The shadowed procedure is a separate module procedure that is
            // actually defined later in this (sub)module.
            // Define its interface now as a new symbol.
            moduleAttr.set(Attr::MODULE);
            specific = nullptr;
          } else if (&specific->owner() != &symbol->owner()) {
            // The shadowed procedure was from an enclosing scope and will be
            // overridden by this interface definition.
            specific = nullptr;
          }
          if (!specific) {
            details->clear_specific();
          }
        } else if (const auto *dType{details->derivedType()}) {
          if (&dType->owner() != &symbol->owner()) {
            // The shadowed derived type was from an enclosing scope and
            // will be overridden by this interface definition.
            details->clear_derivedType();
          }
        }
      }
      if (!specific) {
        specific = &currScope().MakeSymbol(
            name.source, std::move(moduleAttr), SubprogramDetails{});
        if (details->derivedType()) {
          // A specific procedure with the same name as a derived type
          SayAlreadyDeclared(name, *details->derivedType());
        } else {
          details->set_specific(Resolve(name, *specific));
        }
      } else if (isGeneric()) {
        SayAlreadyDeclared(name, *specific);
      }
      if (specific->has<SubprogramNameDetails>()) {
        specific->set_details(Details{SubprogramDetails{}});
      }
      return specific;
    }
  }
  return nullptr;
}

// DeclarationVisitor implementation

bool DeclarationVisitor::BeginDecl() {
  BeginDeclTypeSpec();
  BeginArraySpec();
  return BeginAttrs();
}
void DeclarationVisitor::EndDecl() {
  EndDeclTypeSpec();
  EndArraySpec();
  EndAttrs();
}

bool DeclarationVisitor::CheckUseError(const parser::Name &name) {
  return HadUseError(context(), name.source, name.symbol);
}

// Report error if accessibility of symbol doesn't match isPrivate.
void DeclarationVisitor::CheckAccessibility(
    const SourceName &name, bool isPrivate, Symbol &symbol) {
  if (symbol.attrs().test(Attr::PRIVATE) != isPrivate) {
    Say2(name,
        "'%s' does not have the same accessibility as its previous declaration"_err_en_US,
        symbol, "Previous declaration of '%s'"_en_US);
  }
}

bool DeclarationVisitor::Pre(const parser::TypeDeclarationStmt &x) {
  BeginDecl();
  // If INTRINSIC appears as an attr-spec, handle it now as if the
  // names had appeared on an INTRINSIC attribute statement beforehand.
  for (const auto &attr : std::get<std::list<parser::AttrSpec>>(x.t)) {
    if (std::holds_alternative<parser::Intrinsic>(attr.u)) {
      for (const auto &decl : std::get<std::list<parser::EntityDecl>>(x.t)) {
        DeclareIntrinsic(parser::GetFirstName(decl));
      }
      break;
    }
  }
  return true;
}
void DeclarationVisitor::Post(const parser::TypeDeclarationStmt &) {
  EndDecl();
}

void DeclarationVisitor::Post(const parser::DimensionStmt::Declaration &x) {
  DeclareObjectEntity(std::get<parser::Name>(x.t));
}
void DeclarationVisitor::Post(const parser::CodimensionDecl &x) {
  DeclareObjectEntity(std::get<parser::Name>(x.t));
}

bool DeclarationVisitor::Pre(const parser::Initialization &) {
  // Defer inspection of initializers to Initialization() so that the
  // symbol being initialized will be available within the initialization
  // expression.
  return false;
}

void DeclarationVisitor::Post(const parser::EntityDecl &x) {
  const auto &name{std::get<parser::ObjectName>(x.t)};
  Attrs attrs{attrs_ ? HandleSaveName(name.source, *attrs_) : Attrs{}};
  attrs.set(Attr::INTRINSIC, false); // dealt with in Pre(TypeDeclarationStmt)
  Symbol &symbol{DeclareUnknownEntity(name, attrs)};
  symbol.ReplaceName(name.source);
  SetCUDADataAttr(name.source, symbol, cudaDataAttr());
  if (const auto &init{std::get<std::optional<parser::Initialization>>(x.t)}) {
    ConvertToObjectEntity(symbol) || ConvertToProcEntity(symbol);
    symbol.set(
        Symbol::Flag::EntryDummyArgument, false); // forestall excessive errors
    Initialization(name, *init, false);
  } else if (attrs.test(Attr::PARAMETER)) { // C882, C883
    Say(name, "Missing initialization for parameter '%s'"_err_en_US);
  }
  if (auto *scopeSymbol{currScope().symbol()})
    if (auto *details{scopeSymbol->detailsIf<DerivedTypeDetails>()})
      if (details->isDECStructure())
        details->add_component(symbol);
}

void DeclarationVisitor::Post(const parser::PointerDecl &x) {
  const auto &name{std::get<parser::Name>(x.t)};
  if (const auto &deferredShapeSpecs{
          std::get<std::optional<parser::DeferredShapeSpecList>>(x.t)}) {
    CHECK(arraySpec().empty());
    BeginArraySpec();
    set_arraySpec(AnalyzeDeferredShapeSpecList(context(), *deferredShapeSpecs));
    Symbol &symbol{DeclareObjectEntity(name, Attrs{Attr::POINTER})};
    symbol.ReplaceName(name.source);
    EndArraySpec();
  } else {
    if (const auto *symbol{FindInScope(name)}) {
      const auto *subp{symbol->detailsIf<SubprogramDetails>()};
      if (!symbol->has<UseDetails>() && // error caught elsewhere
          !symbol->has<ObjectEntityDetails>() &&
          !symbol->has<ProcEntityDetails>() &&
          !symbol->CanReplaceDetails(ObjectEntityDetails{}) &&
          !symbol->CanReplaceDetails(ProcEntityDetails{}) &&
          !(subp && subp->isInterface())) {
        Say(name, "'%s' cannot have the POINTER attribute"_err_en_US);
      }
    }
    HandleAttributeStmt(Attr::POINTER, std::get<parser::Name>(x.t));
  }
}

bool DeclarationVisitor::Pre(const parser::BindEntity &x) {
  auto kind{std::get<parser::BindEntity::Kind>(x.t)};
  auto &name{std::get<parser::Name>(x.t)};
  Symbol *symbol;
  if (kind == parser::BindEntity::Kind::Object) {
    symbol = &HandleAttributeStmt(Attr::BIND_C, name);
  } else {
    symbol = &MakeCommonBlockSymbol(name);
    SetExplicitAttr(*symbol, Attr::BIND_C);
  }
  // 8.6.4(1)
  // Some entities such as named constant or module name need to checked
  // elsewhere. This is to skip the ICE caused by setting Bind name for non-name
  // things such as data type and also checks for procedures.
  if (symbol->has<CommonBlockDetails>() || symbol->has<ObjectEntityDetails>() ||
      symbol->has<EntityDetails>()) {
    SetBindNameOn(*symbol);
  } else {
    Say(name,
        "Only variable and named common block can be in BIND statement"_err_en_US);
  }
  return false;
}
bool DeclarationVisitor::Pre(const parser::OldParameterStmt &x) {
  inOldStyleParameterStmt_ = true;
  Walk(x.v);
  inOldStyleParameterStmt_ = false;
  return false;
}
bool DeclarationVisitor::Pre(const parser::NamedConstantDef &x) {
  auto &name{std::get<parser::NamedConstant>(x.t).v};
  auto &symbol{HandleAttributeStmt(Attr::PARAMETER, name)};
  ConvertToObjectEntity(symbol);
  auto *details{symbol.detailsIf<ObjectEntityDetails>()};
  if (!details || symbol.test(Symbol::Flag::CrayPointer) ||
      symbol.test(Symbol::Flag::CrayPointee)) {
    SayWithDecl(
        name, symbol, "PARAMETER attribute not allowed on '%s'"_err_en_US);
    return false;
  }
  const auto &expr{std::get<parser::ConstantExpr>(x.t)};
  if (details->init() || symbol.test(Symbol::Flag::InDataStmt)) {
    Say(name, "Named constant '%s' already has a value"_err_en_US);
  }
  if (inOldStyleParameterStmt_) {
    // non-standard extension PARAMETER statement (no parentheses)
    Walk(expr);
    auto folded{EvaluateExpr(expr)};
    if (details->type()) {
      SayWithDecl(name, symbol,
          "Alternative style PARAMETER '%s' must not already have an explicit type"_err_en_US);
    } else if (folded) {
      auto at{expr.thing.value().source};
      if (evaluate::IsActuallyConstant(*folded)) {
        if (const auto *type{currScope().GetType(*folded)}) {
          if (type->IsPolymorphic()) {
            Say(at, "The expression must not be polymorphic"_err_en_US);
          } else if (auto shape{ToArraySpec(
                         GetFoldingContext(), evaluate::GetShape(*folded))}) {
            // The type of the named constant is assumed from the expression.
            details->set_type(*type);
            details->set_init(std::move(*folded));
            details->set_shape(std::move(*shape));
          } else {
            Say(at, "The expression must have constant shape"_err_en_US);
          }
        } else {
          Say(at, "The expression must have a known type"_err_en_US);
        }
      } else {
        Say(at, "The expression must be a constant of known type"_err_en_US);
      }
    }
  } else {
    // standard-conforming PARAMETER statement (with parentheses)
    ApplyImplicitRules(symbol);
    Walk(expr);
    if (auto converted{EvaluateNonPointerInitializer(
            symbol, expr, expr.thing.value().source)}) {
      details->set_init(std::move(*converted));
    }
  }
  return false;
}
bool DeclarationVisitor::Pre(const parser::NamedConstant &x) {
  const parser::Name &name{x.v};
  if (!FindSymbol(name)) {
    Say(name, "Named constant '%s' not found"_err_en_US);
  } else {
    CheckUseError(name);
  }
  return false;
}

bool DeclarationVisitor::Pre(const parser::Enumerator &enumerator) {
  const parser::Name &name{std::get<parser::NamedConstant>(enumerator.t).v};
  Symbol *symbol{FindInScope(name)};
  if (symbol && !symbol->has<UnknownDetails>()) {
    // Contrary to named constants appearing in a PARAMETER statement,
    // enumerator names should not have their type, dimension or any other
    // attributes defined before they are declared in the enumerator statement,
    // with the exception of accessibility.
    // This is not explicitly forbidden by the standard, but they are scalars
    // which type is left for the compiler to chose, so do not let users try to
    // tamper with that.
    SayAlreadyDeclared(name, *symbol);
    symbol = nullptr;
  } else {
    // Enumerators are treated as PARAMETER (section 7.6 paragraph (4))
    symbol = &MakeSymbol(name, Attrs{Attr::PARAMETER}, ObjectEntityDetails{});
    symbol->SetType(context().MakeNumericType(
        TypeCategory::Integer, evaluate::CInteger::kind));
  }

  if (auto &init{std::get<std::optional<parser::ScalarIntConstantExpr>>(
          enumerator.t)}) {
    Walk(*init); // Resolve names in expression before evaluation.
    if (auto value{EvaluateInt64(context(), *init)}) {
      // Cast all init expressions to C_INT so that they can then be
      // safely incremented (see 7.6 Note 2).
      enumerationState_.value = static_cast<int>(*value);
    } else {
      Say(name,
          "Enumerator value could not be computed "
          "from the given expression"_err_en_US);
      // Prevent resolution of next enumerators value
      enumerationState_.value = std::nullopt;
    }
  }

  if (symbol) {
    if (enumerationState_.value) {
      symbol->get<ObjectEntityDetails>().set_init(SomeExpr{
          evaluate::Expr<evaluate::CInteger>{*enumerationState_.value}});
    } else {
      context().SetError(*symbol);
    }
  }

  if (enumerationState_.value) {
    (*enumerationState_.value)++;
  }
  return false;
}

void DeclarationVisitor::Post(const parser::EnumDef &) {
  enumerationState_ = EnumeratorState{};
}

bool DeclarationVisitor::Pre(const parser::AccessSpec &x) {
  Attr attr{AccessSpecToAttr(x)};
  if (!NonDerivedTypeScope().IsModule()) { // C817
    Say(currStmtSource().value(),
        "%s attribute may only appear in the specification part of a module"_err_en_US,
        EnumToString(attr));
  }
  CheckAndSet(attr);
  return false;
}

bool DeclarationVisitor::Pre(const parser::AsynchronousStmt &x) {
  return HandleAttributeStmt(Attr::ASYNCHRONOUS, x.v);
}
bool DeclarationVisitor::Pre(const parser::ContiguousStmt &x) {
  return HandleAttributeStmt(Attr::CONTIGUOUS, x.v);
}
bool DeclarationVisitor::Pre(const parser::ExternalStmt &x) {
  HandleAttributeStmt(Attr::EXTERNAL, x.v);
  for (const auto &name : x.v) {
    auto *symbol{FindSymbol(name)};
    if (!ConvertToProcEntity(DEREF(symbol), name.source)) {
      // Check if previous symbol is an interface.
      if (auto *details{symbol->detailsIf<SubprogramDetails>()}) {
        if (details->isInterface()) {
          // Warn if interface previously declared.
          Say(name,
              "EXTERNAL attribute was already specified on '%s'"_warn_en_US);
        }
      } else {
        SayWithDecl(
            name, *symbol, "EXTERNAL attribute not allowed on '%s'"_err_en_US);
      }
    } else if (symbol->attrs().test(Attr::INTRINSIC)) { // C840
      Say(symbol->name(),
          "Symbol '%s' cannot have both INTRINSIC and EXTERNAL attributes"_err_en_US,
          symbol->name());
    }
  }
  return false;
}
bool DeclarationVisitor::Pre(const parser::IntentStmt &x) {
  auto &intentSpec{std::get<parser::IntentSpec>(x.t)};
  auto &names{std::get<std::list<parser::Name>>(x.t)};
  return CheckNotInBlock("INTENT") && // C1107
      HandleAttributeStmt(IntentSpecToAttr(intentSpec), names);
}
bool DeclarationVisitor::Pre(const parser::IntrinsicStmt &x) {
  for (const auto &name : x.v) {
    DeclareIntrinsic(name);
  }
  return false;
}
void DeclarationVisitor::DeclareIntrinsic(const parser::Name &name) {
  HandleAttributeStmt(Attr::INTRINSIC, name);
  if (!IsIntrinsic(name.source, std::nullopt)) {
    Say(name.source, "'%s' is not a known intrinsic procedure"_err_en_US);
  }
  auto &symbol{DEREF(FindSymbol(name))};
  if (symbol.has<GenericDetails>()) {
    // Generic interface is extending intrinsic; ok
  } else if (!ConvertToProcEntity(symbol, name.source)) {
    SayWithDecl(
        name, symbol, "INTRINSIC attribute not allowed on '%s'"_err_en_US);
  } else if (symbol.attrs().test(Attr::EXTERNAL)) { // C840
    Say(symbol.name(),
        "Symbol '%s' cannot have both EXTERNAL and INTRINSIC attributes"_err_en_US,
        symbol.name());
  } else {
    if (symbol.GetType()) {
      // These warnings are worded so that they should make sense in either
      // order.
      Say(symbol.name(),
          "Explicit type declaration ignored for intrinsic function '%s'"_warn_en_US,
          symbol.name())
          .Attach(name.source,
              "INTRINSIC statement for explicitly-typed '%s'"_en_US,
              name.source);
    }
    if (!symbol.test(Symbol::Flag::Function) &&
        !symbol.test(Symbol::Flag::Subroutine)) {
      if (context().intrinsics().IsIntrinsicFunction(name.source.ToString())) {
        symbol.set(Symbol::Flag::Function);
      } else if (context().intrinsics().IsIntrinsicSubroutine(
                     name.source.ToString())) {
        symbol.set(Symbol::Flag::Subroutine);
      }
    }
  }
}
bool DeclarationVisitor::Pre(const parser::OptionalStmt &x) {
  return CheckNotInBlock("OPTIONAL") && // C1107
      HandleAttributeStmt(Attr::OPTIONAL, x.v);
}
bool DeclarationVisitor::Pre(const parser::ProtectedStmt &x) {
  return HandleAttributeStmt(Attr::PROTECTED, x.v);
}
bool DeclarationVisitor::Pre(const parser::ValueStmt &x) {
  return CheckNotInBlock("VALUE") && // C1107
      HandleAttributeStmt(Attr::VALUE, x.v);
}
bool DeclarationVisitor::Pre(const parser::VolatileStmt &x) {
  return HandleAttributeStmt(Attr::VOLATILE, x.v);
}
bool DeclarationVisitor::Pre(const parser::CUDAAttributesStmt &x) {
  auto attr{std::get<common::CUDADataAttr>(x.t)};
  for (const auto &name : std::get<std::list<parser::Name>>(x.t)) {
    auto *symbol{FindInScope(name)};
    if (symbol && symbol->has<UseDetails>()) {
      Say(currStmtSource().value(),
          "Cannot apply CUDA data attribute to use-associated '%s'"_err_en_US,
          name.source);
    } else {
      if (!symbol) {
        symbol = &MakeSymbol(name, ObjectEntityDetails{});
      }
      SetCUDADataAttr(name.source, *symbol, attr);
    }
  }
  return false;
}
// Handle a statement that sets an attribute on a list of names.
bool DeclarationVisitor::HandleAttributeStmt(
    Attr attr, const std::list<parser::Name> &names) {
  for (const auto &name : names) {
    HandleAttributeStmt(attr, name);
  }
  return false;
}
Symbol &DeclarationVisitor::HandleAttributeStmt(
    Attr attr, const parser::Name &name) {
  auto *symbol{FindInScope(name)};
  if (attr == Attr::ASYNCHRONOUS || attr == Attr::VOLATILE) {
    // these can be set on a symbol that is host-assoc or use-assoc
    if (!symbol &&
        (currScope().kind() == Scope::Kind::Subprogram ||
            currScope().kind() == Scope::Kind::BlockConstruct)) {
      if (auto *hostSymbol{FindSymbol(name)}) {
        symbol = &MakeHostAssocSymbol(name, *hostSymbol);
      }
    }
  } else if (symbol && symbol->has<UseDetails>()) {
    if (symbol->GetUltimate().attrs().test(attr)) {
      Say(currStmtSource().value(),
          "Use-associated '%s' already has '%s' attribute"_warn_en_US,
          name.source, EnumToString(attr));
    } else {
      Say(currStmtSource().value(),
          "Cannot change %s attribute on use-associated '%s'"_err_en_US,
          EnumToString(attr), name.source);
    }
    return *symbol;
  }
  if (!symbol) {
    symbol = &MakeSymbol(name, EntityDetails{});
  }
  if (CheckDuplicatedAttr(name.source, *symbol, attr)) {
    HandleSaveName(name.source, Attrs{attr});
    SetExplicitAttr(*symbol, attr);
  }
  return *symbol;
}
// C1107
bool DeclarationVisitor::CheckNotInBlock(const char *stmt) {
  if (currScope().kind() == Scope::Kind::BlockConstruct) {
    Say(MessageFormattedText{
        "%s statement is not allowed in a BLOCK construct"_err_en_US, stmt});
    return false;
  } else {
    return true;
  }
}

void DeclarationVisitor::Post(const parser::ObjectDecl &x) {
  CHECK(objectDeclAttr_);
  const auto &name{std::get<parser::ObjectName>(x.t)};
  DeclareObjectEntity(name, Attrs{*objectDeclAttr_});
}

// Declare an entity not yet known to be an object or proc.
Symbol &DeclarationVisitor::DeclareUnknownEntity(
    const parser::Name &name, Attrs attrs) {
  if (!arraySpec().empty() || !coarraySpec().empty()) {
    return DeclareObjectEntity(name, attrs);
  } else {
    Symbol &symbol{DeclareEntity<EntityDetails>(name, attrs)};
    if (auto *type{GetDeclTypeSpec()}) {
      SetType(name, *type);
    }
    charInfo_.length.reset();
    if (symbol.attrs().test(Attr::EXTERNAL)) {
      ConvertToProcEntity(symbol);
    }
    if (attrs.test(Attr::BIND_C)) {
      SetBindNameOn(symbol);
    }
    return symbol;
  }
}

bool DeclarationVisitor::HasCycle(
    const Symbol &procSymbol, const Symbol *interface) {
  SourceOrderedSymbolSet procsInCycle;
  procsInCycle.insert(procSymbol);
  while (interface) {
    if (procsInCycle.count(*interface) > 0) {
      for (const auto &procInCycle : procsInCycle) {
        Say(procInCycle->name(),
            "The interface for procedure '%s' is recursively "
            "defined"_err_en_US,
            procInCycle->name());
        context().SetError(*procInCycle);
      }
      return true;
    } else if (const auto *procDetails{
                   interface->detailsIf<ProcEntityDetails>()}) {
      procsInCycle.insert(*interface);
      interface = procDetails->procInterface();
    } else {
      break;
    }
  }
  return false;
}

Symbol &DeclarationVisitor::DeclareProcEntity(
    const parser::Name &name, Attrs attrs, const Symbol *interface) {
  Symbol &symbol{DeclareEntity<ProcEntityDetails>(name, attrs)};
  if (auto *details{symbol.detailsIf<ProcEntityDetails>()}) {
    if (context().HasError(symbol)) {
    } else if (HasCycle(symbol, interface)) {
      return symbol;
    } else if (interface && (details->procInterface() || details->type())) {
      SayWithDecl(name, symbol,
          "The interface for procedure '%s' has already been declared"_err_en_US);
      context().SetError(symbol);
    } else if (interface) {
      details->set_procInterfaces(
          *interface, BypassGeneric(interface->GetUltimate()));
      if (interface->test(Symbol::Flag::Function)) {
        symbol.set(Symbol::Flag::Function);
      } else if (interface->test(Symbol::Flag::Subroutine)) {
        symbol.set(Symbol::Flag::Subroutine);
      }
      if (IsBindCProcedure(*interface) && !IsPointer(symbol) &&
          !IsDummy(symbol)) {
        // Inherit BIND_C attribute from the interface, but not the NAME="..."
        // if any. This is not clearly described in the standard, but matches
        // the behavior of other compilers.
        SetImplicitAttr(symbol, Attr::BIND_C);
      }
    } else if (auto *type{GetDeclTypeSpec()}) {
      SetType(name, *type);
      symbol.set(Symbol::Flag::Function);
    }
    SetBindNameOn(symbol);
    SetPassNameOn(symbol);
  }
  return symbol;
}

Symbol &DeclarationVisitor::DeclareObjectEntity(
    const parser::Name &name, Attrs attrs) {
  Symbol &symbol{DeclareEntity<ObjectEntityDetails>(name, attrs)};
  if (auto *details{symbol.detailsIf<ObjectEntityDetails>()}) {
    if (auto *type{GetDeclTypeSpec()}) {
      SetType(name, *type);
    }
    if (!arraySpec().empty()) {
      if (details->IsArray()) {
        if (!context().HasError(symbol)) {
          Say(name,
              "The dimensions of '%s' have already been declared"_err_en_US);
          context().SetError(symbol);
        }
      } else if (MustBeScalar(symbol)) {
        Say(name,
            "'%s' appeared earlier as a scalar actual argument to a specification function"_warn_en_US);
      } else if (details->init() || symbol.test(Symbol::Flag::InDataStmt)) {
        Say(name, "'%s' was initialized earlier as a scalar"_err_en_US);
      } else {
        details->set_shape(arraySpec());
      }
    }
    if (!coarraySpec().empty()) {
      if (details->IsCoarray()) {
        if (!context().HasError(symbol)) {
          Say(name,
              "The codimensions of '%s' have already been declared"_err_en_US);
          context().SetError(symbol);
        }
      } else {
        details->set_coshape(coarraySpec());
      }
    }
    SetBindNameOn(symbol);
  }
  ClearArraySpec();
  ClearCoarraySpec();
  charInfo_.length.reset();
  return symbol;
}

void DeclarationVisitor::Post(const parser::IntegerTypeSpec &x) {
  if (!isVectorType_) {
    SetDeclTypeSpec(MakeNumericType(TypeCategory::Integer, x.v));
  }
}
void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Real &x) {
  if (!isVectorType_) {
    SetDeclTypeSpec(MakeNumericType(TypeCategory::Real, x.kind));
  }
}
void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Complex &x) {
  SetDeclTypeSpec(MakeNumericType(TypeCategory::Complex, x.kind));
}
void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Logical &x) {
  SetDeclTypeSpec(MakeLogicalType(x.kind));
}
void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Character &) {
  if (!charInfo_.length) {
    charInfo_.length = ParamValue{1, common::TypeParamAttr::Len};
  }
  if (!charInfo_.kind) {
    charInfo_.kind =
        KindExpr{context().GetDefaultKind(TypeCategory::Character)};
  }
  SetDeclTypeSpec(currScope().MakeCharacterType(
      std::move(*charInfo_.length), std::move(*charInfo_.kind)));
  charInfo_ = {};
}
void DeclarationVisitor::Post(const parser::CharSelector::LengthAndKind &x) {
  charInfo_.kind = EvaluateSubscriptIntExpr(x.kind);
  std::optional<std::int64_t> intKind{ToInt64(charInfo_.kind)};
  if (intKind &&
      !context().targetCharacteristics().IsTypeEnabled(
          TypeCategory::Character, *intKind)) { // C715, C719
    Say(currStmtSource().value(),
        "KIND value (%jd) not valid for CHARACTER"_err_en_US, *intKind);
    charInfo_.kind = std::nullopt; // prevent further errors
  }
  if (x.length) {
    charInfo_.length = GetParamValue(*x.length, common::TypeParamAttr::Len);
  }
}
void DeclarationVisitor::Post(const parser::CharLength &x) {
  if (const auto *length{std::get_if<std::uint64_t>(&x.u)}) {
    charInfo_.length = ParamValue{
        static_cast<ConstantSubscript>(*length), common::TypeParamAttr::Len};
  } else {
    charInfo_.length = GetParamValue(
        std::get<parser::TypeParamValue>(x.u), common::TypeParamAttr::Len);
  }
}
void DeclarationVisitor::Post(const parser::LengthSelector &x) {
  if (const auto *param{std::get_if<parser::TypeParamValue>(&x.u)}) {
    charInfo_.length = GetParamValue(*param, common::TypeParamAttr::Len);
  }
}

bool DeclarationVisitor::Pre(const parser::KindParam &x) {
  if (const auto *kind{std::get_if<
          parser::Scalar<parser::Integer<parser::Constant<parser::Name>>>>(
          &x.u)}) {
    const parser::Name &name{kind->thing.thing.thing};
    if (!FindSymbol(name)) {
      Say(name, "Parameter '%s' not found"_err_en_US);
    }
  }
  return false;
}

int DeclarationVisitor::GetVectorElementKind(
    TypeCategory category, const std::optional<parser::KindSelector> &kind) {
  KindExpr value{GetKindParamExpr(category, kind)};
  if (auto known{evaluate::ToInt64(value)}) {
    return static_cast<int>(*known);
  }
  common::die("Vector element kind must be known at compile-time");
}

bool DeclarationVisitor::Pre(const parser::VectorTypeSpec &) {
  // PowerPC vector types are allowed only on Power architectures.
  if (!currScope().context().targetCharacteristics().isPPC()) {
    Say(currStmtSource().value(),
        "Vector type is only supported for PowerPC"_err_en_US);
    isVectorType_ = false;
    return false;
  }
  isVectorType_ = true;
  return true;
}
// Create semantic::DerivedTypeSpec for Vector types here.
void DeclarationVisitor::Post(const parser::VectorTypeSpec &x) {
  llvm::StringRef typeName;
  llvm::SmallVector<ParamValue> typeParams;
  DerivedTypeSpec::Category vectorCategory;

  isVectorType_ = false;
  common::visit(
      common::visitors{
          [&](const parser::IntrinsicVectorTypeSpec &y) {
            vectorCategory = DerivedTypeSpec::Category::IntrinsicVector;
            int vecElemKind = 0;
            typeName = "__builtin_ppc_intrinsic_vector";
            common::visit(
                common::visitors{
                    [&](const parser::IntegerTypeSpec &z) {
                      vecElemKind = GetVectorElementKind(
                          TypeCategory::Integer, std::move(z.v));
                      typeParams.push_back(ParamValue(
                          static_cast<common::ConstantSubscript>(
                              common::VectorElementCategory::Integer),
                          common::TypeParamAttr::Kind));
                    },
                    [&](const parser::IntrinsicTypeSpec::Real &z) {
                      vecElemKind = GetVectorElementKind(
                          TypeCategory::Real, std::move(z.kind));
                      typeParams.push_back(
                          ParamValue(static_cast<common::ConstantSubscript>(
                                         common::VectorElementCategory::Real),
                              common::TypeParamAttr::Kind));
                    },
                    [&](const parser::UnsignedTypeSpec &z) {
                      vecElemKind = GetVectorElementKind(
                          TypeCategory::Integer, std::move(z.v));
                      typeParams.push_back(ParamValue(
                          static_cast<common::ConstantSubscript>(
                              common::VectorElementCategory::Unsigned),
                          common::TypeParamAttr::Kind));
                    },
                },
                y.v.u);
            typeParams.push_back(
                ParamValue(static_cast<common::ConstantSubscript>(vecElemKind),
                    common::TypeParamAttr::Kind));
          },
          [&](const parser::VectorTypeSpec::PairVectorTypeSpec &y) {
            vectorCategory = DerivedTypeSpec::Category::PairVector;
            typeName = "__builtin_ppc_pair_vector";
          },
          [&](const parser::VectorTypeSpec::QuadVectorTypeSpec &y) {
            vectorCategory = DerivedTypeSpec::Category::QuadVector;
            typeName = "__builtin_ppc_quad_vector";
          },
      },
      x.u);

  auto ppcBuiltinTypesScope = currScope().context().GetPPCBuiltinTypesScope();
  if (!ppcBuiltinTypesScope) {
    common::die("INTERNAL: The __ppc_types module was not found ");
  }

  auto iter{ppcBuiltinTypesScope->find(
      semantics::SourceName{typeName.data(), typeName.size()})};
  if (iter == ppcBuiltinTypesScope->cend()) {
    common::die("INTERNAL: The __ppc_types module does not define "
                "the type '%s'",
        typeName.data());
  }

  const semantics::Symbol &typeSymbol{*iter->second};
  DerivedTypeSpec vectorDerivedType{typeName.data(), typeSymbol};
  vectorDerivedType.set_category(vectorCategory);
  if (typeParams.size()) {
    vectorDerivedType.AddRawParamValue(nullptr, std::move(typeParams[0]));
    vectorDerivedType.AddRawParamValue(nullptr, std::move(typeParams[1]));
    vectorDerivedType.CookParameters(GetFoldingContext());
  }

  if (const DeclTypeSpec *
      extant{ppcBuiltinTypesScope->FindInstantiatedDerivedType(
          vectorDerivedType, DeclTypeSpec::Category::TypeDerived)}) {
    // This derived type and parameter expressions (if any) are already present
    // in the __ppc_intrinsics scope.
    SetDeclTypeSpec(*extant);
  } else {
    DeclTypeSpec &type{ppcBuiltinTypesScope->MakeDerivedType(
        DeclTypeSpec::Category::TypeDerived, std::move(vectorDerivedType))};
    DerivedTypeSpec &derived{type.derivedTypeSpec()};
    auto restorer{
        GetFoldingContext().messages().SetLocation(currStmtSource().value())};
    derived.Instantiate(*ppcBuiltinTypesScope);
    SetDeclTypeSpec(type);
  }
}

bool DeclarationVisitor::Pre(const parser::DeclarationTypeSpec::Type &) {
  CHECK(GetDeclTypeSpecCategory() == DeclTypeSpec::Category::TypeDerived);
  return true;
}

void DeclarationVisitor::Post(const parser::DeclarationTypeSpec::Type &type) {
  const parser::Name &derivedName{std::get<parser::Name>(type.derived.t)};
  if (const Symbol * derivedSymbol{derivedName.symbol}) {
    CheckForAbstractType(*derivedSymbol); // C706
  }
}

bool DeclarationVisitor::Pre(const parser::DeclarationTypeSpec::Class &) {
  SetDeclTypeSpecCategory(DeclTypeSpec::Category::ClassDerived);
  return true;
}

void DeclarationVisitor::Post(
    const parser::DeclarationTypeSpec::Class &parsedClass) {
  const auto &typeName{std::get<parser::Name>(parsedClass.derived.t)};
  if (auto spec{ResolveDerivedType(typeName)};
      spec && !IsExtensibleType(&*spec)) { // C705
    SayWithDecl(typeName, *typeName.symbol,
        "Non-extensible derived type '%s' may not be used with CLASS"
        " keyword"_err_en_US);
  }
}

void DeclarationVisitor::Post(const parser::DerivedTypeSpec &x) {
  const auto &typeName{std::get<parser::Name>(x.t)};
  auto spec{ResolveDerivedType(typeName)};
  if (!spec) {
    return;
  }
  bool seenAnyName{false};
  for (const auto &typeParamSpec :
      std::get<std::list<parser::TypeParamSpec>>(x.t)) {
    const auto &optKeyword{
        std::get<std::optional<parser::Keyword>>(typeParamSpec.t)};
    std::optional<SourceName> name;
    if (optKeyword) {
      seenAnyName = true;
      name = optKeyword->v.source;
    } else if (seenAnyName) {
      Say(typeName.source, "Type parameter value must have a name"_err_en_US);
      continue;
    }
    const auto &value{std::get<parser::TypeParamValue>(typeParamSpec.t)};
    // The expressions in a derived type specifier whose values define
    // non-defaulted type parameters are evaluated (folded) in the enclosing
    // scope.  The KIND/LEN distinction is resolved later in
    // DerivedTypeSpec::CookParameters().
    ParamValue param{GetParamValue(value, common::TypeParamAttr::Kind)};
    if (!param.isExplicit() || param.GetExplicit()) {
      spec->AddRawParamValue(
          common::GetPtrFromOptional(optKeyword), std::move(param));
    }
  }
  // The DerivedTypeSpec *spec is used initially as a search key.
  // If it turns out to have the same name and actual parameter
  // value expressions as another DerivedTypeSpec in the current
  // scope does, then we'll use that extant spec; otherwise, when this
  // spec is distinct from all derived types previously instantiated
  // in the current scope, this spec will be moved into that collection.
  const auto &dtDetails{spec->typeSymbol().get<DerivedTypeDetails>()};
  auto category{GetDeclTypeSpecCategory()};
  if (dtDetails.isForwardReferenced()) {
    DeclTypeSpec &type{currScope().MakeDerivedType(category, std::move(*spec))};
    SetDeclTypeSpec(type);
    return;
  }
  // Normalize parameters to produce a better search key.
  spec->CookParameters(GetFoldingContext());
  if (!spec->MightBeParameterized()) {
    spec->EvaluateParameters(context());
  }
  if (const DeclTypeSpec *
      extant{currScope().FindInstantiatedDerivedType(*spec, category)}) {
    // This derived type and parameter expressions (if any) are already present
    // in this scope.
    SetDeclTypeSpec(*extant);
  } else {
    DeclTypeSpec &type{currScope().MakeDerivedType(category, std::move(*spec))};
    DerivedTypeSpec &derived{type.derivedTypeSpec()};
    if (derived.MightBeParameterized() &&
        currScope().IsParameterizedDerivedType()) {
      // Defer instantiation; use the derived type's definition's scope.
      derived.set_scope(DEREF(spec->typeSymbol().scope()));
    } else if (&currScope() == spec->typeSymbol().scope()) {
      // Direct recursive use of a type in the definition of one of its
      // components: defer instantiation
    } else {
      auto restorer{
          GetFoldingContext().messages().SetLocation(currStmtSource().value())};
      derived.Instantiate(currScope());
    }
    SetDeclTypeSpec(type);
  }
  // Capture the DerivedTypeSpec in the parse tree for use in building
  // structure constructor expressions.
  x.derivedTypeSpec = &GetDeclTypeSpec()->derivedTypeSpec();
}

void DeclarationVisitor::Post(const parser::DeclarationTypeSpec::Record &rec) {
  const auto &typeName{rec.v};
  if (auto spec{ResolveDerivedType(typeName)}) {
    spec->CookParameters(GetFoldingContext());
    spec->EvaluateParameters(context());
    if (const DeclTypeSpec *
        extant{currScope().FindInstantiatedDerivedType(
            *spec, DeclTypeSpec::TypeDerived)}) {
      SetDeclTypeSpec(*extant);
    } else {
      Say(typeName.source, "%s is not a known STRUCTURE"_err_en_US,
          typeName.source);
    }
  }
}

// The descendents of DerivedTypeDef in the parse tree are visited directly
// in this Pre() routine so that recursive use of the derived type can be
// supported in the components.
bool DeclarationVisitor::Pre(const parser::DerivedTypeDef &x) {
  auto &stmt{std::get<parser::Statement<parser::DerivedTypeStmt>>(x.t)};
  Walk(stmt);
  Walk(std::get<std::list<parser::Statement<parser::TypeParamDefStmt>>>(x.t));
  auto &scope{currScope()};
  CHECK(scope.symbol());
  CHECK(scope.symbol()->scope() == &scope);
  auto &details{scope.symbol()->get<DerivedTypeDetails>()};
  std::set<SourceName> paramNames;
  for (auto &paramName : std::get<std::list<parser::Name>>(stmt.statement.t)) {
    details.add_paramName(paramName.source);
    auto *symbol{FindInScope(scope, paramName)};
    if (!symbol) {
      Say(paramName,
          "No definition found for type parameter '%s'"_err_en_US); // C742
      // No symbol for a type param.  Create one and mark it as containing an
      // error to improve subsequent semantic processing
      BeginAttrs();
      Symbol *typeParam{MakeTypeSymbol(
          paramName, TypeParamDetails{common::TypeParamAttr::Len})};
      context().SetError(*typeParam);
      EndAttrs();
    } else if (!symbol->has<TypeParamDetails>()) {
      Say2(paramName, "'%s' is not defined as a type parameter"_err_en_US,
          *symbol, "Definition of '%s'"_en_US); // C741
    }
    if (!paramNames.insert(paramName.source).second) {
      Say(paramName,
          "Duplicate type parameter name: '%s'"_err_en_US); // C731
    }
  }
  for (const auto &[name, symbol] : currScope()) {
    if (symbol->has<TypeParamDetails>() && !paramNames.count(name)) {
      SayDerivedType(name,
          "'%s' is not a type parameter of this derived type"_err_en_US,
          currScope()); // C741
    }
  }
  Walk(std::get<std::list<parser::Statement<parser::PrivateOrSequence>>>(x.t));
  const auto &componentDefs{
      std::get<std::list<parser::Statement<parser::ComponentDefStmt>>>(x.t)};
  Walk(componentDefs);
  if (derivedTypeInfo_.sequence) {
    details.set_sequence(true);
    if (componentDefs.empty()) {
      // F'2023 C745 - not enforced by any compiler
      Say(stmt.source,
          "A sequence type should have at least one component"_warn_en_US);
    }
    if (!details.paramNames().empty()) { // C740
      Say(stmt.source,
          "A sequence type may not have type parameters"_err_en_US);
    }
    if (derivedTypeInfo_.extends) { // C735
      Say(stmt.source,
          "A sequence type may not have the EXTENDS attribute"_err_en_US);
    }
  }
  Walk(std::get<std::optional<parser::TypeBoundProcedurePart>>(x.t));
  Walk(std::get<parser::Statement<parser::EndTypeStmt>>(x.t));
  details.set_isForwardReferenced(false);
  derivedTypeInfo_ = {};
  PopScope();
  return false;
}

bool DeclarationVisitor::Pre(const parser::DerivedTypeStmt &) {
  return BeginAttrs();
}
void DeclarationVisitor::Post(const parser::DerivedTypeStmt &x) {
  auto &name{std::get<parser::Name>(x.t)};
  // Resolve the EXTENDS() clause before creating the derived
  // type's symbol to foil attempts to recursively extend a type.
  auto *extendsName{derivedTypeInfo_.extends};
  std::optional<DerivedTypeSpec> extendsType{
      ResolveExtendsType(name, extendsName)};
  DerivedTypeDetails derivedTypeDetails;
  if (Symbol *typeSymbol{FindInScope(currScope(), name)}; typeSymbol &&
      typeSymbol->has<DerivedTypeDetails>() &&
      typeSymbol->get<DerivedTypeDetails>().isForwardReferenced()) {
    derivedTypeDetails.set_isForwardReferenced(true);
  }
  auto &symbol{MakeSymbol(name, GetAttrs(), std::move(derivedTypeDetails))};
  symbol.ReplaceName(name.source);
  derivedTypeInfo_.type = &symbol;
  PushScope(Scope::Kind::DerivedType, &symbol);
  if (extendsType) {
    // Declare the "parent component"; private if the type is.
    // Any symbol stored in the EXTENDS() clause is temporarily
    // hidden so that a new symbol can be created for the parent
    // component without producing spurious errors about already
    // existing.
    const Symbol &extendsSymbol{extendsType->typeSymbol()};
    auto restorer{common::ScopedSet(extendsName->symbol, nullptr)};
    if (OkToAddComponent(*extendsName, &extendsSymbol)) {
      auto &comp{DeclareEntity<ObjectEntityDetails>(*extendsName, Attrs{})};
      comp.attrs().set(
          Attr::PRIVATE, extendsSymbol.attrs().test(Attr::PRIVATE));
      comp.implicitAttrs().set(
          Attr::PRIVATE, extendsSymbol.implicitAttrs().test(Attr::PRIVATE));
      comp.set(Symbol::Flag::ParentComp);
      DeclTypeSpec &type{currScope().MakeDerivedType(
          DeclTypeSpec::TypeDerived, std::move(*extendsType))};
      type.derivedTypeSpec().set_scope(*extendsSymbol.scope());
      comp.SetType(type);
      DerivedTypeDetails &details{symbol.get<DerivedTypeDetails>()};
      details.add_component(comp);
    }
  }
  EndAttrs();
}

void DeclarationVisitor::Post(const parser::TypeParamDefStmt &x) {
  auto *type{GetDeclTypeSpec()};
  auto attr{std::get<common::TypeParamAttr>(x.t)};
  for (auto &decl : std::get<std::list<parser::TypeParamDecl>>(x.t)) {
    auto &name{std::get<parser::Name>(decl.t)};
    if (Symbol * symbol{MakeTypeSymbol(name, TypeParamDetails{attr})}) {
      SetType(name, *type);
      if (auto &init{
              std::get<std::optional<parser::ScalarIntConstantExpr>>(decl.t)}) {
        if (auto maybeExpr{EvaluateNonPointerInitializer(
                *symbol, *init, init->thing.thing.thing.value().source)}) {
          if (auto *intExpr{std::get_if<SomeIntExpr>(&maybeExpr->u)}) {
            symbol->get<TypeParamDetails>().set_init(std::move(*intExpr));
          }
        }
      }
    }
  }
  EndDecl();
}
bool DeclarationVisitor::Pre(const parser::TypeAttrSpec::Extends &x) {
  if (derivedTypeInfo_.extends) {
    Say(currStmtSource().value(),
        "Attribute 'EXTENDS' cannot be used more than once"_err_en_US);
  } else {
    derivedTypeInfo_.extends = &x.v;
  }
  return false;
}

bool DeclarationVisitor::Pre(const parser::PrivateStmt &) {
  if (!currScope().parent().IsModule()) {
    Say("PRIVATE is only allowed in a derived type that is"
        " in a module"_err_en_US); // C766
  } else if (derivedTypeInfo_.sawContains) {
    derivedTypeInfo_.privateBindings = true;
  } else if (!derivedTypeInfo_.privateComps) {
    derivedTypeInfo_.privateComps = true;
  } else { // C738
    Say("PRIVATE should not appear more than once in derived type components"_warn_en_US);
  }
  return false;
}
bool DeclarationVisitor::Pre(const parser::SequenceStmt &) {
  if (derivedTypeInfo_.sequence) { // C738
    Say("SEQUENCE should not appear more than once in derived type components"_warn_en_US);
  }
  derivedTypeInfo_.sequence = true;
  return false;
}
void DeclarationVisitor::Post(const parser::ComponentDecl &x) {
  const auto &name{std::get<parser::Name>(x.t)};
  auto attrs{GetAttrs()};
  if (derivedTypeInfo_.privateComps &&
      !attrs.HasAny({Attr::PUBLIC, Attr::PRIVATE})) {
    attrs.set(Attr::PRIVATE);
  }
  if (const auto *declType{GetDeclTypeSpec()}) {
    if (const auto *derived{declType->AsDerived()}) {
      if (!attrs.HasAny({Attr::POINTER, Attr::ALLOCATABLE})) {
        if (derivedTypeInfo_.type == &derived->typeSymbol()) { // C744
          Say("Recursive use of the derived type requires "
              "POINTER or ALLOCATABLE"_err_en_US);
        }
      }
      // TODO: This would be more appropriate in CheckDerivedType()
      if (auto it{FindCoarrayUltimateComponent(*derived)}) { // C748
        std::string ultimateName{it.BuildResultDesignatorName()};
        // Strip off the leading "%"
        if (ultimateName.length() > 1) {
          ultimateName.erase(0, 1);
          if (attrs.HasAny({Attr::POINTER, Attr::ALLOCATABLE})) {
            evaluate::AttachDeclaration(
                Say(name.source,
                    "A component with a POINTER or ALLOCATABLE attribute may "
                    "not "
                    "be of a type with a coarray ultimate component (named "
                    "'%s')"_err_en_US,
                    ultimateName),
                derived->typeSymbol());
          }
          if (!arraySpec().empty() || !coarraySpec().empty()) {
            evaluate::AttachDeclaration(
                Say(name.source,
                    "An array or coarray component may not be of a type with a "
                    "coarray ultimate component (named '%s')"_err_en_US,
                    ultimateName),
                derived->typeSymbol());
          }
        }
      }
    }
  }
  if (OkToAddComponent(name)) {
    auto &symbol{DeclareObjectEntity(name, attrs)};
    SetCUDADataAttr(name.source, symbol, cudaDataAttr());
    if (symbol.has<ObjectEntityDetails>()) {
      if (auto &init{std::get<std::optional<parser::Initialization>>(x.t)}) {
        Initialization(name, *init, true);
      }
    }
    currScope().symbol()->get<DerivedTypeDetails>().add_component(symbol);
  }
  ClearArraySpec();
  ClearCoarraySpec();
}
void DeclarationVisitor::Post(const parser::FillDecl &x) {
  // Replace "%FILL" with a distinct generated name
  const auto &name{std::get<parser::Name>(x.t)};
  const_cast<SourceName &>(name.source) = context().GetTempName(currScope());
  if (OkToAddComponent(name)) {
    auto &symbol{DeclareObjectEntity(name, GetAttrs())};
    currScope().symbol()->get<DerivedTypeDetails>().add_component(symbol);
  }
  ClearArraySpec();
}
bool DeclarationVisitor::Pre(const parser::ProcedureDeclarationStmt &x) {
  CHECK(!interfaceName_);
  const auto &procAttrSpec{std::get<std::list<parser::ProcAttrSpec>>(x.t)};
  for (const parser::ProcAttrSpec &procAttr : procAttrSpec) {
    if (auto *bindC{std::get_if<parser::LanguageBindingSpec>(&procAttr.u)}) {
      if (bindC->v.has_value()) {
        if (std::get<std::list<parser::ProcDecl>>(x.t).size() > 1) {
          Say(context().location().value(),
              "A procedure declaration statement with a binding name may not declare multiple procedures"_err_en_US);
        }
        break;
      }
    }
  }
  return BeginDecl();
}
void DeclarationVisitor::Post(const parser::ProcedureDeclarationStmt &) {
  interfaceName_ = nullptr;
  EndDecl();
}
bool DeclarationVisitor::Pre(const parser::DataComponentDefStmt &x) {
  // Overrides parse tree traversal so as to handle attributes first,
  // so POINTER & ALLOCATABLE enable forward references to derived types.
  Walk(std::get<std::list<parser::ComponentAttrSpec>>(x.t));
  set_allowForwardReferenceToDerivedType(
      GetAttrs().HasAny({Attr::POINTER, Attr::ALLOCATABLE}));
  Walk(std::get<parser::DeclarationTypeSpec>(x.t));
  set_allowForwardReferenceToDerivedType(false);
  if (derivedTypeInfo_.sequence) { // C740
    if (const auto *declType{GetDeclTypeSpec()}) {
      if (!declType->AsIntrinsic() && !declType->IsSequenceType() &&
          !InModuleFile()) {
        if (GetAttrs().test(Attr::POINTER) &&
            context().IsEnabled(common::LanguageFeature::PointerInSeqType)) {
          if (context().ShouldWarn(common::LanguageFeature::PointerInSeqType)) {
            Say("A sequence type data component that is a pointer to a non-sequence type is not standard"_port_en_US);
          }
        } else {
          Say("A sequence type data component must either be of an intrinsic type or a derived sequence type"_err_en_US);
        }
      }
    }
  }
  Walk(std::get<std::list<parser::ComponentOrFill>>(x.t));
  return false;
}
bool DeclarationVisitor::Pre(const parser::ProcComponentDefStmt &) {
  CHECK(!interfaceName_);
  return true;
}
void DeclarationVisitor::Post(const parser::ProcComponentDefStmt &) {
  interfaceName_ = nullptr;
}
bool DeclarationVisitor::Pre(const parser::ProcPointerInit &x) {
  if (auto *name{std::get_if<parser::Name>(&x.u)}) {
    return !NameIsKnownOrIntrinsic(*name) && !CheckUseError(*name);
  } else {
    const auto &null{DEREF(std::get_if<parser::NullInit>(&x.u))};
    Walk(null);
    if (auto nullInit{EvaluateExpr(null)}) {
      if (!evaluate::IsNullPointer(*nullInit)) {
        Say(null.v.value().source,
            "Procedure pointer initializer must be a name or intrinsic NULL()"_err_en_US);
      }
    }
    return false;
  }
}
void DeclarationVisitor::Post(const parser::ProcInterface &x) {
  if (auto *name{std::get_if<parser::Name>(&x.u)}) {
    interfaceName_ = name;
    NoteInterfaceName(*name);
  }
}
void DeclarationVisitor::Post(const parser::ProcDecl &x) {
  const auto &name{std::get<parser::Name>(x.t)};
  // Don't use BypassGeneric or GetUltimate on this symbol, they can
  // lead to unusable names in module files.
  const Symbol *procInterface{
      interfaceName_ ? interfaceName_->symbol : nullptr};
  auto attrs{HandleSaveName(name.source, GetAttrs())};
  DerivedTypeDetails *dtDetails{nullptr};
  if (Symbol * symbol{currScope().symbol()}) {
    dtDetails = symbol->detailsIf<DerivedTypeDetails>();
  }
  if (!dtDetails) {
    attrs.set(Attr::EXTERNAL);
  }
  Symbol &symbol{DeclareProcEntity(name, attrs, procInterface)};
  SetCUDADataAttr(name.source, symbol, cudaDataAttr()); // for error
  symbol.ReplaceName(name.source);
  if (dtDetails) {
    dtDetails->add_component(symbol);
  }
  DeclaredPossibleSpecificProc(symbol);
}

bool DeclarationVisitor::Pre(const parser::TypeBoundProcedurePart &) {
  derivedTypeInfo_.sawContains = true;
  return true;
}

// Resolve binding names from type-bound generics, saved in genericBindings_.
void DeclarationVisitor::Post(const parser::TypeBoundProcedurePart &) {
  // track specifics seen for the current generic to detect duplicates:
  const Symbol *currGeneric{nullptr};
  std::set<SourceName> specifics;
  for (const auto &[generic, bindingName] : genericBindings_) {
    if (generic != currGeneric) {
      currGeneric = generic;
      specifics.clear();
    }
    auto [it, inserted]{specifics.insert(bindingName->source)};
    if (!inserted) {
      Say(*bindingName, // C773
          "Binding name '%s' was already specified for generic '%s'"_err_en_US,
          bindingName->source, generic->name())
          .Attach(*it, "Previous specification of '%s'"_en_US, *it);
      continue;
    }
    auto *symbol{FindInTypeOrParents(*bindingName)};
    if (!symbol) {
      Say(*bindingName, // C772
          "Binding name '%s' not found in this derived type"_err_en_US);
    } else if (!symbol->has<ProcBindingDetails>()) {
      SayWithDecl(*bindingName, *symbol, // C772
          "'%s' is not the name of a specific binding of this type"_err_en_US);
    } else {
      generic->get<GenericDetails>().AddSpecificProc(
          *symbol, bindingName->source);
    }
  }
  genericBindings_.clear();
}

void DeclarationVisitor::Post(const parser::ContainsStmt &) {
  if (derivedTypeInfo_.sequence) {
    Say("A sequence type may not have a CONTAINS statement"_err_en_US); // C740
  }
}

void DeclarationVisitor::Post(
    const parser::TypeBoundProcedureStmt::WithoutInterface &x) {
  if (GetAttrs().test(Attr::DEFERRED)) { // C783
    Say("DEFERRED is only allowed when an interface-name is provided"_err_en_US);
  }
  for (auto &declaration : x.declarations) {
    auto &bindingName{std::get<parser::Name>(declaration.t)};
    auto &optName{std::get<std::optional<parser::Name>>(declaration.t)};
    const parser::Name &procedureName{optName ? *optName : bindingName};
    Symbol *procedure{FindSymbol(procedureName)};
    if (!procedure) {
      procedure = NoteInterfaceName(procedureName);
    }
    if (procedure) {
      const Symbol &bindTo{BypassGeneric(*procedure)};
      if (auto *s{MakeTypeSymbol(bindingName, ProcBindingDetails{bindTo})}) {
        SetPassNameOn(*s);
        if (GetAttrs().test(Attr::DEFERRED)) {
          context().SetError(*s);
        }
      }
    }
  }
}

void DeclarationVisitor::CheckBindings(
    const parser::TypeBoundProcedureStmt::WithoutInterface &tbps) {
  CHECK(currScope().IsDerivedType());
  for (auto &declaration : tbps.declarations) {
    auto &bindingName{std::get<parser::Name>(declaration.t)};
    if (Symbol * binding{FindInScope(bindingName)}) {
      if (auto *details{binding->detailsIf<ProcBindingDetails>()}) {
        const Symbol &ultimate{details->symbol().GetUltimate()};
        const Symbol &procedure{BypassGeneric(ultimate)};
        if (&procedure != &ultimate) {
          details->ReplaceSymbol(procedure);
        }
        if (!CanBeTypeBoundProc(procedure)) {
          if (details->symbol().name() != binding->name()) {
            Say(binding->name(),
                "The binding of '%s' ('%s') must be either an accessible "
                "module procedure or an external procedure with "
                "an explicit interface"_err_en_US,
                binding->name(), details->symbol().name());
          } else {
            Say(binding->name(),
                "'%s' must be either an accessible module procedure "
                "or an external procedure with an explicit interface"_err_en_US,
                binding->name());
          }
          context().SetError(*binding);
        }
      }
    }
  }
}

void DeclarationVisitor::Post(
    const parser::TypeBoundProcedureStmt::WithInterface &x) {
  if (!GetAttrs().test(Attr::DEFERRED)) { // C783
    Say("DEFERRED is required when an interface-name is provided"_err_en_US);
  }
  if (Symbol * interface{NoteInterfaceName(x.interfaceName)}) {
    for (auto &bindingName : x.bindingNames) {
      if (auto *s{
              MakeTypeSymbol(bindingName, ProcBindingDetails{*interface})}) {
        SetPassNameOn(*s);
        if (!GetAttrs().test(Attr::DEFERRED)) {
          context().SetError(*s);
        }
      }
    }
  }
}

bool DeclarationVisitor::Pre(const parser::FinalProcedureStmt &x) {
  if (currScope().IsDerivedType() && currScope().symbol()) {
    if (auto *details{currScope().symbol()->detailsIf<DerivedTypeDetails>()}) {
      for (const auto &subrName : x.v) {
        Symbol *symbol{FindSymbol(subrName)};
        if (!symbol) {
          // FINAL procedures must be module subroutines
          symbol = &MakeSymbol(
              currScope().parent(), subrName.source, Attrs{Attr::MODULE});
          Resolve(subrName, symbol);
          symbol->set_details(ProcEntityDetails{});
          symbol->set(Symbol::Flag::Subroutine);
        }
        if (auto pair{details->finals().emplace(subrName.source, *symbol)};
            !pair.second) { // C787
          Say(subrName.source,
              "FINAL subroutine '%s' already appeared in this derived type"_err_en_US,
              subrName.source)
              .Attach(pair.first->first,
                  "earlier appearance of this FINAL subroutine"_en_US);
        }
      }
    }
  }
  return false;
}

bool DeclarationVisitor::Pre(const parser::TypeBoundGenericStmt &x) {
  const auto &accessSpec{std::get<std::optional<parser::AccessSpec>>(x.t)};
  const auto &genericSpec{std::get<Indirection<parser::GenericSpec>>(x.t)};
  const auto &bindingNames{std::get<std::list<parser::Name>>(x.t)};
  GenericSpecInfo info{genericSpec.value()};
  SourceName symbolName{info.symbolName()};
  bool isPrivate{accessSpec ? accessSpec->v == parser::AccessSpec::Kind::Private
                            : derivedTypeInfo_.privateBindings};
  auto *genericSymbol{FindInScope(symbolName)};
  if (genericSymbol) {
    if (!genericSymbol->has<GenericDetails>()) {
      genericSymbol = nullptr; // MakeTypeSymbol will report the error below
    }
  } else {
    // look in ancestor types for a generic of the same name
    for (const auto &name : GetAllNames(context(), symbolName)) {
      if (Symbol * inherited{currScope().FindComponent(SourceName{name})}) {
        if (inherited->has<GenericDetails>()) {
          CheckAccessibility(symbolName, isPrivate, *inherited); // C771
        } else {
          Say(symbolName,
              "Type bound generic procedure '%s' may not have the same name as a non-generic symbol inherited from an ancestor type"_err_en_US)
              .Attach(inherited->name(), "Inherited symbol"_en_US);
        }
        break;
      }
    }
  }
  if (genericSymbol) {
    CheckAccessibility(symbolName, isPrivate, *genericSymbol); // C771
  } else {
    genericSymbol = MakeTypeSymbol(symbolName, GenericDetails{});
    if (!genericSymbol) {
      return false;
    }
    if (isPrivate) {
      SetExplicitAttr(*genericSymbol, Attr::PRIVATE);
    }
  }
  for (const parser::Name &bindingName : bindingNames) {
    genericBindings_.emplace(genericSymbol, &bindingName);
  }
  info.Resolve(genericSymbol);
  return false;
}

// DEC STRUCTUREs are handled thus to allow for nested definitions.
bool DeclarationVisitor::Pre(const parser::StructureDef &def) {
  const auto &structureStatement{
      std::get<parser::Statement<parser::StructureStmt>>(def.t)};
  auto saveDerivedTypeInfo{derivedTypeInfo_};
  derivedTypeInfo_ = {};
  derivedTypeInfo_.isStructure = true;
  derivedTypeInfo_.sequence = true;
  Scope *previousStructure{nullptr};
  if (saveDerivedTypeInfo.isStructure) {
    previousStructure = &currScope();
    PopScope();
  }
  const parser::StructureStmt &structStmt{structureStatement.statement};
  const auto &name{std::get<std::optional<parser::Name>>(structStmt.t)};
  if (!name) {
    // Construct a distinct generated name for an anonymous structure
    auto &mutableName{const_cast<std::optional<parser::Name> &>(name)};
    mutableName.emplace(
        parser::Name{context().GetTempName(currScope()), nullptr});
  }
  auto &symbol{MakeSymbol(*name, DerivedTypeDetails{})};
  symbol.ReplaceName(name->source);
  symbol.get<DerivedTypeDetails>().set_sequence(true);
  symbol.get<DerivedTypeDetails>().set_isDECStructure(true);
  derivedTypeInfo_.type = &symbol;
  PushScope(Scope::Kind::DerivedType, &symbol);
  const auto &fields{std::get<std::list<parser::StructureField>>(def.t)};
  Walk(fields);
  PopScope();
  // Complete the definition
  DerivedTypeSpec derivedTypeSpec{symbol.name(), symbol};
  derivedTypeSpec.set_scope(DEREF(symbol.scope()));
  derivedTypeSpec.CookParameters(GetFoldingContext());
  derivedTypeSpec.EvaluateParameters(context());
  DeclTypeSpec &type{currScope().MakeDerivedType(
      DeclTypeSpec::TypeDerived, std::move(derivedTypeSpec))};
  type.derivedTypeSpec().Instantiate(currScope());
  // Restore previous structure definition context, if any
  derivedTypeInfo_ = saveDerivedTypeInfo;
  if (previousStructure) {
    PushScope(*previousStructure);
  }
  // Handle any entity declarations on the STRUCTURE statement
  const auto &decls{std::get<std::list<parser::EntityDecl>>(structStmt.t)};
  if (!decls.empty()) {
    BeginDecl();
    SetDeclTypeSpec(type);
    Walk(decls);
    EndDecl();
  }
  return false;
}

bool DeclarationVisitor::Pre(const parser::Union::UnionStmt &) {
  Say("support for UNION"_todo_en_US); // TODO
  return true;
}

bool DeclarationVisitor::Pre(const parser::StructureField &x) {
  if (std::holds_alternative<parser::Statement<parser::DataComponentDefStmt>>(
          x.u)) {
    BeginDecl();
  }
  return true;
}

void DeclarationVisitor::Post(const parser::StructureField &x) {
  if (std::holds_alternative<parser::Statement<parser::DataComponentDefStmt>>(
          x.u)) {
    EndDecl();
  }
}

bool DeclarationVisitor::Pre(const parser::AllocateStmt &) {
  BeginDeclTypeSpec();
  return true;
}
void DeclarationVisitor::Post(const parser::AllocateStmt &) {
  EndDeclTypeSpec();
}

bool DeclarationVisitor::Pre(const parser::StructureConstructor &x) {
  auto &parsedType{std::get<parser::DerivedTypeSpec>(x.t)};
  const DeclTypeSpec *type{ProcessTypeSpec(parsedType)};
  if (!type) {
    return false;
  }
  const DerivedTypeSpec *spec{type->AsDerived()};
  const Scope *typeScope{spec ? spec->scope() : nullptr};
  if (!typeScope) {
    return false;
  }

  // N.B C7102 is implicitly enforced by having inaccessible types not
  // being found in resolution.
  // More constraints are enforced in expression.cpp so that they
  // can apply to structure constructors that have been converted
  // from misparsed function references.
  for (const auto &component :
      std::get<std::list<parser::ComponentSpec>>(x.t)) {
    // Visit the component spec expression, but not the keyword, since
    // we need to resolve its symbol in the scope of the derived type.
    Walk(std::get<parser::ComponentDataSource>(component.t));
    if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) {
      FindInTypeOrParents(*typeScope, kw->v);
    }
  }
  return false;
}

bool DeclarationVisitor::Pre(const parser::BasedPointer &) {
  BeginArraySpec();
  return true;
}

void DeclarationVisitor::Post(const parser::BasedPointer &bp) {
  const parser::ObjectName &pointerName{std::get<0>(bp.t)};
  auto *pointer{FindSymbol(pointerName)};
  if (!pointer) {
    pointer = &MakeSymbol(pointerName, ObjectEntityDetails{});
  } else if (!ConvertToObjectEntity(*pointer)) {
    SayWithDecl(pointerName, *pointer, "'%s' is not a variable"_err_en_US);
  } else if (IsNamedConstant(*pointer)) {
    SayWithDecl(pointerName, *pointer,
        "'%s' is a named constant and may not be a Cray pointer"_err_en_US);
  } else if (pointer->Rank() > 0) {
    SayWithDecl(
        pointerName, *pointer, "Cray pointer '%s' must be a scalar"_err_en_US);
  } else if (pointer->test(Symbol::Flag::CrayPointee)) {
    Say(pointerName,
        "'%s' cannot be a Cray pointer as it is already a Cray pointee"_err_en_US);
  }
  pointer->set(Symbol::Flag::CrayPointer);
  const DeclTypeSpec &pointerType{MakeNumericType(
      TypeCategory::Integer, context().defaultKinds().subscriptIntegerKind())};
  const auto *type{pointer->GetType()};
  if (!type) {
    pointer->SetType(pointerType);
  } else if (*type != pointerType) {
    Say(pointerName.source, "Cray pointer '%s' must have type %s"_err_en_US,
        pointerName.source, pointerType.AsFortran());
  }
  const parser::ObjectName &pointeeName{std::get<1>(bp.t)};
  DeclareObjectEntity(pointeeName);
  if (Symbol * pointee{pointeeName.symbol}) {
    if (!ConvertToObjectEntity(*pointee)) {
      return;
    }
    if (IsNamedConstant(*pointee)) {
      Say(pointeeName,
          "'%s' is a named constant and may not be a Cray pointee"_err_en_US);
      return;
    }
    if (pointee->test(Symbol::Flag::CrayPointer)) {
      Say(pointeeName,
          "'%s' cannot be a Cray pointee as it is already a Cray pointer"_err_en_US);
    } else if (pointee->test(Symbol::Flag::CrayPointee)) {
      Say(pointeeName, "'%s' was already declared as a Cray pointee"_err_en_US);
    } else {
      pointee->set(Symbol::Flag::CrayPointee);
    }
    if (const auto *pointeeType{pointee->GetType()}) {
      if (const auto *derived{pointeeType->AsDerived()}) {
        if (!IsSequenceOrBindCType(derived)) {
          Say(pointeeName,
              "Type of Cray pointee '%s' is a derived type that is neither SEQUENCE nor BIND(C)"_warn_en_US);
        }
      }
    }
    currScope().add_crayPointer(pointeeName.source, *pointer);
  }
}

bool DeclarationVisitor::Pre(const parser::NamelistStmt::Group &x) {
  if (!CheckNotInBlock("NAMELIST")) { // C1107
    return false;
  }
  const auto &groupName{std::get<parser::Name>(x.t)};
  auto *groupSymbol{FindInScope(groupName)};
  if (!groupSymbol || !groupSymbol->has<NamelistDetails>()) {
    groupSymbol = &MakeSymbol(groupName, NamelistDetails{});
    groupSymbol->ReplaceName(groupName.source);
  }
  // Name resolution of group items is deferred to FinishNamelists()
  // so that host association is handled correctly.
  GetDeferredDeclarationState(true)->namelistGroups.emplace_back(&x);
  return false;
}

void DeclarationVisitor::FinishNamelists() {
  if (auto *deferred{GetDeferredDeclarationState()}) {
    for (const parser::NamelistStmt::Group *group : deferred->namelistGroups) {
      if (auto *groupSymbol{FindInScope(std::get<parser::Name>(group->t))}) {
        if (auto *details{groupSymbol->detailsIf<NamelistDetails>()}) {
          for (const auto &name : std::get<std::list<parser::Name>>(group->t)) {
            auto *symbol{FindSymbol(name)};
            if (!symbol) {
              symbol = &MakeSymbol(name, ObjectEntityDetails{});
              ApplyImplicitRules(*symbol);
            } else if (!ConvertToObjectEntity(symbol->GetUltimate())) {
              SayWithDecl(name, *symbol, "'%s' is not a variable"_err_en_US);
              context().SetError(*groupSymbol);
            }
            symbol->GetUltimate().set(Symbol::Flag::InNamelist);
            details->add_object(*symbol);
          }
        }
      }
    }
    deferred->namelistGroups.clear();
  }
}

bool DeclarationVisitor::Pre(const parser::IoControlSpec &x) {
  if (const auto *name{std::get_if<parser::Name>(&x.u)}) {
    auto *symbol{FindSymbol(*name)};
    if (!symbol) {
      Say(*name, "Namelist group '%s' not found"_err_en_US);
    } else if (!symbol->GetUltimate().has<NamelistDetails>()) {
      SayWithDecl(
          *name, *symbol, "'%s' is not the name of a namelist group"_err_en_US);
    }
  }
  return true;
}

bool DeclarationVisitor::Pre(const parser::CommonStmt::Block &x) {
  CheckNotInBlock("COMMON"); // C1107
  return true;
}

bool DeclarationVisitor::Pre(const parser::CommonBlockObject &) {
  BeginArraySpec();
  return true;
}

void DeclarationVisitor::Post(const parser::CommonBlockObject &x) {
  const auto &name{std::get<parser::Name>(x.t)};
  DeclareObjectEntity(name);
  auto pair{specPartState_.commonBlockObjects.insert(name.source)};
  if (!pair.second) {
    const SourceName &prev{*pair.first};
    Say2(name.source, "'%s' is already in a COMMON block"_err_en_US, prev,
        "Previous occurrence of '%s' in a COMMON block"_en_US);
  }
}

bool DeclarationVisitor::Pre(const parser::EquivalenceStmt &x) {
  // save equivalence sets to be processed after specification part
  if (CheckNotInBlock("EQUIVALENCE")) { // C1107
    for (const std::list<parser::EquivalenceObject> &set : x.v) {
      specPartState_.equivalenceSets.push_back(&set);
    }
  }
  return false; // don't implicitly declare names yet
}

void DeclarationVisitor::CheckEquivalenceSets() {
  EquivalenceSets equivSets{context()};
  inEquivalenceStmt_ = true;
  for (const auto *set : specPartState_.equivalenceSets) {
    const auto &source{set->front().v.value().source};
    if (set->size() <= 1) { // R871
      Say(source, "Equivalence set must have more than one object"_err_en_US);
    }
    for (const parser::EquivalenceObject &object : *set) {
      const auto &designator{object.v.value()};
      // The designator was not resolved when it was encountered so do it now.
      // AnalyzeExpr causes array sections to be changed to substrings as needed
      Walk(designator);
      if (AnalyzeExpr(context(), designator)) {
        equivSets.AddToSet(designator);
      }
    }
    equivSets.FinishSet(source);
  }
  inEquivalenceStmt_ = false;
  for (auto &set : equivSets.sets()) {
    if (!set.empty()) {
      currScope().add_equivalenceSet(std::move(set));
    }
  }
  specPartState_.equivalenceSets.clear();
}

bool DeclarationVisitor::Pre(const parser::SaveStmt &x) {
  if (x.v.empty()) {
    specPartState_.saveInfo.saveAll = currStmtSource();
    currScope().set_hasSAVE();
  } else {
    for (const parser::SavedEntity &y : x.v) {
      auto kind{std::get<parser::SavedEntity::Kind>(y.t)};
      const auto &name{std::get<parser::Name>(y.t)};
      if (kind == parser::SavedEntity::Kind::Common) {
        MakeCommonBlockSymbol(name);
        AddSaveName(specPartState_.saveInfo.commons, name.source);
      } else {
        HandleAttributeStmt(Attr::SAVE, name);
      }
    }
  }
  return false;
}

void DeclarationVisitor::CheckSaveStmts() {
  for (const SourceName &name : specPartState_.saveInfo.entities) {
    auto *symbol{FindInScope(name)};
    if (!symbol) {
      // error was reported
    } else if (specPartState_.saveInfo.saveAll) {
      // C889 - note that pgi, ifort, xlf do not enforce this constraint
      Say2(name,
          "Explicit SAVE of '%s' is redundant due to global SAVE statement"_warn_en_US,
          *specPartState_.saveInfo.saveAll, "Global SAVE statement"_en_US);
    } else if (!IsSaved(*symbol)) {
      SetExplicitAttr(*symbol, Attr::SAVE);
    }
  }
  for (const SourceName &name : specPartState_.saveInfo.commons) {
    if (auto *symbol{currScope().FindCommonBlock(name)}) {
      auto &objects{symbol->get<CommonBlockDetails>().objects()};
      if (objects.empty()) {
        if (currScope().kind() != Scope::Kind::BlockConstruct) {
          Say(name,
              "'%s' appears as a COMMON block in a SAVE statement but not in"
              " a COMMON statement"_err_en_US);
        } else { // C1108
          Say(name,
              "SAVE statement in BLOCK construct may not contain a"
              " common block name '%s'"_err_en_US);
        }
      } else {
        for (auto &object : symbol->get<CommonBlockDetails>().objects()) {
          if (!IsSaved(*object)) {
            SetImplicitAttr(*object, Attr::SAVE);
          }
        }
      }
    }
  }
  specPartState_.saveInfo = {};
}

// Record SAVEd names in specPartState_.saveInfo.entities.
Attrs DeclarationVisitor::HandleSaveName(const SourceName &name, Attrs attrs) {
  if (attrs.test(Attr::SAVE)) {
    AddSaveName(specPartState_.saveInfo.entities, name);
  }
  return attrs;
}

// Record a name in a set of those to be saved.
void DeclarationVisitor::AddSaveName(
    std::set<SourceName> &set, const SourceName &name) {
  auto pair{set.insert(name)};
  if (!pair.second) {
    Say2(name, "SAVE attribute was already specified on '%s'"_warn_en_US,
        *pair.first, "Previous specification of SAVE attribute"_en_US);
  }
}

// Check types of common block objects, now that they are known.
void DeclarationVisitor::CheckCommonBlocks() {
  // check for empty common blocks
  for (const auto &pair : currScope().commonBlocks()) {
    const auto &symbol{*pair.second};
    if (symbol.get<CommonBlockDetails>().objects().empty() &&
        symbol.attrs().test(Attr::BIND_C)) {
      Say(symbol.name(),
          "'%s' appears as a COMMON block in a BIND statement but not in"
          " a COMMON statement"_err_en_US);
    }
  }
  // check objects in common blocks
  for (const auto &name : specPartState_.commonBlockObjects) {
    const auto *symbol{currScope().FindSymbol(name)};
    if (!symbol) {
      continue;
    }
    const auto &attrs{symbol->attrs()};
    if (attrs.test(Attr::ALLOCATABLE)) {
      Say(name,
          "ALLOCATABLE object '%s' may not appear in a COMMON block"_err_en_US);
    } else if (attrs.test(Attr::BIND_C)) {
      Say(name,
          "Variable '%s' with BIND attribute may not appear in a COMMON block"_err_en_US);
    } else if (IsNamedConstant(*symbol)) {
      Say(name,
          "A named constant '%s' may not appear in a COMMON block"_err_en_US);
    } else if (IsDummy(*symbol)) {
      Say(name,
          "Dummy argument '%s' may not appear in a COMMON block"_err_en_US);
    } else if (symbol->IsFuncResult()) {
      Say(name,
          "Function result '%s' may not appear in a COMMON block"_err_en_US);
    } else if (const DeclTypeSpec * type{symbol->GetType()}) {
      if (type->category() == DeclTypeSpec::ClassStar) {
        Say(name,
            "Unlimited polymorphic pointer '%s' may not appear in a COMMON block"_err_en_US);
      } else if (const auto *derived{type->AsDerived()}) {
        if (!IsSequenceOrBindCType(derived)) {
          Say(name,
              "Derived type '%s' in COMMON block must have the BIND or"
              " SEQUENCE attribute"_err_en_US);
        }
        UnorderedSymbolSet typeSet;
        CheckCommonBlockDerivedType(name, derived->typeSymbol(), typeSet);
      }
    }
  }
  specPartState_.commonBlockObjects = {};
}

Symbol &DeclarationVisitor::MakeCommonBlockSymbol(const parser::Name &name) {
  return Resolve(name, currScope().MakeCommonBlock(name.source));
}
Symbol &DeclarationVisitor::MakeCommonBlockSymbol(
    const std::optional<parser::Name> &name) {
  if (name) {
    return MakeCommonBlockSymbol(*name);
  } else {
    return MakeCommonBlockSymbol(parser::Name{});
  }
}

bool DeclarationVisitor::NameIsKnownOrIntrinsic(const parser::Name &name) {
  return FindSymbol(name) || HandleUnrestrictedSpecificIntrinsicFunction(name);
}

// Check if this derived type can be in a COMMON block.
void DeclarationVisitor::CheckCommonBlockDerivedType(const SourceName &name,
    const Symbol &typeSymbol, UnorderedSymbolSet &typeSet) {
  if (auto iter{typeSet.find(SymbolRef{typeSymbol})}; iter != typeSet.end()) {
    return;
  }
  typeSet.emplace(typeSymbol);
  if (const auto *scope{typeSymbol.scope()}) {
    for (const auto &pair : *scope) {
      const Symbol &component{*pair.second};
      if (component.attrs().test(Attr::ALLOCATABLE)) {
        Say2(name,
            "Derived type variable '%s' may not appear in a COMMON block"
            " due to ALLOCATABLE component"_err_en_US,
            component.name(), "Component with ALLOCATABLE attribute"_en_US);
        return;
      }
      const auto *details{component.detailsIf<ObjectEntityDetails>()};
      if (component.test(Symbol::Flag::InDataStmt) ||
          (details && details->init())) {
        Say2(name,
            "Derived type variable '%s' may not appear in a COMMON block due to component with default initialization"_err_en_US,
            component.name(), "Component with default initialization"_en_US);
        return;
      }
      if (details) {
        if (const auto *type{details->type()}) {
          if (const auto *derived{type->AsDerived()}) {
            const Symbol &derivedTypeSymbol{derived->typeSymbol()};
            CheckCommonBlockDerivedType(name, derivedTypeSymbol, typeSet);
          }
        }
      }
    }
  }
}

bool DeclarationVisitor::HandleUnrestrictedSpecificIntrinsicFunction(
    const parser::Name &name) {
  if (auto interface{context().intrinsics().IsSpecificIntrinsicFunction(
          name.source.ToString())}) {
    // Unrestricted specific intrinsic function names (e.g., "cos")
    // are acceptable as procedure interfaces.  The presence of the
    // INTRINSIC flag will cause this symbol to have a complete interface
    // recreated for it later on demand, but capturing its result type here
    // will make GetType() return a correct result without having to
    // probe the intrinsics table again.
    Symbol &symbol{MakeSymbol(InclusiveScope(), name.source, Attrs{})};
    SetImplicitAttr(symbol, Attr::INTRINSIC);
    CHECK(interface->functionResult.has_value());
    evaluate::DynamicType dyType{
        DEREF(interface->functionResult->GetTypeAndShape()).type()};
    CHECK(common::IsNumericTypeCategory(dyType.category()));
    const DeclTypeSpec &typeSpec{
        MakeNumericType(dyType.category(), dyType.kind())};
    ProcEntityDetails details;
    details.set_type(typeSpec);
    symbol.set_details(std::move(details));
    symbol.set(Symbol::Flag::Function);
    if (interface->IsElemental()) {
      SetExplicitAttr(symbol, Attr::ELEMENTAL);
    }
    if (interface->IsPure()) {
      SetExplicitAttr(symbol, Attr::PURE);
    }
    Resolve(name, symbol);
    return true;
  } else {
    return false;
  }
}

// Checks for all locality-specs: LOCAL, LOCAL_INIT, and SHARED
bool DeclarationVisitor::PassesSharedLocalityChecks(
    const parser::Name &name, Symbol &symbol) {
  if (!IsVariableName(symbol)) {
    SayLocalMustBeVariable(name, symbol); // C1124
    return false;
  }
  if (symbol.owner() == currScope()) { // C1125 and C1126
    SayAlreadyDeclared(name, symbol);
    return false;
  }
  return true;
}

// Checks for locality-specs LOCAL and LOCAL_INIT
bool DeclarationVisitor::PassesLocalityChecks(
    const parser::Name &name, Symbol &symbol) {
  if (IsAllocatable(symbol)) { // C1128
    SayWithDecl(name, symbol,
        "ALLOCATABLE variable '%s' not allowed in a locality-spec"_err_en_US);
    return false;
  }
  if (IsOptional(symbol)) { // C1128
    SayWithDecl(name, symbol,
        "OPTIONAL argument '%s' not allowed in a locality-spec"_err_en_US);
    return false;
  }
  if (IsIntentIn(symbol)) { // C1128
    SayWithDecl(name, symbol,
        "INTENT IN argument '%s' not allowed in a locality-spec"_err_en_US);
    return false;
  }
  if (IsFinalizable(symbol)) { // C1128
    SayWithDecl(name, symbol,
        "Finalizable variable '%s' not allowed in a locality-spec"_err_en_US);
    return false;
  }
  if (evaluate::IsCoarray(symbol)) { // C1128
    SayWithDecl(
        name, symbol, "Coarray '%s' not allowed in a locality-spec"_err_en_US);
    return false;
  }
  if (const DeclTypeSpec * type{symbol.GetType()}) {
    if (type->IsPolymorphic() && IsDummy(symbol) &&
        !IsPointer(symbol)) { // C1128
      SayWithDecl(name, symbol,
          "Nonpointer polymorphic argument '%s' not allowed in a "
          "locality-spec"_err_en_US);
      return false;
    }
  }
  if (IsAssumedSizeArray(symbol)) { // C1128
    SayWithDecl(name, symbol,
        "Assumed size array '%s' not allowed in a locality-spec"_err_en_US);
    return false;
  }
  if (std::optional<Message> whyNot{WhyNotDefinable(
          name.source, currScope(), DefinabilityFlags{}, symbol)}) {
    SayWithReason(name, symbol,
        "'%s' may not appear in a locality-spec because it is not "
        "definable"_err_en_US,
        std::move(*whyNot));
    return false;
  }
  return PassesSharedLocalityChecks(name, symbol);
}

Symbol &DeclarationVisitor::FindOrDeclareEnclosingEntity(
    const parser::Name &name) {
  Symbol *prev{FindSymbol(name)};
  if (!prev) {
    // Declare the name as an object in the enclosing scope so that
    // the name can't be repurposed there later as something else.
    prev = &MakeSymbol(InclusiveScope(), name.source, Attrs{});
    ConvertToObjectEntity(*prev);
    ApplyImplicitRules(*prev);
  }
  return *prev;
}

Symbol *DeclarationVisitor::DeclareLocalEntity(const parser::Name &name) {
  Symbol &prev{FindOrDeclareEnclosingEntity(name)};
  if (!PassesLocalityChecks(name, prev)) {
    return nullptr;
  }
  return &MakeHostAssocSymbol(name, prev);
}

Symbol *DeclarationVisitor::DeclareStatementEntity(
    const parser::DoVariable &doVar,
    const std::optional<parser::IntegerTypeSpec> &type) {
  const parser::Name &name{doVar.thing.thing};
  const DeclTypeSpec *declTypeSpec{nullptr};
  if (auto *prev{FindSymbol(name)}) {
    if (prev->owner() == currScope()) {
      SayAlreadyDeclared(name, *prev);
      return nullptr;
    }
    name.symbol = nullptr;
    declTypeSpec = prev->GetType();
  }
  Symbol &symbol{DeclareEntity<ObjectEntityDetails>(name, {})};
  if (!symbol.has<ObjectEntityDetails>()) {
    return nullptr; // error was reported in DeclareEntity
  }
  if (type) {
    declTypeSpec = ProcessTypeSpec(*type);
  }
  if (declTypeSpec) {
    // Subtlety: Don't let a "*length" specifier (if any is pending) affect the
    // declaration of this implied DO loop control variable.
    auto restorer{
        common::ScopedSet(charInfo_.length, std::optional<ParamValue>{})};
    SetType(name, *declTypeSpec);
  } else {
    ApplyImplicitRules(symbol);
  }
  Symbol *result{Resolve(name, &symbol)};
  AnalyzeExpr(context(), doVar); // enforce INTEGER type
  return result;
}

// Set the type of an entity or report an error.
void DeclarationVisitor::SetType(
    const parser::Name &name, const DeclTypeSpec &type) {
  CHECK(name.symbol);
  auto &symbol{*name.symbol};
  if (charInfo_.length) { // Declaration has "*length" (R723)
    auto length{std::move(*charInfo_.length)};
    charInfo_.length.reset();
    if (type.category() == DeclTypeSpec::Character) {
      auto kind{type.characterTypeSpec().kind()};
      // Recurse with correct type.
      SetType(name,
          currScope().MakeCharacterType(std::move(length), std::move(kind)));
      return;
    } else { // C753
      Say(name,
          "A length specifier cannot be used to declare the non-character entity '%s'"_err_en_US);
    }
  }
  if (auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {
    if (proc->procInterface()) {
      Say(name,
          "'%s' has an explicit interface and may not also have a type"_err_en_US);
      context().SetError(symbol);
      return;
    }
  }
  auto *prevType{symbol.GetType()};
  if (!prevType) {
    if (symbol.test(Symbol::Flag::InDataStmt) && isImplicitNoneType() &&
        context().ShouldWarn(
            common::LanguageFeature::ForwardRefImplicitNoneData)) {
      Say(name,
          "'%s' appeared in a DATA statement before its type was declared under IMPLICIT NONE(TYPE)"_port_en_US);
    }
    symbol.SetType(type);
  } else if (symbol.has<UseDetails>()) {
    // error recovery case, redeclaration of use-associated name
  } else if (HadForwardRef(symbol)) {
    // error recovery after use of host-associated name
  } else if (!symbol.test(Symbol::Flag::Implicit)) {
    SayWithDecl(
        name, symbol, "The type of '%s' has already been declared"_err_en_US);
    context().SetError(symbol);
  } else if (type != *prevType) {
    SayWithDecl(name, symbol,
        "The type of '%s' has already been implicitly declared"_err_en_US);
    context().SetError(symbol);
  } else {
    symbol.set(Symbol::Flag::Implicit, false);
  }
}

std::optional<DerivedTypeSpec> DeclarationVisitor::ResolveDerivedType(
    const parser::Name &name) {
  Scope &outer{NonDerivedTypeScope()};
  Symbol *symbol{FindSymbol(outer, name)};
  Symbol *ultimate{symbol ? &symbol->GetUltimate() : nullptr};
  auto *generic{ultimate ? ultimate->detailsIf<GenericDetails>() : nullptr};
  if (generic) {
    if (Symbol * genDT{generic->derivedType()}) {
      symbol = genDT;
      generic = nullptr;
    }
  }
  if (!symbol || symbol->has<UnknownDetails>() ||
      (generic && &ultimate->owner() == &outer)) {
    if (allowForwardReferenceToDerivedType()) {
      if (!symbol) {
        symbol = &MakeSymbol(outer, name.source, Attrs{});
        Resolve(name, *symbol);
      } else if (generic) {
        // forward ref to type with later homonymous generic
        symbol = &outer.MakeSymbol(name.source, Attrs{}, UnknownDetails{});
        generic->set_derivedType(*symbol);
        name.symbol = symbol;
      }
      DerivedTypeDetails details;
      details.set_isForwardReferenced(true);
      symbol->set_details(std::move(details));
    } else { // C732
      Say(name, "Derived type '%s' not found"_err_en_US);
      return std::nullopt;
    }
  } else if (&DEREF(symbol).owner() != &outer &&
      !ultimate->has<GenericDetails>()) {
    // Prevent a later declaration in this scope of a host-associated
    // type name.
    outer.add_importName(name.source);
  }
  if (CheckUseError(name)) {
    return std::nullopt;
  }
  symbol = &symbol->GetUltimate();
  if (symbol->has<DerivedTypeDetails>()) {
    return DerivedTypeSpec{name.source, *symbol};
  } else {
    Say(name, "'%s' is not a derived type"_err_en_US);
    return std::nullopt;
  }
}

std::optional<DerivedTypeSpec> DeclarationVisitor::ResolveExtendsType(
    const parser::Name &typeName, const parser::Name *extendsName) {
  if (!extendsName) {
    return std::nullopt;
  } else if (typeName.source == extendsName->source) {
    Say(extendsName->source,
        "Derived type '%s' cannot extend itself"_err_en_US);
    return std::nullopt;
  } else {
    return ResolveDerivedType(*extendsName);
  }
}

Symbol *DeclarationVisitor::NoteInterfaceName(const parser::Name &name) {
  // The symbol is checked later by CheckExplicitInterface() and
  // CheckBindings().  It can be a forward reference.
  if (!NameIsKnownOrIntrinsic(name)) {
    Symbol &symbol{MakeSymbol(InclusiveScope(), name.source, Attrs{})};
    Resolve(name, symbol);
  }
  return name.symbol;
}

void DeclarationVisitor::CheckExplicitInterface(const parser::Name &name) {
  if (const Symbol * symbol{name.symbol}) {
    const Symbol &ultimate{symbol->GetUltimate()};
    if (!context().HasError(*symbol) && !context().HasError(ultimate) &&
        !BypassGeneric(ultimate).HasExplicitInterface()) {
      Say(name,
          "'%s' must be an abstract interface or a procedure with an explicit interface"_err_en_US,
          symbol->name());
    }
  }
}

// Create a symbol for a type parameter, component, or procedure binding in
// the current derived type scope. Return false on error.
Symbol *DeclarationVisitor::MakeTypeSymbol(
    const parser::Name &name, Details &&details) {
  return Resolve(name, MakeTypeSymbol(name.source, std::move(details)));
}
Symbol *DeclarationVisitor::MakeTypeSymbol(
    const SourceName &name, Details &&details) {
  Scope &derivedType{currScope()};
  CHECK(derivedType.IsDerivedType());
  if (auto *symbol{FindInScope(derivedType, name)}) { // C742
    Say2(name,
        "Type parameter, component, or procedure binding '%s'"
        " already defined in this type"_err_en_US,
        *symbol, "Previous definition of '%s'"_en_US);
    return nullptr;
  } else {
    auto attrs{GetAttrs()};
    // Apply binding-private-stmt if present and this is a procedure binding
    if (derivedTypeInfo_.privateBindings &&
        !attrs.HasAny({Attr::PUBLIC, Attr::PRIVATE}) &&
        std::holds_alternative<ProcBindingDetails>(details)) {
      attrs.set(Attr::PRIVATE);
    }
    Symbol &result{MakeSymbol(name, attrs, std::move(details))};
    SetCUDADataAttr(name, result, cudaDataAttr());
    if (result.has<TypeParamDetails>()) {
      derivedType.symbol()->get<DerivedTypeDetails>().add_paramDecl(result);
    }
    return &result;
  }
}

// Return true if it is ok to declare this component in the current scope.
// Otherwise, emit an error and return false.
bool DeclarationVisitor::OkToAddComponent(
    const parser::Name &name, const Symbol *extends) {
  for (const Scope *scope{&currScope()}; scope;) {
    CHECK(scope->IsDerivedType());
    if (auto *prev{FindInScope(*scope, name.source)}) {
      std::optional<parser::MessageFixedText> msg;
      if (context().HasError(*prev)) { // don't pile on
      } else if (extends) {
        msg = "Type cannot be extended as it has a component named"
              " '%s'"_err_en_US;
      } else if (CheckAccessibleSymbol(currScope(), *prev)) {
        // inaccessible component -- redeclaration is ok
        msg = "Component '%s' is inaccessibly declared in or as a "
              "parent of this derived type"_warn_en_US;
      } else if (prev->test(Symbol::Flag::ParentComp)) {
        msg = "'%s' is a parent type of this type and so cannot be"
              " a component"_err_en_US;
      } else if (scope == &currScope()) {
        msg = "Component '%s' is already declared in this"
              " derived type"_err_en_US;
      } else {
        msg = "Component '%s' is already declared in a parent of this"
              " derived type"_err_en_US;
      }
      if (msg) {
        Say2(
            name, std::move(*msg), *prev, "Previous declaration of '%s'"_en_US);
        if (msg->severity() == parser::Severity::Error) {
          Resolve(name, *prev);
          return false;
        }
      }
    }
    if (scope == &currScope() && extends) {
      // The parent component has not yet been added to the scope.
      scope = extends->scope();
    } else {
      scope = scope->GetDerivedTypeParent();
    }
  }
  return true;
}

ParamValue DeclarationVisitor::GetParamValue(
    const parser::TypeParamValue &x, common::TypeParamAttr attr) {
  return common::visit(
      common::visitors{
          [=](const parser::ScalarIntExpr &x) { // C704
            return ParamValue{EvaluateIntExpr(x), attr};
          },
          [=](const parser::Star &) { return ParamValue::Assumed(attr); },
          [=](const parser::TypeParamValue::Deferred &) {
            return ParamValue::Deferred(attr);
          },
      },
      x.u);
}

// ConstructVisitor implementation

void ConstructVisitor::ResolveIndexName(
    const parser::ConcurrentControl &control) {
  const parser::Name &name{std::get<parser::Name>(control.t)};
  auto *prev{FindSymbol(name)};
  if (prev) {
    if (prev->owner() == currScope()) {
      SayAlreadyDeclared(name, *prev);
      return;
    } else if (prev->owner().kind() == Scope::Kind::Forall &&
        context().ShouldWarn(
            common::LanguageFeature::OddIndexVariableRestrictions)) {
      SayWithDecl(name, *prev,
          "Index variable '%s' should not also be an index in an enclosing FORALL or DO CONCURRENT"_port_en_US);
    }
    name.symbol = nullptr;
  }
  auto &symbol{DeclareObjectEntity(name)};
  if (symbol.GetType()) {
    // type came from explicit type-spec
  } else if (!prev) {
    ApplyImplicitRules(symbol);
  } else {
    // Odd rules in F'2023 19.4 paras 6 & 8.
    Symbol &prevRoot{prev->GetUltimate()};
    if (const auto *type{prevRoot.GetType()}) {
      symbol.SetType(*type);
    } else {
      ApplyImplicitRules(symbol);
    }
    if (prevRoot.has<ObjectEntityDetails>() ||
        ConvertToObjectEntity(prevRoot)) {
      if (prevRoot.IsObjectArray() &&
          context().ShouldWarn(
              common::LanguageFeature::OddIndexVariableRestrictions)) {
        SayWithDecl(name, *prev,
            "Index variable '%s' should be scalar in the enclosing scope"_port_en_US);
      }
    } else if (!prevRoot.has<CommonBlockDetails>() &&
        context().ShouldWarn(
            common::LanguageFeature::OddIndexVariableRestrictions)) {
      SayWithDecl(name, *prev,
          "Index variable '%s' should be a scalar object or common block if it is present in the enclosing scope"_port_en_US);
    }
  }
  EvaluateExpr(parser::Scalar{parser::Integer{common::Clone(name)}});
}

// We need to make sure that all of the index-names get declared before the
// expressions in the loop control are evaluated so that references to the
// index-names in the expressions are correctly detected.
bool ConstructVisitor::Pre(const parser::ConcurrentHeader &header) {
  BeginDeclTypeSpec();
  Walk(std::get<std::optional<parser::IntegerTypeSpec>>(header.t));
  const auto &controls{
      std::get<std::list<parser::ConcurrentControl>>(header.t)};
  for (const auto &control : controls) {
    ResolveIndexName(control);
  }
  Walk(controls);
  Walk(std::get<std::optional<parser::ScalarLogicalExpr>>(header.t));
  EndDeclTypeSpec();
  return false;
}

bool ConstructVisitor::Pre(const parser::LocalitySpec::Local &x) {
  for (auto &name : x.v) {
    if (auto *symbol{DeclareLocalEntity(name)}) {
      symbol->set(Symbol::Flag::LocalityLocal);
    }
  }
  return false;
}

bool ConstructVisitor::Pre(const parser::LocalitySpec::LocalInit &x) {
  for (auto &name : x.v) {
    if (auto *symbol{DeclareLocalEntity(name)}) {
      symbol->set(Symbol::Flag::LocalityLocalInit);
    }
  }
  return false;
}

bool ConstructVisitor::Pre(const parser::LocalitySpec::Shared &x) {
  for (const auto &name : x.v) {
    if (!FindSymbol(name)) {
      Say(name,
          "Variable '%s' with SHARED locality implicitly declared"_warn_en_US);
    }
    Symbol &prev{FindOrDeclareEnclosingEntity(name)};
    if (PassesSharedLocalityChecks(name, prev)) {
      MakeHostAssocSymbol(name, prev).set(Symbol::Flag::LocalityShared);
    }
  }
  return false;
}

bool ConstructVisitor::Pre(const parser::AcSpec &x) {
  ProcessTypeSpec(x.type);
  Walk(x.values);
  return false;
}

// Section 19.4, paragraph 5 says that each ac-do-variable has the scope of the
// enclosing ac-implied-do
bool ConstructVisitor::Pre(const parser::AcImpliedDo &x) {
  auto &values{std::get<std::list<parser::AcValue>>(x.t)};
  auto &control{std::get<parser::AcImpliedDoControl>(x.t)};
  auto &type{std::get<std::optional<parser::IntegerTypeSpec>>(control.t)};
  auto &bounds{std::get<parser::AcImpliedDoControl::Bounds>(control.t)};
  // F'2018 has the scope of the implied DO variable covering the entire
  // implied DO production (19.4(5)), which seems wrong in cases where the name
  // of the implied DO variable appears in one of the bound expressions. Thus
  // this extension, which shrinks the scope of the variable to exclude the
  // expressions in the bounds.
  auto restore{BeginCheckOnIndexUseInOwnBounds(bounds.name)};
  Walk(bounds.lower);
  Walk(bounds.upper);
  Walk(bounds.step);
  EndCheckOnIndexUseInOwnBounds(restore);
  PushScope(Scope::Kind::ImpliedDos, nullptr);
  DeclareStatementEntity(bounds.name, type);
  Walk(values);
  PopScope();
  return false;
}

bool ConstructVisitor::Pre(const parser::DataImpliedDo &x) {
  auto &objects{std::get<std::list<parser::DataIDoObject>>(x.t)};
  auto &type{std::get<std::optional<parser::IntegerTypeSpec>>(x.t)};
  auto &bounds{std::get<parser::DataImpliedDo::Bounds>(x.t)};
  // See comment in Pre(AcImpliedDo) above.
  auto restore{BeginCheckOnIndexUseInOwnBounds(bounds.name)};
  Walk(bounds.lower);
  Walk(bounds.upper);
  Walk(bounds.step);
  EndCheckOnIndexUseInOwnBounds(restore);
  bool pushScope{currScope().kind() != Scope::Kind::ImpliedDos};
  if (pushScope) {
    PushScope(Scope::Kind::ImpliedDos, nullptr);
  }
  DeclareStatementEntity(bounds.name, type);
  Walk(objects);
  if (pushScope) {
    PopScope();
  }
  return false;
}

// Sets InDataStmt flag on a variable (or misidentified function) in a DATA
// statement so that the predicate IsInitialized() will be true
// during semantic analysis before the symbol's initializer is constructed.
bool ConstructVisitor::Pre(const parser::DataIDoObject &x) {
  common::visit(
      common::visitors{
          [&](const parser::Scalar<Indirection<parser::Designator>> &y) {
            Walk(y.thing.value());
            const parser::Name &first{parser::GetFirstName(y.thing.value())};
            if (first.symbol) {
              first.symbol->set(Symbol::Flag::InDataStmt);
            }
          },
          [&](const Indirection<parser::DataImpliedDo> &y) { Walk(y.value()); },
      },
      x.u);
  return false;
}

bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {
  // Subtle: DATA statements may appear in both the specification and
  // execution parts, but should be treated as if in the execution part
  // for purposes of implicit variable declaration vs. host association.
  // When a name first appears as an object in a DATA statement, it should
  // be implicitly declared locally as if it had been assigned.
  auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)};
  common::visit(common::visitors{
                    [&](const Indirection<parser::Variable> &y) {
                      auto restorer{
                          common::ScopedSet(deferImplicitTyping_, true)};
                      Walk(y.value());
                      const parser::Name &first{
                          parser::GetFirstName(y.value())};
                      if (first.symbol) {
                        first.symbol->set(Symbol::Flag::InDataStmt);
                      }
                    },
                    [&](const parser::DataImpliedDo &y) {
                      PushScope(Scope::Kind::ImpliedDos, nullptr);
                      Walk(y);
                      PopScope();
                    },
                },
      x.u);
  return false;
}

bool ConstructVisitor::Pre(const parser::DataStmtValue &x) {
  const auto &data{std::get<parser::DataStmtConstant>(x.t)};
  auto &mutableData{const_cast<parser::DataStmtConstant &>(data)};
  if (auto *elem{parser::Unwrap<parser::ArrayElement>(mutableData)}) {
    if (const auto *name{std::get_if<parser::Name>(&elem->base.u)}) {
      if (const Symbol * symbol{FindSymbol(*name)}) {
        const Symbol &ultimate{symbol->GetUltimate()};
        if (ultimate.has<DerivedTypeDetails>()) {
          mutableData.u = elem->ConvertToStructureConstructor(
              DerivedTypeSpec{name->source, ultimate});
        }
      }
    }
  }
  return true;
}

bool ConstructVisitor::Pre(const parser::DoConstruct &x) {
  if (x.IsDoConcurrent()) {
    // The new scope has Kind::Forall for index variable name conflict
    // detection with nested FORALL/DO CONCURRENT constructs in
    // ResolveIndexName().
    PushScope(Scope::Kind::Forall, nullptr);
  }
  return true;
}
void ConstructVisitor::Post(const parser::DoConstruct &x) {
  if (x.IsDoConcurrent()) {
    PopScope();
  }
}

bool ConstructVisitor::Pre(const parser::ForallConstruct &) {
  PushScope(Scope::Kind::Forall, nullptr);
  return true;
}
void ConstructVisitor::Post(const parser::ForallConstruct &) { PopScope(); }
bool ConstructVisitor::Pre(const parser::ForallStmt &) {
  PushScope(Scope::Kind::Forall, nullptr);
  return true;
}
void ConstructVisitor::Post(const parser::ForallStmt &) { PopScope(); }

bool ConstructVisitor::Pre(const parser::BlockConstruct &x) {
  const auto &[blockStmt, specPart, execPart, endBlockStmt] = x.t;
  Walk(blockStmt);
  CheckDef(blockStmt.statement.v);
  PushScope(Scope::Kind::BlockConstruct, nullptr);
  Walk(specPart);
  HandleImpliedAsynchronousInScope(execPart);
  Walk(execPart);
  Walk(endBlockStmt);
  PopScope();
  CheckRef(endBlockStmt.statement.v);
  return false;
}

void ConstructVisitor::Post(const parser::Selector &x) {
  GetCurrentAssociation().selector = ResolveSelector(x);
}

void ConstructVisitor::Post(const parser::AssociateStmt &x) {
  CheckDef(x.t);
  PushScope(Scope::Kind::OtherConstruct, nullptr);
  const auto assocCount{std::get<std::list<parser::Association>>(x.t).size()};
  for (auto nthLastAssoc{assocCount}; nthLastAssoc > 0; --nthLastAssoc) {
    SetCurrentAssociation(nthLastAssoc);
    if (auto *symbol{MakeAssocEntity()}) {
      if (ExtractCoarrayRef(GetCurrentAssociation().selector.expr)) { // C1103
        Say("Selector must not be a coindexed object"_err_en_US);
      }
      SetTypeFromAssociation(*symbol);
      SetAttrsFromAssociation(*symbol);
    }
  }
  PopAssociation(assocCount);
}

void ConstructVisitor::Post(const parser::EndAssociateStmt &x) {
  PopScope();
  CheckRef(x.v);
}

bool ConstructVisitor::Pre(const parser::Association &x) {
  PushAssociation();
  const auto &name{std::get<parser::Name>(x.t)};
  GetCurrentAssociation().name = &name;
  return true;
}

bool ConstructVisitor::Pre(const parser::ChangeTeamStmt &x) {
  CheckDef(x.t);
  PushScope(Scope::Kind::OtherConstruct, nullptr);
  PushAssociation();
  return true;
}

void ConstructVisitor::Post(const parser::CoarrayAssociation &x) {
  const auto &decl{std::get<parser::CodimensionDecl>(x.t)};
  const auto &name{std::get<parser::Name>(decl.t)};
  if (auto *symbol{FindInScope(name)}) {
    const auto &selector{std::get<parser::Selector>(x.t)};
    if (auto sel{ResolveSelector(selector)}) {
      const Symbol *whole{UnwrapWholeSymbolDataRef(sel.expr)};
      if (!whole || whole->Corank() == 0) {
        Say(sel.source, // C1116
            "Selector in coarray association must name a coarray"_err_en_US);
      } else if (auto dynType{sel.expr->GetType()}) {
        if (!symbol->GetType()) {
          symbol->SetType(ToDeclTypeSpec(std::move(*dynType)));
        }
      }
    }
  }
}

void ConstructVisitor::Post(const parser::EndChangeTeamStmt &x) {
  PopAssociation();
  PopScope();
  CheckRef(x.t);
}

bool ConstructVisitor::Pre(const parser::SelectTypeConstruct &) {
  PushAssociation();
  return true;
}

void ConstructVisitor::Post(const parser::SelectTypeConstruct &) {
  PopAssociation();
}

void ConstructVisitor::Post(const parser::SelectTypeStmt &x) {
  auto &association{GetCurrentAssociation()};
  if (const std::optional<parser::Name> &name{std::get<1>(x.t)}) {
    // This isn't a name in the current scope, it is in each TypeGuardStmt
    MakePlaceholder(*name, MiscDetails::Kind::SelectTypeAssociateName);
    association.name = &*name;
    if (ExtractCoarrayRef(association.selector.expr)) { // C1103
      Say("Selector must not be a coindexed object"_err_en_US);
    }
    if (association.selector.expr) {
      auto exprType{association.selector.expr->GetType()};
      if (exprType && !exprType->IsPolymorphic()) { // C1159
        Say(association.selector.source,
            "Selector '%s' in SELECT TYPE statement must be "
            "polymorphic"_err_en_US);
      }
    }
  } else {
    if (const Symbol *
        whole{UnwrapWholeSymbolDataRef(association.selector.expr)}) {
      ConvertToObjectEntity(const_cast<Symbol &>(*whole));
      if (!IsVariableName(*whole)) {
        Say(association.selector.source, // C901
            "Selector is not a variable"_err_en_US);
        association = {};
      }
      if (const DeclTypeSpec * type{whole->GetType()}) {
        if (!type->IsPolymorphic()) { // C1159
          Say(association.selector.source,
              "Selector '%s' in SELECT TYPE statement must be "
              "polymorphic"_err_en_US);
        }
      }
    } else {
      Say(association.selector.source, // C1157
          "Selector is not a named variable: 'associate-name =>' is required"_err_en_US);
      association = {};
    }
  }
}

void ConstructVisitor::Post(const parser::SelectRankStmt &x) {
  auto &association{GetCurrentAssociation()};
  if (const std::optional<parser::Name> &name{std::get<1>(x.t)}) {
    // This isn't a name in the current scope, it is in each SelectRankCaseStmt
    MakePlaceholder(*name, MiscDetails::Kind::SelectRankAssociateName);
    association.name = &*name;
  }
}

bool ConstructVisitor::Pre(const parser::SelectTypeConstruct::TypeCase &) {
  PushScope(Scope::Kind::OtherConstruct, nullptr);
  return true;
}
void ConstructVisitor::Post(const parser::SelectTypeConstruct::TypeCase &) {
  PopScope();
}

bool ConstructVisitor::Pre(const parser::SelectRankConstruct::RankCase &) {
  PushScope(Scope::Kind::OtherConstruct, nullptr);
  return true;
}
void ConstructVisitor::Post(const parser::SelectRankConstruct::RankCase &) {
  PopScope();
}

bool ConstructVisitor::Pre(const parser::TypeGuardStmt::Guard &x) {
  if (std::holds_alternative<parser::DerivedTypeSpec>(x.u)) {
    // CLASS IS (t)
    SetDeclTypeSpecCategory(DeclTypeSpec::Category::ClassDerived);
  }
  return true;
}

void ConstructVisitor::Post(const parser::TypeGuardStmt::Guard &x) {
  if (auto *symbol{MakeAssocEntity()}) {
    if (std::holds_alternative<parser::Default>(x.u)) {
      SetTypeFromAssociation(*symbol);
    } else if (const auto *type{GetDeclTypeSpec()}) {
      symbol->SetType(*type);
    }
    SetAttrsFromAssociation(*symbol);
  }
}

void ConstructVisitor::Post(const parser::SelectRankCaseStmt::Rank &x) {
  if (auto *symbol{MakeAssocEntity()}) {
    SetTypeFromAssociation(*symbol);
    auto &details{symbol->get<AssocEntityDetails>()};
    // Don't call SetAttrsFromAssociation() for SELECT RANK.
    Attrs selectorAttrs{
        evaluate::GetAttrs(GetCurrentAssociation().selector.expr)};
    Attrs attrsToKeep{Attr::ASYNCHRONOUS, Attr::TARGET, Attr::VOLATILE};
    if (const auto *rankValue{
            std::get_if<parser::ScalarIntConstantExpr>(&x.u)}) {
      // RANK(n)
      if (auto expr{EvaluateIntExpr(*rankValue)}) {
        if (auto val{evaluate::ToInt64(*expr)}) {
          details.set_rank(*val);
          attrsToKeep |= Attrs{Attr::ALLOCATABLE, Attr::POINTER};
        } else {
          Say("RANK() expression must be constant"_err_en_US);
        }
      }
    } else if (std::holds_alternative<parser::Star>(x.u)) {
      // RANK(*): assumed-size
      details.set_IsAssumedSize();
    } else {
      CHECK(std::holds_alternative<parser::Default>(x.u));
      // RANK DEFAULT: assumed-rank
      details.set_IsAssumedRank();
      attrsToKeep |= Attrs{Attr::ALLOCATABLE, Attr::POINTER};
    }
    symbol->attrs() |= selectorAttrs & attrsToKeep;
  }
}

bool ConstructVisitor::Pre(const parser::SelectRankConstruct &) {
  PushAssociation();
  return true;
}

void ConstructVisitor::Post(const parser::SelectRankConstruct &) {
  PopAssociation();
}

bool ConstructVisitor::CheckDef(const std::optional<parser::Name> &x) {
  if (x && !x->symbol) {
    // Construct names are not scoped by BLOCK in the standard, but many,
    // but not all, compilers do treat them as if they were so scoped.
    if (Symbol * inner{FindInScope(currScope(), *x)}) {
      SayAlreadyDeclared(*x, *inner);
    } else {
      if (context().ShouldWarn(common::LanguageFeature::BenignNameClash)) {
        if (Symbol *
            other{FindInScopeOrBlockConstructs(InclusiveScope(), x->source)}) {
          SayWithDecl(*x, *other,
              "The construct name '%s' should be distinct at the subprogram level"_port_en_US);
        }
      }
      MakeSymbol(*x, MiscDetails{MiscDetails::Kind::ConstructName});
    }
  }
  return true;
}

void ConstructVisitor::CheckRef(const std::optional<parser::Name> &x) {
  if (x) {
    // Just add an occurrence of this name; checking is done in ValidateLabels
    FindSymbol(*x);
  }
}

// Make a symbol for the associating entity of the current association.
Symbol *ConstructVisitor::MakeAssocEntity() {
  Symbol *symbol{nullptr};
  auto &association{GetCurrentAssociation()};
  if (association.name) {
    symbol = &MakeSymbol(*association.name, UnknownDetails{});
    if (symbol->has<AssocEntityDetails>() && symbol->owner() == currScope()) {
      Say(*association.name, // C1102
          "The associate name '%s' is already used in this associate statement"_err_en_US);
      return nullptr;
    }
  } else if (const Symbol *
      whole{UnwrapWholeSymbolDataRef(association.selector.expr)}) {
    symbol = &MakeSymbol(whole->name());
  } else {
    return nullptr;
  }
  if (auto &expr{association.selector.expr}) {
    symbol->set_details(AssocEntityDetails{common::Clone(*expr)});
  } else {
    symbol->set_details(AssocEntityDetails{});
  }
  return symbol;
}

// Set the type of symbol based on the current association selector.
void ConstructVisitor::SetTypeFromAssociation(Symbol &symbol) {
  auto &details{symbol.get<AssocEntityDetails>()};
  const MaybeExpr *pexpr{&details.expr()};
  if (!*pexpr) {
    pexpr = &GetCurrentAssociation().selector.expr;
  }
  if (*pexpr) {
    const SomeExpr &expr{**pexpr};
    if (std::optional<evaluate::DynamicType> type{expr.GetType()}) {
      if (const auto *charExpr{
              evaluate::UnwrapExpr<evaluate::Expr<evaluate::SomeCharacter>>(
                  expr)}) {
        symbol.SetType(ToDeclTypeSpec(std::move(*type),
            FoldExpr(common::visit(
                [](const auto &kindChar) { return kindChar.LEN(); },
                charExpr->u))));
      } else {
        symbol.SetType(ToDeclTypeSpec(std::move(*type)));
      }
    } else {
      // BOZ literals, procedure designators, &c. are not acceptable
      Say(symbol.name(), "Associate name '%s' must have a type"_err_en_US);
    }
  }
}

// If current selector is a variable, set some of its attributes on symbol.
// For ASSOCIATE, CHANGE TEAM, and SELECT TYPE only; not SELECT RANK.
void ConstructVisitor::SetAttrsFromAssociation(Symbol &symbol) {
  Attrs attrs{evaluate::GetAttrs(GetCurrentAssociation().selector.expr)};
  symbol.attrs() |=
      attrs & Attrs{Attr::TARGET, Attr::ASYNCHRONOUS, Attr::VOLATILE};
  if (attrs.test(Attr::POINTER)) {
    SetImplicitAttr(symbol, Attr::TARGET);
  }
}

ConstructVisitor::Selector ConstructVisitor::ResolveSelector(
    const parser::Selector &x) {
  return common::visit(common::visitors{
                           [&](const parser::Expr &expr) {
                             return Selector{expr.source, EvaluateExpr(x)};
                           },
                           [&](const parser::Variable &var) {
                             return Selector{var.GetSource(), EvaluateExpr(x)};
                           },
                       },
      x.u);
}

// Set the current association to the nth to the last association on the
// association stack.  The top of the stack is at n = 1.  This allows access
// to the interior of a list of associations at the top of the stack.
void ConstructVisitor::SetCurrentAssociation(std::size_t n) {
  CHECK(n > 0 && n <= associationStack_.size());
  currentAssociation_ = &associationStack_[associationStack_.size() - n];
}

ConstructVisitor::Association &ConstructVisitor::GetCurrentAssociation() {
  CHECK(currentAssociation_);
  return *currentAssociation_;
}

void ConstructVisitor::PushAssociation() {
  associationStack_.emplace_back(Association{});
  currentAssociation_ = &associationStack_.back();
}

void ConstructVisitor::PopAssociation(std::size_t count) {
  CHECK(count > 0 && count <= associationStack_.size());
  associationStack_.resize(associationStack_.size() - count);
  currentAssociation_ =
      associationStack_.empty() ? nullptr : &associationStack_.back();
}

const DeclTypeSpec &ConstructVisitor::ToDeclTypeSpec(
    evaluate::DynamicType &&type) {
  switch (type.category()) {
    SWITCH_COVERS_ALL_CASES
  case common::TypeCategory::Integer:
  case common::TypeCategory::Real:
  case common::TypeCategory::Complex:
    return context().MakeNumericType(type.category(), type.kind());
  case common::TypeCategory::Logical:
    return context().MakeLogicalType(type.kind());
  case common::TypeCategory::Derived:
    if (type.IsAssumedType()) {
      return currScope().MakeTypeStarType();
    } else if (type.IsUnlimitedPolymorphic()) {
      return currScope().MakeClassStarType();
    } else {
      return currScope().MakeDerivedType(
          type.IsPolymorphic() ? DeclTypeSpec::ClassDerived
                               : DeclTypeSpec::TypeDerived,
          common::Clone(type.GetDerivedTypeSpec())

      );
    }
  case common::TypeCategory::Character:
    CRASH_NO_CASE;
  }
}

const DeclTypeSpec &ConstructVisitor::ToDeclTypeSpec(
    evaluate::DynamicType &&type, MaybeSubscriptIntExpr &&length) {
  CHECK(type.category() == common::TypeCategory::Character);
  if (length) {
    return currScope().MakeCharacterType(
        ParamValue{SomeIntExpr{*std::move(length)}, common::TypeParamAttr::Len},
        KindExpr{type.kind()});
  } else {
    return currScope().MakeCharacterType(
        ParamValue::Deferred(common::TypeParamAttr::Len),
        KindExpr{type.kind()});
  }
}

class ExecutionPartSkimmerBase {
public:
  template <typename A> bool Pre(const A &) { return true; }
  template <typename A> void Post(const A &) {}

  bool InNestedBlockConstruct() const { return blockDepth_ > 0; }

  bool Pre(const parser::AssociateConstruct &) {
    PushScope();
    return true;
  }
  void Post(const parser::AssociateConstruct &) { PopScope(); }
  bool Pre(const parser::Association &x) {
    Hide(std::get<parser::Name>(x.t));
    return true;
  }
  bool Pre(const parser::BlockConstruct &) {
    PushScope();
    ++blockDepth_;
    return true;
  }
  void Post(const parser::BlockConstruct &) {
    --blockDepth_;
    PopScope();
  }
  bool Pre(const parser::EntityDecl &x) {
    Hide(std::get<parser::ObjectName>(x.t));
    return true;
  }
  void Post(const parser::ImportStmt &x) {
    if (x.kind == common::ImportKind::None ||
        x.kind == common::ImportKind::Only) {
      if (!nestedScopes_.front().importOnly.has_value()) {
        nestedScopes_.front().importOnly.emplace();
      }
      for (const auto &name : x.names) {
        nestedScopes_.front().importOnly->emplace(name.source);
      }
    } else {
      // no special handling needed for explicit names or IMPORT, ALL
    }
  }
  void Post(const parser::UseStmt &x) {
    if (const auto *onlyList{std::get_if<std::list<parser::Only>>(&x.u)}) {
      for (const auto &only : *onlyList) {
        if (const auto *name{std::get_if<parser::Name>(&only.u)}) {
          Hide(*name);
        } else if (const auto *rename{std::get_if<parser::Rename>(&only.u)}) {
          if (const auto *names{
                  std::get_if<parser::Rename::Names>(&rename->u)}) {
            Hide(std::get<0>(names->t));
          }
        }
      }
    } else {
      // USE may or may not shadow symbols in host scopes
      nestedScopes_.front().hasUseWithoutOnly = true;
    }
  }
  bool Pre(const parser::DerivedTypeStmt &x) {
    Hide(std::get<parser::Name>(x.t));
    PushScope();
    return true;
  }
  void Post(const parser::DerivedTypeDef &) { PopScope(); }
  bool Pre(const parser::SelectTypeConstruct &) {
    PushScope();
    return true;
  }
  void Post(const parser::SelectTypeConstruct &) { PopScope(); }
  bool Pre(const parser::SelectTypeStmt &x) {
    if (const auto &maybeName{std::get<1>(x.t)}) {
      Hide(*maybeName);
    }
    return true;
  }
  bool Pre(const parser::SelectRankConstruct &) {
    PushScope();
    return true;
  }
  void Post(const parser::SelectRankConstruct &) { PopScope(); }
  bool Pre(const parser::SelectRankStmt &x) {
    if (const auto &maybeName{std::get<1>(x.t)}) {
      Hide(*maybeName);
    }
    return true;
  }

protected:
  bool IsHidden(SourceName name) {
    for (const auto &scope : nestedScopes_) {
      if (scope.locals.find(name) != scope.locals.end()) {
        return true; // shadowed by nested declaration
      }
      if (scope.hasUseWithoutOnly) {
        break;
      }
      if (scope.importOnly &&
          scope.importOnly->find(name) == scope.importOnly->end()) {
        return true; // not imported
      }
    }
    return false;
  }

  void EndWalk() { CHECK(nestedScopes_.empty()); }

private:
  void PushScope() { nestedScopes_.emplace_front(); }
  void PopScope() { nestedScopes_.pop_front(); }
  void Hide(const parser::Name &name) {
    nestedScopes_.front().locals.emplace(name.source);
  }

  int blockDepth_{0};
  struct NestedScopeInfo {
    bool hasUseWithoutOnly{false};
    std::set<SourceName> locals;
    std::optional<std::set<SourceName>> importOnly;
  };
  std::list<NestedScopeInfo> nestedScopes_;
};

class ExecutionPartAsyncIOSkimmer : public ExecutionPartSkimmerBase {
public:
  explicit ExecutionPartAsyncIOSkimmer(SemanticsContext &context)
      : context_{context} {}

  void Walk(const parser::Block &block) {
    parser::Walk(block, *this);
    EndWalk();
  }

  const std::set<SourceName> asyncIONames() const { return asyncIONames_; }

  using ExecutionPartSkimmerBase::Post;
  using ExecutionPartSkimmerBase::Pre;

  bool Pre(const parser::IoControlSpec::Asynchronous &async) {
    if (auto folded{evaluate::Fold(
            context_.foldingContext(), AnalyzeExpr(context_, async.v))}) {
      if (auto str{
              evaluate::GetScalarConstantValue<evaluate::Ascii>(*folded)}) {
        for (char ch : *str) {
          if (ch != ' ') {
            inAsyncIO_ = ch == 'y' || ch == 'Y';
            break;
          }
        }
      }
    }
    return true;
  }
  void Post(const parser::ReadStmt &) { inAsyncIO_ = false; }
  void Post(const parser::WriteStmt &) { inAsyncIO_ = false; }
  void Post(const parser::IoControlSpec::Size &size) {
    if (const auto *designator{
            std::get_if<common::Indirection<parser::Designator>>(
                &size.v.thing.thing.u)}) {
      NoteAsyncIODesignator(designator->value());
    }
  }
  void Post(const parser::InputItem &x) {
    if (const auto *var{std::get_if<parser::Variable>(&x.u)}) {
      if (const auto *designator{
              std::get_if<common::Indirection<parser::Designator>>(&var->u)}) {
        NoteAsyncIODesignator(designator->value());
      }
    }
  }
  void Post(const parser::OutputItem &x) {
    if (const auto *expr{std::get_if<parser::Expr>(&x.u)}) {
      if (const auto *designator{
              std::get_if<common::Indirection<parser::Designator>>(&expr->u)}) {
        NoteAsyncIODesignator(designator->value());
      }
    }
  }

private:
  void NoteAsyncIODesignator(const parser::Designator &designator) {
    if (inAsyncIO_ && !InNestedBlockConstruct()) {
      const parser::Name &name{parser::GetFirstName(designator)};
      if (!IsHidden(name.source)) {
        asyncIONames_.insert(name.source);
      }
    }
  }

  SemanticsContext &context_;
  bool inAsyncIO_{false};
  std::set<SourceName> asyncIONames_;
};

// Any data list item or SIZE= specifier of an I/O data transfer statement
// with ASYNCHRONOUS="YES" implicitly has the ASYNCHRONOUS attribute in the
// local scope.
void ConstructVisitor::HandleImpliedAsynchronousInScope(
    const parser::Block &block) {
  ExecutionPartAsyncIOSkimmer skimmer{context()};
  skimmer.Walk(block);
  for (auto name : skimmer.asyncIONames()) {
    if (Symbol * symbol{currScope().FindSymbol(name)}) {
      if (!symbol->attrs().test(Attr::ASYNCHRONOUS)) {
        if (&symbol->owner() != &currScope()) {
          symbol = &*currScope()
                         .try_emplace(name, HostAssocDetails{*symbol})
                         .first->second;
        }
        if (symbol->has<AssocEntityDetails>()) {
          symbol = const_cast<Symbol *>(&GetAssociationRoot(*symbol));
        }
        SetImplicitAttr(*symbol, Attr::ASYNCHRONOUS);
      }
    }
  }
}

// ResolveNamesVisitor implementation

bool ResolveNamesVisitor::Pre(const parser::FunctionReference &x) {
  HandleCall(Symbol::Flag::Function, x.v);
  return false;
}
bool ResolveNamesVisitor::Pre(const parser::CallStmt &x) {
  HandleCall(Symbol::Flag::Subroutine, x.call);
  Walk(x.chevrons);
  return false;
}

bool ResolveNamesVisitor::Pre(const parser::ImportStmt &x) {
  auto &scope{currScope()};
  // Check C896 and C899: where IMPORT statements are allowed
  switch (scope.kind()) {
  case Scope::Kind::Module:
    if (scope.IsModule()) {
      Say("IMPORT is not allowed in a module scoping unit"_err_en_US);
      return false;
    } else if (x.kind == common::ImportKind::None) {
      Say("IMPORT,NONE is not allowed in a submodule scoping unit"_err_en_US);
      return false;
    }
    break;
  case Scope::Kind::MainProgram:
    Say("IMPORT is not allowed in a main program scoping unit"_err_en_US);
    return false;
  case Scope::Kind::Subprogram:
    if (scope.parent().IsGlobal()) {
      Say("IMPORT is not allowed in an external subprogram scoping unit"_err_en_US);
      return false;
    }
    break;
  case Scope::Kind::BlockData: // C1415 (in part)
    Say("IMPORT is not allowed in a BLOCK DATA subprogram"_err_en_US);
    return false;
  default:;
  }
  if (auto error{scope.SetImportKind(x.kind)}) {
    Say(std::move(*error));
  }
  for (auto &name : x.names) {
    if (Symbol * outer{FindSymbol(scope.parent(), name)}) {
      scope.add_importName(name.source);
      if (Symbol * symbol{FindInScope(name)}) {
        if (outer->GetUltimate() == symbol->GetUltimate()) {
          if (context().ShouldWarn(common::LanguageFeature::BenignNameClash)) {
            Say(name,
                "The same '%s' is already present in this scope"_port_en_US);
          }
        } else {
          Say(name,
              "A distinct '%s' is already present in this scope"_err_en_US)
              .Attach(symbol->name(), "Previous declaration of '%s'"_en_US)
              .Attach(outer->name(), "Declaration of '%s' in host scope"_en_US);
        }
      }
    } else {
      Say(name, "'%s' not found in host scope"_err_en_US);
    }
  }
  prevImportStmt_ = currStmtSource();
  return false;
}

const parser::Name *DeclarationVisitor::ResolveStructureComponent(
    const parser::StructureComponent &x) {
  return FindComponent(ResolveDataRef(x.base), x.component);
}

const parser::Name *DeclarationVisitor::ResolveDesignator(
    const parser::Designator &x) {
  return common::visit(
      common::visitors{
          [&](const parser::DataRef &x) { return ResolveDataRef(x); },
          [&](const parser::Substring &x) {
            Walk(std::get<parser::SubstringRange>(x.t).t);
            return ResolveDataRef(std::get<parser::DataRef>(x.t));
          },
      },
      x.u);
}

const parser::Name *DeclarationVisitor::ResolveDataRef(
    const parser::DataRef &x) {
  return common::visit(
      common::visitors{
          [=](const parser::Name &y) { return ResolveName(y); },
          [=](const Indirection<parser::StructureComponent> &y) {
            return ResolveStructureComponent(y.value());
          },
          [&](const Indirection<parser::ArrayElement> &y) {
            Walk(y.value().subscripts);
            const parser::Name *name{ResolveDataRef(y.value().base)};
            if (name && name->symbol) {
              if (!IsProcedure(*name->symbol)) {
                ConvertToObjectEntity(*name->symbol);
              } else if (!context().HasError(*name->symbol)) {
                SayWithDecl(*name, *name->symbol,
                    "Cannot reference function '%s' as data"_err_en_US);
                context().SetError(*name->symbol);
              }
            }
            return name;
          },
          [&](const Indirection<parser::CoindexedNamedObject> &y) {
            Walk(y.value().imageSelector);
            return ResolveDataRef(y.value().base);
          },
      },
      x.u);
}

// If implicit types are allowed, ensure name is in the symbol table.
// Otherwise, report an error if it hasn't been declared.
const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {
  FindSymbol(name);
  if (CheckForHostAssociatedImplicit(name)) {
    NotePossibleBadForwardRef(name);
    return &name;
  }
  if (Symbol * symbol{name.symbol}) {
    if (CheckUseError(name)) {
      return nullptr; // reported an error
    }
    NotePossibleBadForwardRef(name);
    symbol->set(Symbol::Flag::ImplicitOrError, false);
    if (IsUplevelReference(*symbol)) {
      MakeHostAssocSymbol(name, *symbol);
    } else if (IsDummy(*symbol) ||
        (!symbol->GetType() && FindCommonBlockContaining(*symbol))) {
      CheckEntryDummyUse(name.source, symbol);
      ConvertToObjectEntity(*symbol);
      ApplyImplicitRules(*symbol);
    }
    if (checkIndexUseInOwnBounds_ &&
        *checkIndexUseInOwnBounds_ == name.source && !InModuleFile()) {
      if (context().ShouldWarn(common::LanguageFeature::ImpliedDoIndexScope)) {
        Say(name,
            "Implied DO index '%s' uses an object of the same name in its bounds expressions"_port_en_US,
            name.source);
      }
    }
    return &name;
  }
  if (isImplicitNoneType() && !deferImplicitTyping_) {
    Say(name, "No explicit type declared for '%s'"_err_en_US);
    return nullptr;
  }
  // Create the symbol, then ensure that it is accessible
  if (checkIndexUseInOwnBounds_ && *checkIndexUseInOwnBounds_ == name.source) {
    Say(name,
        "Implied DO index '%s' uses itself in its own bounds expressions"_err_en_US,
        name.source);
  }
  MakeSymbol(InclusiveScope(), name.source, Attrs{});
  auto *symbol{FindSymbol(name)};
  if (!symbol) {
    Say(name,
        "'%s' from host scoping unit is not accessible due to IMPORT"_err_en_US);
    return nullptr;
  }
  ConvertToObjectEntity(*symbol);
  ApplyImplicitRules(*symbol);
  NotePossibleBadForwardRef(name);
  return &name;
}

// A specification expression may refer to a symbol in the host procedure that
// is implicitly typed. Because specification parts are processed before
// execution parts, this may be the first time we see the symbol. It can't be a
// local in the current scope (because it's in a specification expression) so
// either it is implicitly declared in the host procedure or it is an error.
// We create a symbol in the host assuming it is the former; if that proves to
// be wrong we report an error later in CheckDeclarations().
bool DeclarationVisitor::CheckForHostAssociatedImplicit(
    const parser::Name &name) {
  if (!inSpecificationPart_ || inEquivalenceStmt_) {
    return false;
  }
  if (name.symbol) {
    ApplyImplicitRules(*name.symbol, true);
  }
  Symbol *hostSymbol;
  Scope *host{GetHostProcedure()};
  if (!host || isImplicitNoneType(*host)) {
    return false;
  }
  if (!name.symbol) {
    hostSymbol = &MakeSymbol(*host, name.source, Attrs{});
    ConvertToObjectEntity(*hostSymbol);
    ApplyImplicitRules(*hostSymbol);
    hostSymbol->set(Symbol::Flag::ImplicitOrError);
  } else if (name.symbol->test(Symbol::Flag::ImplicitOrError)) {
    hostSymbol = name.symbol;
  } else {
    return false;
  }
  Symbol &symbol{MakeHostAssocSymbol(name, *hostSymbol)};
  if (isImplicitNoneType()) {
    symbol.get<HostAssocDetails>().implicitOrExplicitTypeError = true;
  } else {
    symbol.get<HostAssocDetails>().implicitOrSpecExprError = true;
  }
  return true;
}

bool DeclarationVisitor::IsUplevelReference(const Symbol &symbol) {
  const Scope &symbolUnit{GetProgramUnitContaining(symbol)};
  if (symbolUnit == GetProgramUnitContaining(currScope())) {
    return false;
  } else {
    Scope::Kind kind{symbolUnit.kind()};
    return kind == Scope::Kind::Subprogram || kind == Scope::Kind::MainProgram;
  }
}

// base is a part-ref of a derived type; find the named component in its type.
// Also handles intrinsic type parameter inquiries (%kind, %len) and
// COMPLEX component references (%re, %im).
const parser::Name *DeclarationVisitor::FindComponent(
    const parser::Name *base, const parser::Name &component) {
  if (!base || !base->symbol) {
    return nullptr;
  }
  if (auto *misc{base->symbol->detailsIf<MiscDetails>()}) {
    if (component.source == "kind") {
      if (misc->kind() == MiscDetails::Kind::ComplexPartRe ||
          misc->kind() == MiscDetails::Kind::ComplexPartIm ||
          misc->kind() == MiscDetails::Kind::KindParamInquiry ||
          misc->kind() == MiscDetails::Kind::LenParamInquiry) {
        // x%{re,im,kind,len}%kind
        MakePlaceholder(component, MiscDetails::Kind::KindParamInquiry);
        return &component;
      }
    }
  }
  CheckEntryDummyUse(base->source, base->symbol);
  auto &symbol{base->symbol->GetUltimate()};
  if (!symbol.has<AssocEntityDetails>() && !ConvertToObjectEntity(symbol)) {
    SayWithDecl(*base, symbol,
        "'%s' is not an object and may not be used as the base of a component reference or type parameter inquiry"_err_en_US);
    return nullptr;
  }
  auto *type{symbol.GetType()};
  if (!type) {
    return nullptr; // should have already reported error
  }
  if (const IntrinsicTypeSpec * intrinsic{type->AsIntrinsic()}) {
    auto category{intrinsic->category()};
    MiscDetails::Kind miscKind{MiscDetails::Kind::None};
    if (component.source == "kind") {
      miscKind = MiscDetails::Kind::KindParamInquiry;
    } else if (category == TypeCategory::Character) {
      if (component.source == "len") {
        miscKind = MiscDetails::Kind::LenParamInquiry;
      }
    } else if (category == TypeCategory::Complex) {
      if (component.source == "re") {
        miscKind = MiscDetails::Kind::ComplexPartRe;
      } else if (component.source == "im") {
        miscKind = MiscDetails::Kind::ComplexPartIm;
      }
    }
    if (miscKind != MiscDetails::Kind::None) {
      MakePlaceholder(component, miscKind);
      return &component;
    }
  } else if (DerivedTypeSpec * derived{type->AsDerived()}) {
    derived->Instantiate(currScope()); // in case of forward referenced type
    if (const Scope * scope{derived->scope()}) {
      if (Resolve(component, scope->FindComponent(component.source))) {
        if (auto msg{CheckAccessibleSymbol(currScope(), *component.symbol)}) {
          context().Say(component.source, *msg);
        }
        return &component;
      } else {
        SayDerivedType(component.source,
            "Component '%s' not found in derived type '%s'"_err_en_US, *scope);
      }
    }
    return nullptr;
  }
  if (symbol.test(Symbol::Flag::Implicit)) {
    Say(*base,
        "'%s' is not an object of derived type; it is implicitly typed"_err_en_US);
  } else {
    SayWithDecl(
        *base, symbol, "'%s' is not an object of derived type"_err_en_US);
  }
  return nullptr;
}

void DeclarationVisitor::Initialization(const parser::Name &name,
    const parser::Initialization &init, bool inComponentDecl) {
  // Traversal of the initializer was deferred to here so that the
  // symbol being declared can be available for use in the expression, e.g.:
  //   real, parameter :: x = tiny(x)
  if (!name.symbol) {
    return;
  }
  Symbol &ultimate{name.symbol->GetUltimate()};
  // TODO: check C762 - all bounds and type parameters of component
  // are colons or constant expressions if component is initialized
  common::visit(
      common::visitors{
          [&](const parser::ConstantExpr &expr) {
            Walk(expr);
            if (IsNamedConstant(ultimate) || inComponentDecl) {
              NonPointerInitialization(name, expr);
            } else {
              // Defer analysis so forward references to nested subprograms
              // can be properly resolved when they appear in structure
              // constructors.
              ultimate.set(Symbol::Flag::InDataStmt);
            }
          },
          [&](const parser::NullInit &null) { // => NULL()
            Walk(null);
            if (auto nullInit{EvaluateExpr(null)}) {
              if (!evaluate::IsNullPointer(*nullInit)) { // C813
                Say(null.v.value().source,
                    "Pointer initializer must be intrinsic NULL()"_err_en_US);
              } else if (IsPointer(ultimate)) {
                if (auto *object{ultimate.detailsIf<ObjectEntityDetails>()}) {
                  CHECK(!object->init());
                  object->set_init(std::move(*nullInit));
                } else if (auto *procPtr{
                               ultimate.detailsIf<ProcEntityDetails>()}) {
                  CHECK(!procPtr->init());
                  procPtr->set_init(nullptr);
                }
              } else {
                Say(name,
                    "Non-pointer component '%s' initialized with null pointer"_err_en_US);
              }
            }
          },
          [&](const parser::InitialDataTarget &target) {
            // Defer analysis to the end of the specification part
            // so that forward references and attribute checks like SAVE
            // work better.
            auto restorer{common::ScopedSet(deferImplicitTyping_, true)};
            Walk(target);
            ultimate.set(Symbol::Flag::InDataStmt);
          },
          [&](const std::list<Indirection<parser::DataStmtValue>> &values) {
            // Handled later in data-to-inits conversion
            ultimate.set(Symbol::Flag::InDataStmt);
            Walk(values);
          },
      },
      init.u);
}

void DeclarationVisitor::PointerInitialization(
    const parser::Name &name, const parser::InitialDataTarget &target) {
  if (name.symbol) {
    Symbol &ultimate{name.symbol->GetUltimate()};
    if (!context().HasError(ultimate)) {
      if (IsPointer(ultimate)) {
        Walk(target);
        if (MaybeExpr expr{EvaluateExpr(target)}) {
          // Validation is done in declaration checking.
          if (auto *details{ultimate.detailsIf<ObjectEntityDetails>()}) {
            CHECK(!details->init());
            details->set_init(std::move(*expr));
            ultimate.set(Symbol::Flag::InDataStmt, false);
          } else if (auto *details{ultimate.detailsIf<ProcEntityDetails>()}) {
            // something like "REAL, EXTERNAL, POINTER :: p => t"
            if (evaluate::IsNullProcedurePointer(*expr)) {
              CHECK(!details->init());
              details->set_init(nullptr);
            } else if (const Symbol *
                targetSymbol{evaluate::UnwrapWholeSymbolDataRef(*expr)}) {
              CHECK(!details->init());
              details->set_init(*targetSymbol);
            } else {
              Say(name,
                  "Procedure pointer '%s' must be initialized with a procedure name or NULL()"_err_en_US);
              context().SetError(ultimate);
            }
          }
        }
      } else {
        Say(name,
            "'%s' is not a pointer but is initialized like one"_err_en_US);
        context().SetError(ultimate);
      }
    }
  }
}
void DeclarationVisitor::PointerInitialization(
    const parser::Name &name, const parser::ProcPointerInit &target) {
  if (name.symbol) {
    Symbol &ultimate{name.symbol->GetUltimate()};
    if (!context().HasError(ultimate)) {
      if (IsProcedurePointer(ultimate)) {
        auto &details{ultimate.get<ProcEntityDetails>()};
        CHECK(!details.init());
        if (const auto *targetName{std::get_if<parser::Name>(&target.u)}) {
          Walk(target);
          if (!CheckUseError(*targetName) && targetName->symbol) {
            // Validation is done in declaration checking.
            details.set_init(*targetName->symbol);
          }
        } else { // explicit NULL
          details.set_init(nullptr);
        }
      } else {
        Say(name,
            "'%s' is not a procedure pointer but is initialized "
            "like one"_err_en_US);
        context().SetError(ultimate);
      }
    }
  }
}

void DeclarationVisitor::NonPointerInitialization(
    const parser::Name &name, const parser::ConstantExpr &expr) {
  if (!context().HasError(name.symbol)) {
    Symbol &ultimate{name.symbol->GetUltimate()};
    if (!context().HasError(ultimate)) {
      if (IsPointer(ultimate)) {
        Say(name,
            "'%s' is a pointer but is not initialized like one"_err_en_US);
      } else if (auto *details{ultimate.detailsIf<ObjectEntityDetails>()}) {
        if (details->init()) {
          SayWithDecl(name, *name.symbol,
              "'%s' has already been initialized"_err_en_US);
        } else if (IsAllocatable(ultimate)) {
          Say(name, "Allocatable object '%s' cannot be initialized"_err_en_US);
        } else if (ultimate.owner().IsParameterizedDerivedType()) {
          // Save the expression for per-instantiation analysis.
          details->set_unanalyzedPDTComponentInit(&expr.thing.value());
        } else if (MaybeExpr folded{EvaluateNonPointerInitializer(
                       ultimate, expr, expr.thing.value().source)}) {
          details->set_init(std::move(*folded));
          ultimate.set(Symbol::Flag::InDataStmt, false);
        }
      } else {
        Say(name, "'%s' is not an object that can be initialized"_err_en_US);
      }
    }
  }
}

void ResolveNamesVisitor::HandleCall(
    Symbol::Flag procFlag, const parser::Call &call) {
  common::visit(
      common::visitors{
          [&](const parser::Name &x) { HandleProcedureName(procFlag, x); },
          [&](const parser::ProcComponentRef &x) {
            Walk(x);
            const parser::Name &name{x.v.thing.component};
            if (Symbol * symbol{name.symbol}) {
              if (IsProcedure(*symbol)) {
                SetProcFlag(name, *symbol, procFlag);
              }
            }
          },
      },
      std::get<parser::ProcedureDesignator>(call.t).u);
  const auto &arguments{std::get<std::list<parser::ActualArgSpec>>(call.t)};
  Walk(arguments);
  // Once an object has appeared in a specification function reference as
  // a whole scalar actual argument, it cannot be (re)dimensioned later.
  // The fact that it appeared to be a scalar may determine the resolution
  // or the result of an inquiry intrinsic function or generic procedure.
  if (inSpecificationPart_) {
    for (const auto &argSpec : arguments) {
      const auto &actual{std::get<parser::ActualArg>(argSpec.t)};
      if (const auto *expr{
              std::get_if<common::Indirection<parser::Expr>>(&actual.u)}) {
        if (const auto *designator{
                std::get_if<common::Indirection<parser::Designator>>(
                    &expr->value().u)}) {
          if (const auto *dataRef{
                  std::get_if<parser::DataRef>(&designator->value().u)}) {
            if (const auto *name{std::get_if<parser::Name>(&dataRef->u)};
                name && name->symbol) {
              const Symbol &symbol{*name->symbol};
              const auto *object{symbol.detailsIf<ObjectEntityDetails>()};
              if (symbol.has<EntityDetails>() ||
                  (object && !object->IsArray())) {
                NoteScalarSpecificationArgument(symbol);
              }
            }
          }
        }
      }
    }
  }
}

void ResolveNamesVisitor::HandleProcedureName(
    Symbol::Flag flag, const parser::Name &name) {
  CHECK(flag == Symbol::Flag::Function || flag == Symbol::Flag::Subroutine);
  auto *symbol{FindSymbol(NonDerivedTypeScope(), name)};
  if (!symbol) {
    if (IsIntrinsic(name.source, flag)) {
      symbol = &MakeSymbol(InclusiveScope(), name.source, Attrs{});
      SetImplicitAttr(*symbol, Attr::INTRINSIC);
    } else if (const auto ppcBuiltinScope =
                   currScope().context().GetPPCBuiltinsScope()) {
      // Check if it is a builtin from the predefined module
      symbol = FindSymbol(*ppcBuiltinScope, name);
      if (!symbol) {
        symbol = &MakeSymbol(context().globalScope(), name.source, Attrs{});
      }
    } else {
      symbol = &MakeSymbol(context().globalScope(), name.source, Attrs{});
    }
    Resolve(name, *symbol);
    ConvertToProcEntity(*symbol, name.source);
    if (!symbol->attrs().test(Attr::INTRINSIC)) {
      if (CheckImplicitNoneExternal(name.source, *symbol)) {
        MakeExternal(*symbol);
        // Create a place-holder HostAssocDetails symbol to preclude later
        // use of this name as a local symbol; but don't actually use this new
        // HostAssocDetails symbol in expressions.
        MakeHostAssocSymbol(name, *symbol);
        name.symbol = symbol;
      }
    }
    CheckEntryDummyUse(name.source, symbol);
    SetProcFlag(name, *symbol, flag);
  } else if (CheckUseError(name)) {
    // error was reported
  } else {
    symbol = &symbol->GetUltimate();
    if (!name.symbol ||
        (name.symbol->has<HostAssocDetails>() && symbol->owner().IsGlobal() &&
            (symbol->has<ProcEntityDetails>() ||
                (symbol->has<SubprogramDetails>() &&
                    symbol->scope() /*not ENTRY*/)))) {
      name.symbol = symbol;
    }
    CheckEntryDummyUse(name.source, symbol);
    bool convertedToProcEntity{ConvertToProcEntity(*symbol, name.source)};
    if (convertedToProcEntity && !symbol->attrs().test(Attr::EXTERNAL) &&
        IsIntrinsic(symbol->name(), flag) && !IsDummy(*symbol)) {
      AcquireIntrinsicProcedureFlags(*symbol);
    }
    if (!SetProcFlag(name, *symbol, flag)) {
      return; // reported error
    }
    CheckImplicitNoneExternal(name.source, *symbol);
    if (IsProcedure(*symbol) || symbol->has<DerivedTypeDetails>() ||
        symbol->has<AssocEntityDetails>()) {
      // Symbols with DerivedTypeDetails and AssocEntityDetails are accepted
      // here as procedure-designators because this means the related
      // FunctionReference are mis-parsed structure constructors or array
      // references that will be fixed later when analyzing expressions.
    } else if (symbol->has<ObjectEntityDetails>()) {
      // Symbols with ObjectEntityDetails are also accepted because this can be
      // a mis-parsed array reference that will be fixed later. Ensure that if
      // this is a symbol from a host procedure, a symbol with HostAssocDetails
      // is created for the current scope.
      // Operate on non ultimate symbol so that HostAssocDetails are also
      // created for symbols used associated in the host procedure.
      ResolveName(name);
    } else if (symbol->test(Symbol::Flag::Implicit)) {
      Say(name,
          "Use of '%s' as a procedure conflicts with its implicit definition"_err_en_US);
    } else {
      SayWithDecl(name, *symbol,
          "Use of '%s' as a procedure conflicts with its declaration"_err_en_US);
    }
  }
}

bool ResolveNamesVisitor::CheckImplicitNoneExternal(
    const SourceName &name, const Symbol &symbol) {
  if (symbol.has<ProcEntityDetails>() && isImplicitNoneExternal() &&
      !symbol.attrs().test(Attr::EXTERNAL) &&
      !symbol.attrs().test(Attr::INTRINSIC) && !symbol.HasExplicitInterface()) {
    Say(name,
        "'%s' is an external procedure without the EXTERNAL attribute in a scope with IMPLICIT NONE(EXTERNAL)"_err_en_US);
    return false;
  }
  return true;
}

// Variant of HandleProcedureName() for use while skimming the executable
// part of a subprogram to catch calls to dummy procedures that are part
// of the subprogram's interface, and to mark as procedures any symbols
// that might otherwise have been miscategorized as objects.
void ResolveNamesVisitor::NoteExecutablePartCall(
    Symbol::Flag flag, SourceName name, bool hasCUDAChevrons) {
  // Subtlety: The symbol pointers in the parse tree are not set, because
  // they might end up resolving elsewhere (e.g., construct entities in
  // SELECT TYPE).
  if (Symbol * symbol{currScope().FindSymbol(name)}) {
    Symbol::Flag other{flag == Symbol::Flag::Subroutine
            ? Symbol::Flag::Function
            : Symbol::Flag::Subroutine};
    if (!symbol->test(other)) {
      ConvertToProcEntity(*symbol, name);
      if (auto *details{symbol->detailsIf<ProcEntityDetails>()}) {
        symbol->set(flag);
        if (IsDummy(*symbol)) {
          SetImplicitAttr(*symbol, Attr::EXTERNAL);
        }
        ApplyImplicitRules(*symbol);
        if (hasCUDAChevrons) {
          details->set_isCUDAKernel();
        }
      }
    }
  }
}

static bool IsLocallyImplicitGlobalSymbol(
    const Symbol &symbol, const parser::Name &localName) {
  if (symbol.owner().IsGlobal()) {
    const auto *subp{symbol.detailsIf<SubprogramDetails>()};
    const Scope *scope{
        subp && subp->entryScope() ? subp->entryScope() : symbol.scope()};
    return !(scope && scope->sourceRange().Contains(localName.source));
  }
  return false;
}

static bool TypesMismatchIfNonNull(
    const DeclTypeSpec *type1, const DeclTypeSpec *type2) {
  return type1 && type2 && *type1 != *type2;
}

// Check and set the Function or Subroutine flag on symbol; false on error.
bool ResolveNamesVisitor::SetProcFlag(
    const parser::Name &name, Symbol &symbol, Symbol::Flag flag) {
  if (symbol.test(Symbol::Flag::Function) && flag == Symbol::Flag::Subroutine) {
    SayWithDecl(
        name, symbol, "Cannot call function '%s' like a subroutine"_err_en_US);
    context().SetError(symbol);
    return false;
  } else if (symbol.test(Symbol::Flag::Subroutine) &&
      flag == Symbol::Flag::Function) {
    SayWithDecl(
        name, symbol, "Cannot call subroutine '%s' like a function"_err_en_US);
    context().SetError(symbol);
    return false;
  } else if (flag == Symbol::Flag::Function &&
      IsLocallyImplicitGlobalSymbol(symbol, name) &&
      TypesMismatchIfNonNull(symbol.GetType(), GetImplicitType(symbol))) {
    SayWithDecl(name, symbol,
        "Implicit declaration of function '%s' has a different result type than in previous declaration"_err_en_US);
    return false;
  } else if (symbol.has<ProcEntityDetails>()) {
    symbol.set(flag); // in case it hasn't been set yet
    if (flag == Symbol::Flag::Function) {
      ApplyImplicitRules(symbol);
    }
    if (symbol.attrs().test(Attr::INTRINSIC)) {
      AcquireIntrinsicProcedureFlags(symbol);
    }
  } else if (symbol.GetType() && flag == Symbol::Flag::Subroutine) {
    SayWithDecl(
        name, symbol, "Cannot call function '%s' like a subroutine"_err_en_US);
    context().SetError(symbol);
  } else if (symbol.attrs().test(Attr::INTRINSIC)) {
    AcquireIntrinsicProcedureFlags(symbol);
  }
  return true;
}

bool ModuleVisitor::Pre(const parser::AccessStmt &x) {
  Attr accessAttr{AccessSpecToAttr(std::get<parser::AccessSpec>(x.t))};
  if (!currScope().IsModule()) { // C869
    Say(currStmtSource().value(),
        "%s statement may only appear in the specification part of a module"_err_en_US,
        EnumToString(accessAttr));
    return false;
  }
  const auto &accessIds{std::get<std::list<parser::AccessId>>(x.t)};
  if (accessIds.empty()) {
    if (prevAccessStmt_) { // C869
      Say("The default accessibility of this module has already been declared"_err_en_US)
          .Attach(*prevAccessStmt_, "Previous declaration"_en_US);
    }
    prevAccessStmt_ = currStmtSource();
    auto *moduleDetails{DEREF(currScope().symbol()).detailsIf<ModuleDetails>()};
    DEREF(moduleDetails).set_isDefaultPrivate(accessAttr == Attr::PRIVATE);
  } else {
    for (const auto &accessId : accessIds) {
      GenericSpecInfo info{accessId.v.value()};
      auto *symbol{FindInScope(info.symbolName())};
      if (!symbol && !info.kind().IsName()) {
        symbol = &MakeSymbol(info.symbolName(), Attrs{}, GenericDetails{});
      }
      info.Resolve(&SetAccess(info.symbolName(), accessAttr, symbol));
    }
  }
  return false;
}

// Set the access specification for this symbol.
Symbol &ModuleVisitor::SetAccess(
    const SourceName &name, Attr attr, Symbol *symbol) {
  if (!symbol) {
    symbol = &MakeSymbol(name);
  }
  Attrs &attrs{symbol->attrs()};
  if (attrs.HasAny({Attr::PUBLIC, Attr::PRIVATE})) {
    // PUBLIC/PRIVATE already set: make it a fatal error if it changed
    Attr prev = attrs.test(Attr::PUBLIC) ? Attr::PUBLIC : Attr::PRIVATE;
    Say(name,
        WithSeverity(
            "The accessibility of '%s' has already been specified as %s"_warn_en_US,
            attr != prev ? parser::Severity::Error : parser::Severity::Warning),
        MakeOpName(name), EnumToString(prev));
  } else {
    attrs.set(attr);
  }
  return *symbol;
}

static bool NeedsExplicitType(const Symbol &symbol) {
  if (symbol.has<UnknownDetails>()) {
    return true;
  } else if (const auto *details{symbol.detailsIf<EntityDetails>()}) {
    return !details->type();
  } else if (const auto *details{symbol.detailsIf<ObjectEntityDetails>()}) {
    return !details->type();
  } else if (const auto *details{symbol.detailsIf<ProcEntityDetails>()}) {
    return !details->procInterface() && !details->type();
  } else {
    return false;
  }
}

void ResolveNamesVisitor::HandleDerivedTypesInImplicitStmts(
    const parser::ImplicitPart &implicitPart,
    const std::list<parser::DeclarationConstruct> &decls) {
  // Detect derived type definitions and create symbols for them now if
  // they appear in IMPLICIT statements so that these forward-looking
  // references will not be ambiguous with host associations.
  std::set<SourceName> implicitDerivedTypes;
  for (const auto &ipStmt : implicitPart.v) {
    if (const auto *impl{std::get_if<
            parser::Statement<common::Indirection<parser::ImplicitStmt>>>(
            &ipStmt.u)}) {
      if (const auto *specs{std::get_if<std::list<parser::ImplicitSpec>>(
              &impl->statement.value().u)}) {
        for (const auto &spec : *specs) {
          const auto &declTypeSpec{
              std::get<parser::DeclarationTypeSpec>(spec.t)};
          if (const auto *dtSpec{common::visit(
                  common::visitors{
                      [](const parser::DeclarationTypeSpec::Type &x) {
                        return &x.derived;
                      },
                      [](const parser::DeclarationTypeSpec::Class &x) {
                        return &x.derived;
                      },
                      [](const auto &) -> const parser::DerivedTypeSpec * {
                        return nullptr;
                      }},
                  declTypeSpec.u)}) {
            implicitDerivedTypes.emplace(
                std::get<parser::Name>(dtSpec->t).source);
          }
        }
      }
    }
  }
  if (!implicitDerivedTypes.empty()) {
    for (const auto &decl : decls) {
      if (const auto *spec{
              std::get_if<parser::SpecificationConstruct>(&decl.u)}) {
        if (const auto *dtDef{
                std::get_if<common::Indirection<parser::DerivedTypeDef>>(
                    &spec->u)}) {
          const parser::DerivedTypeStmt &dtStmt{
              std::get<parser::Statement<parser::DerivedTypeStmt>>(
                  dtDef->value().t)
                  .statement};
          const parser::Name &name{std::get<parser::Name>(dtStmt.t)};
          if (implicitDerivedTypes.find(name.source) !=
                  implicitDerivedTypes.end() &&
              !FindInScope(name)) {
            DerivedTypeDetails details;
            details.set_isForwardReferenced(true);
            Resolve(name, MakeSymbol(name, std::move(details)));
            implicitDerivedTypes.erase(name.source);
          }
        }
      }
    }
  }
}

bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
  const auto &[accDecls, ompDecls, compilerDirectives, useStmts, importStmts,
      implicitPart, decls] = x.t;
  auto flagRestorer{common::ScopedSet(inSpecificationPart_, true)};
  auto stateRestorer{
      common::ScopedSet(specPartState_, SpecificationPartState{})};
  Walk(accDecls);
  Walk(ompDecls);
  Walk(compilerDirectives);
  for (const auto &useStmt : useStmts) {
    CollectUseRenames(useStmt.statement.value());
  }
  Walk(useStmts);
  UseCUDABuiltinNames();
  ClearUseRenames();
  ClearUseOnly();
  ClearModuleUses();
  Walk(importStmts);
  HandleDerivedTypesInImplicitStmts(implicitPart, decls);
  Walk(implicitPart);
  for (const auto &decl : decls) {
    if (const auto *spec{
            std::get_if<parser::SpecificationConstruct>(&decl.u)}) {
      PreSpecificationConstruct(*spec);
    }
  }
  Walk(decls);
  FinishSpecificationPart(decls);
  return false;
}

void ResolveNamesVisitor::UseCUDABuiltinNames() {
  if (FindCUDADeviceContext(&currScope())) {
    for (const auto &[name, symbol] : context().GetCUDABuiltinsScope()) {
      if (!FindInScope(name)) {
        auto &localSymbol{MakeSymbol(name)};
        localSymbol.set_details(UseDetails{name, *symbol});
        localSymbol.flags() = symbol->flags();
      }
    }
  }
}

// Initial processing on specification constructs, before visiting them.
void ResolveNamesVisitor::PreSpecificationConstruct(
    const parser::SpecificationConstruct &spec) {
  common::visit(
      common::visitors{
          [&](const parser::Statement<Indirection<parser::GenericStmt>> &y) {
            CreateGeneric(std::get<parser::GenericSpec>(y.statement.value().t));
          },
          [&](const Indirection<parser::InterfaceBlock> &y) {
            const auto &stmt{std::get<parser::Statement<parser::InterfaceStmt>>(
                y.value().t)};
            if (const auto *spec{parser::Unwrap<parser::GenericSpec>(stmt)}) {
              CreateGeneric(*spec);
            }
          },
          [&](const parser::Statement<parser::OtherSpecificationStmt> &y) {
            if (const auto *commonStmt{parser::Unwrap<parser::CommonStmt>(y)}) {
              CreateCommonBlockSymbols(*commonStmt);
            }
          },
          [&](const auto &) {},
      },
      spec.u);
}

void ResolveNamesVisitor::CreateCommonBlockSymbols(
    const parser::CommonStmt &commonStmt) {
  for (const parser::CommonStmt::Block &block : commonStmt.blocks) {
    const auto &[name, objects] = block.t;
    Symbol &commonBlock{MakeCommonBlockSymbol(name)};
    for (const auto &object : objects) {
      Symbol &obj{DeclareObjectEntity(std::get<parser::Name>(object.t))};
      if (auto *details{obj.detailsIf<ObjectEntityDetails>()}) {
        details->set_commonBlock(commonBlock);
        commonBlock.get<CommonBlockDetails>().add_object(obj);
      }
    }
  }
}

void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) {
  auto info{GenericSpecInfo{x}};
  SourceName symbolName{info.symbolName()};
  if (IsLogicalConstant(context(), symbolName)) {
    Say(symbolName,
        "Logical constant '%s' may not be used as a defined operator"_err_en_US);
    return;
  }
  GenericDetails genericDetails;
  Symbol *existing{nullptr};
  // Check all variants of names, e.g. "operator(.ne.)" for "operator(/=)"
  for (const std::string &n : GetAllNames(context(), symbolName)) {
    existing = currScope().FindSymbol(SourceName{n});
    if (existing) {
      break;
    }
  }
  if (existing) {
    Symbol &ultimate{existing->GetUltimate()};
    if (auto *existingGeneric{ultimate.detailsIf<GenericDetails>()}) {
      if (&existing->owner() == &currScope()) {
        if (const auto *existingUse{existing->detailsIf<UseDetails>()}) {
          // Create a local copy of a use associated generic so that
          // it can be locally extended without corrupting the original.
          genericDetails.CopyFrom(*existingGeneric);
          if (existingGeneric->specific()) {
            genericDetails.set_specific(*existingGeneric->specific());
          }
          AddGenericUse(
              genericDetails, existing->name(), existingUse->symbol());
        } else if (existing == &ultimate) {
          // Extending an extant generic in the same scope
          info.Resolve(existing);
          return;
        } else {
          // Host association of a generic is handled elsewhere
          CHECK(existing->has<HostAssocDetails>());
        }
      } else {
        // Create a new generic for this scope.
      }
    } else if (ultimate.has<SubprogramDetails>() ||
        ultimate.has<SubprogramNameDetails>()) {
      genericDetails.set_specific(*existing);
    } else if (ultimate.has<ProcEntityDetails>()) {
      if (existing->name() != symbolName ||
          !ultimate.attrs().test(Attr::INTRINSIC)) {
        genericDetails.set_specific(*existing);
      }
    } else if (ultimate.has<DerivedTypeDetails>()) {
      genericDetails.set_derivedType(*existing);
    } else if (&existing->owner() == &currScope()) {
      SayAlreadyDeclared(symbolName, *existing);
      return;
    }
    if (&existing->owner() == &currScope()) {
      EraseSymbol(*existing);
    }
  }
  info.Resolve(&MakeSymbol(symbolName, Attrs{}, std::move(genericDetails)));
}

void ResolveNamesVisitor::FinishSpecificationPart(
    const std::list<parser::DeclarationConstruct> &decls) {
  misparsedStmtFuncFound_ = false;
  funcResultStack().CompleteFunctionResultType();
  CheckImports();
  for (auto &pair : currScope()) {
    auto &symbol{*pair.second};
    if (NeedsExplicitType(symbol)) {
      ApplyImplicitRules(symbol);
    }
    if (IsDummy(symbol) && isImplicitNoneType() &&
        symbol.test(Symbol::Flag::Implicit) && !context().HasError(symbol)) {
      Say(symbol.name(),
          "No explicit type declared for dummy argument '%s'"_err_en_US);
      context().SetError(symbol);
    }
    if (symbol.has<GenericDetails>()) {
      CheckGenericProcedures(symbol);
    }
    if (!symbol.has<HostAssocDetails>()) {
      CheckPossibleBadForwardRef(symbol);
    }
  }
  currScope().InstantiateDerivedTypes();
  for (const auto &decl : decls) {
    if (const auto *statement{std::get_if<
            parser::Statement<common::Indirection<parser::StmtFunctionStmt>>>(
            &decl.u)}) {
      messageHandler().set_currStmtSource(statement->source);
      AnalyzeStmtFunctionStmt(statement->statement.value());
    }
  }
  // TODO: what about instantiations in BLOCK?
  CheckSaveStmts();
  CheckCommonBlocks();
  if (!inInterfaceBlock()) {
    // TODO: warn for the case where the EQUIVALENCE statement is in a
    // procedure declaration in an interface block
    CheckEquivalenceSets();
  }
}

// Analyze the bodies of statement functions now that the symbols in this
// specification part have been fully declared and implicitly typed.
// (Statement function references are not allowed in specification
// expressions, so it's safe to defer processing their definitions.)
void ResolveNamesVisitor::AnalyzeStmtFunctionStmt(
    const parser::StmtFunctionStmt &stmtFunc) {
  const auto &name{std::get<parser::Name>(stmtFunc.t)};
  Symbol *symbol{name.symbol};
  auto *details{symbol ? symbol->detailsIf<SubprogramDetails>() : nullptr};
  if (!details || !symbol->scope() ||
      &symbol->scope()->parent() != &currScope() || details->isInterface() ||
      details->isDummy() || details->entryScope() ||
      details->moduleInterface() || symbol->test(Symbol::Flag::Subroutine)) {
    return; // error recovery
  }
  // Resolve the symbols on the RHS of the statement function.
  PushScope(*symbol->scope());
  const auto &parsedExpr{std::get<parser::Scalar<parser::Expr>>(stmtFunc.t)};
  Walk(parsedExpr);
  PopScope();
  if (auto expr{AnalyzeExpr(context(), stmtFunc)}) {
    if (auto type{evaluate::DynamicType::From(*symbol)}) {
      if (auto converted{evaluate::ConvertToType(*type, std::move(*expr))}) {
        details->set_stmtFunction(std::move(*converted));
      } else {
        Say(name.source,
            "Defining expression of statement function '%s' cannot be converted to its result type %s"_err_en_US,
            name.source, type->AsFortran());
      }
    } else {
      details->set_stmtFunction(std::move(*expr));
    }
  }
  if (!details->stmtFunction()) {
    context().SetError(*symbol);
  }
}

void ResolveNamesVisitor::CheckImports() {
  auto &scope{currScope()};
  switch (scope.GetImportKind()) {
  case common::ImportKind::None:
    break;
  case common::ImportKind::All:
    // C8102: all entities in host must not be hidden
    for (const auto &pair : scope.parent()) {
      auto &name{pair.first};
      std::optional<SourceName> scopeName{scope.GetName()};
      if (!scopeName || name != *scopeName) {
        CheckImport(prevImportStmt_.value(), name);
      }
    }
    break;
  case common::ImportKind::Default:
  case common::ImportKind::Only:
    // C8102: entities named in IMPORT must not be hidden
    for (auto &name : scope.importNames()) {
      CheckImport(name, name);
    }
    break;
  }
}

void ResolveNamesVisitor::CheckImport(
    const SourceName &location, const SourceName &name) {
  if (auto *symbol{FindInScope(name)}) {
    const Symbol &ultimate{symbol->GetUltimate()};
    if (&ultimate.owner() == &currScope()) {
      Say(location, "'%s' from host is not accessible"_err_en_US, name)
          .Attach(symbol->name(), "'%s' is hidden by this entity"_because_en_US,
              symbol->name());
    }
  }
}

bool ResolveNamesVisitor::Pre(const parser::ImplicitStmt &x) {
  return CheckNotInBlock("IMPLICIT") && // C1107
      ImplicitRulesVisitor::Pre(x);
}

void ResolveNamesVisitor::Post(const parser::PointerObject &x) {
  common::visit(common::visitors{
                    [&](const parser::Name &x) { ResolveName(x); },
                    [&](const parser::StructureComponent &x) {
                      ResolveStructureComponent(x);
                    },
                },
      x.u);
}
void ResolveNamesVisitor::Post(const parser::AllocateObject &x) {
  common::visit(common::visitors{
                    [&](const parser::Name &x) { ResolveName(x); },
                    [&](const parser::StructureComponent &x) {
                      ResolveStructureComponent(x);
                    },
                },
      x.u);
}

bool ResolveNamesVisitor::Pre(const parser::PointerAssignmentStmt &x) {
  const auto &dataRef{std::get<parser::DataRef>(x.t)};
  const auto &bounds{std::get<parser::PointerAssignmentStmt::Bounds>(x.t)};
  const auto &expr{std::get<parser::Expr>(x.t)};
  ResolveDataRef(dataRef);
  Symbol *ptrSymbol{parser::GetLastName(dataRef).symbol};
  Walk(bounds);
  // Resolve unrestricted specific intrinsic procedures as in "p => cos".
  if (const parser::Name * name{parser::Unwrap<parser::Name>(expr)}) {
    if (NameIsKnownOrIntrinsic(*name)) {
      if (Symbol * symbol{name->symbol}) {
        if (IsProcedurePointer(ptrSymbol) &&
            !ptrSymbol->test(Symbol::Flag::Function) &&
            !ptrSymbol->test(Symbol::Flag::Subroutine)) {
          if (symbol->test(Symbol::Flag::Function)) {
            ApplyImplicitRules(*ptrSymbol);
          }
        }
        // If the name is known because it is an object entity from a host
        // procedure, create a host associated symbol.
        if (symbol->GetUltimate().has<ObjectEntityDetails>() &&
            IsUplevelReference(*symbol)) {
          MakeHostAssocSymbol(*name, *symbol);
        }
      }
      return false;
    }
    // Can also reference a global external procedure here
    if (auto it{context().globalScope().find(name->source)};
        it != context().globalScope().end()) {
      Symbol &global{*it->second};
      if (IsProcedure(global)) {
        Resolve(*name, global);
        return false;
      }
    }
    if (IsProcedurePointer(parser::GetLastName(dataRef).symbol) &&
        !FindSymbol(*name)) {
      // Unknown target of procedure pointer must be an external procedure
      Symbol &symbol{MakeSymbol(
          context().globalScope(), name->source, Attrs{Attr::EXTERNAL})};
      symbol.implicitAttrs().set(Attr::EXTERNAL);
      Resolve(*name, symbol);
      ConvertToProcEntity(symbol, name->source);
      return false;
    }
  }
  Walk(expr);
  return false;
}
void ResolveNamesVisitor::Post(const parser::Designator &x) {
  ResolveDesignator(x);
}
void ResolveNamesVisitor::Post(const parser::SubstringInquiry &x) {
  Walk(std::get<parser::SubstringRange>(x.v.t).t);
  ResolveDataRef(std::get<parser::DataRef>(x.v.t));
}

void ResolveNamesVisitor::Post(const parser::ProcComponentRef &x) {
  ResolveStructureComponent(x.v.thing);
}
void ResolveNamesVisitor::Post(const parser::TypeGuardStmt &x) {
  DeclTypeSpecVisitor::Post(x);
  ConstructVisitor::Post(x);
}
bool ResolveNamesVisitor::Pre(const parser::StmtFunctionStmt &x) {
  if (HandleStmtFunction(x)) {
    return false;
  } else {
    // This is an array element or pointer-valued function assignment:
    // resolve the names of indices/arguments
    const auto &names{std::get<std::list<parser::Name>>(x.t)};
    for (auto &name : names) {
      ResolveName(name);
    }
    return true;
  }
}

bool ResolveNamesVisitor::Pre(const parser::DefinedOpName &x) {
  const parser::Name &name{x.v};
  if (FindSymbol(name)) {
    // OK
  } else if (IsLogicalConstant(context(), name.source)) {
    Say(name,
        "Logical constant '%s' may not be used as a defined operator"_err_en_US);
  } else {
    // Resolved later in expression semantics
    MakePlaceholder(name, MiscDetails::Kind::TypeBoundDefinedOp);
  }
  return false;
}

void ResolveNamesVisitor::Post(const parser::AssignStmt &x) {
  if (auto *name{ResolveName(std::get<parser::Name>(x.t))}) {
    CheckEntryDummyUse(name->source, name->symbol);
    ConvertToObjectEntity(DEREF(name->symbol));
  }
}
void ResolveNamesVisitor::Post(const parser::AssignedGotoStmt &x) {
  if (auto *name{ResolveName(std::get<parser::Name>(x.t))}) {
    CheckEntryDummyUse(name->source, name->symbol);
    ConvertToObjectEntity(DEREF(name->symbol));
  }
}

void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
  if (const auto *tkr{
          std::get_if<std::list<parser::CompilerDirective::IgnoreTKR>>(&x.u)}) {
    if (currScope().IsTopLevel() ||
        GetProgramUnitContaining(currScope()).kind() !=
            Scope::Kind::Subprogram) {
      Say(x.source,
          "!DIR$ IGNORE_TKR directive must appear in a subroutine or function"_err_en_US);
      return;
    }
    if (!inSpecificationPart_) {
      Say(x.source,
          "!DIR$ IGNORE_TKR directive must appear in the specification part"_err_en_US);
      return;
    }
    if (tkr->empty()) {
      Symbol *symbol{currScope().symbol()};
      if (SubprogramDetails *
          subp{symbol ? symbol->detailsIf<SubprogramDetails>() : nullptr}) {
        subp->set_defaultIgnoreTKR(true);
      }
    } else {
      for (const parser::CompilerDirective::IgnoreTKR &item : *tkr) {
        common::IgnoreTKRSet set;
        if (const auto &maybeList{
                std::get<std::optional<std::list<const char *>>>(item.t)}) {
          for (const char *p : *maybeList) {
            if (p) {
              switch (*p) {
              case 't':
                set.set(common::IgnoreTKR::Type);
                break;
              case 'k':
                set.set(common::IgnoreTKR::Kind);
                break;
              case 'r':
                set.set(common::IgnoreTKR::Rank);
                break;
              case 'd':
                set.set(common::IgnoreTKR::Device);
                break;
              case 'm':
                set.set(common::IgnoreTKR::Managed);
                break;
              case 'c':
                set.set(common::IgnoreTKR::Contiguous);
                break;
              case 'a':
                set = common::ignoreTKRAll;
                break;
              default:
                Say(x.source,
                    "'%c' is not a valid letter for !DIR$ IGNORE_TKR directive"_err_en_US,
                    *p);
                set = common::ignoreTKRAll;
                break;
              }
            }
          }
          if (set.empty()) {
            Say(x.source,
                "!DIR$ IGNORE_TKR directive may not have an empty parenthesized list of letters"_err_en_US);
          }
        } else { // no (list)
          set = common::ignoreTKRAll;
          ;
        }
        const auto &name{std::get<parser::Name>(item.t)};
        Symbol *symbol{FindSymbol(name)};
        if (!symbol) {
          symbol = &MakeSymbol(name, Attrs{}, ObjectEntityDetails{});
        }
        if (symbol->owner() != currScope()) {
          SayWithDecl(
              name, *symbol, "'%s' must be local to this subprogram"_err_en_US);
        } else {
          ConvertToObjectEntity(*symbol);
          if (auto *object{symbol->detailsIf<ObjectEntityDetails>()}) {
            object->set_ignoreTKR(set);
          } else {
            SayWithDecl(name, *symbol, "'%s' must be an object"_err_en_US);
          }
        }
      }
    }
  } else {
    Say(x.source, "Compiler directive was ignored"_warn_en_US);
  }
}

bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) {
  if (std::holds_alternative<common::Indirection<parser::CompilerDirective>>(
          x.u)) {
    // TODO: global directives
    return true;
  }
  if (std::holds_alternative<
          common::Indirection<parser::OpenACCRoutineConstruct>>(x.u)) {
    ResolveAccParts(context(), x, &topScope_);
    return false;
  }
  auto root{ProgramTree::Build(x)};
  SetScope(topScope_);
  ResolveSpecificationParts(root);
  FinishSpecificationParts(root);
  ResolveExecutionParts(root);
  FinishExecutionParts(root);
  ResolveAccParts(context(), x);
  ResolveOmpParts(context(), x);
  return false;
}

template <typename A> std::set<SourceName> GetUses(const A &x) {
  std::set<SourceName> uses;
  if constexpr (!std::is_same_v<A, parser::CompilerDirective> &&
      !std::is_same_v<A, parser::OpenACCRoutineConstruct>) {
    const auto &spec{std::get<parser::SpecificationPart>(x.t)};
    const auto &unitUses{std::get<
        std::list<parser::Statement<common::Indirection<parser::UseStmt>>>>(
        spec.t)};
    for (const auto &u : unitUses) {
      uses.insert(u.statement.value().moduleName.source);
    }
  }
  return uses;
}

bool ResolveNamesVisitor::Pre(const parser::Program &x) {
  std::map<SourceName, const parser::ProgramUnit *> modules;
  std::set<SourceName> uses;
  bool disordered{false};
  for (const auto &progUnit : x.v) {
    if (const auto *indMod{
            std::get_if<common::Indirection<parser::Module>>(&progUnit.u)}) {
      const parser::Module &mod{indMod->value()};
      const auto &moduleStmt{
          std::get<parser::Statement<parser::ModuleStmt>>(mod.t)};
      const SourceName &name{moduleStmt.statement.v.source};
      if (auto iter{modules.find(name)}; iter != modules.end()) {
        Say(name,
            "Module '%s' appears multiple times in a compilation unit"_err_en_US)
            .Attach(iter->first, "First definition of module"_en_US);
        return true;
      }
      modules.emplace(name, &progUnit);
      if (auto iter{uses.find(name)}; iter != uses.end()) {
        if (context().ShouldWarn(common::LanguageFeature::MiscUseExtensions)) {
          Say(name,
              "A USE statement referencing module '%s' appears earlier in this compilation unit"_port_en_US)
              .Attach(*iter, "First USE of module"_en_US);
        }
        disordered = true;
      }
    }
    for (SourceName used : common::visit(
             [](const auto &indUnit) { return GetUses(indUnit.value()); },
             progUnit.u)) {
      uses.insert(used);
    }
  }
  if (!disordered) {
    return true;
  }
  // Process modules in topological order
  std::vector<const parser::ProgramUnit *> moduleOrder;
  while (!modules.empty()) {
    bool ok;
    for (const auto &pair : modules) {
      const SourceName &name{pair.first};
      const parser::ProgramUnit &progUnit{*pair.second};
      const parser::Module &m{
          std::get<common::Indirection<parser::Module>>(progUnit.u).value()};
      ok = true;
      for (const SourceName &use : GetUses(m)) {
        if (modules.find(use) != modules.end()) {
          ok = false;
          break;
        }
      }
      if (ok) {
        moduleOrder.push_back(&progUnit);
        modules.erase(name);
        break;
      }
    }
    if (!ok) {
      parser::Message *msg{nullptr};
      for (const auto &pair : modules) {
        if (msg) {
          msg->Attach(pair.first, "Module in a cycle"_en_US);
        } else {
          msg = &Say(pair.first,
              "Some modules in this compilation unit form one or more cycles of dependence"_err_en_US);
        }
      }
      return false;
    }
  }
  // Modules can be ordered.  Process them first, and then all of the other
  // program units.
  for (const parser::ProgramUnit *progUnit : moduleOrder) {
    Walk(*progUnit);
  }
  for (const auto &progUnit : x.v) {
    if (!std::get_if<common::Indirection<parser::Module>>(&progUnit.u)) {
      Walk(progUnit);
    }
  }
  return false;
}

// References to procedures need to record that their symbols are known
// to be procedures, so that they don't get converted to objects by default.
class ExecutionPartCallSkimmer : public ExecutionPartSkimmerBase {
public:
  explicit ExecutionPartCallSkimmer(ResolveNamesVisitor &resolver)
      : resolver_{resolver} {}

  void Walk(const parser::ExecutionPart &exec) {
    parser::Walk(exec, *this);
    EndWalk();
  }

  using ExecutionPartSkimmerBase::Post;
  using ExecutionPartSkimmerBase::Pre;

  void Post(const parser::FunctionReference &fr) {
    NoteCall(Symbol::Flag::Function, fr.v, false);
  }
  void Post(const parser::CallStmt &cs) {
    NoteCall(Symbol::Flag::Subroutine, cs.call, cs.chevrons.has_value());
  }

private:
  void NoteCall(
      Symbol::Flag flag, const parser::Call &call, bool hasCUDAChevrons) {
    auto &designator{std::get<parser::ProcedureDesignator>(call.t)};
    if (const auto *name{std::get_if<parser::Name>(&designator.u)}) {
      if (!IsHidden(name->source)) {
        resolver_.NoteExecutablePartCall(flag, name->source, hasCUDAChevrons);
      }
    }
  }

  ResolveNamesVisitor &resolver_;
};

// Build the scope tree and resolve names in the specification parts of this
// node and its children
void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {
  if (node.isSpecificationPartResolved()) {
    return; // been here already
  }
  node.set_isSpecificationPartResolved();
  if (!BeginScopeForNode(node)) {
    return; // an error prevented scope from being created
  }
  Scope &scope{currScope()};
  node.set_scope(scope);
  AddSubpNames(node);
  common::visit(
      [&](const auto *x) {
        if (x) {
          Walk(*x);
        }
      },
      node.stmt());
  Walk(node.spec());
  // If this is a function, convert result to an object. This is to prevent the
  // result from being converted later to a function symbol if it is called
  // inside the function.
  // If the result is function pointer, then ConvertToObjectEntity will not
  // convert the result to an object, and calling the symbol inside the function
  // will result in calls to the result pointer.
  // A function cannot be called recursively if RESULT was not used to define a
  // distinct result name (15.6.2.2 point 4.).
  if (Symbol * symbol{scope.symbol()}) {
    if (auto *details{symbol->detailsIf<SubprogramDetails>()}) {
      if (details->isFunction()) {
        ConvertToObjectEntity(const_cast<Symbol &>(details->result()));
      }
    }
  }
  if (node.IsModule()) {
    ApplyDefaultAccess();
  }
  for (auto &child : node.children()) {
    ResolveSpecificationParts(child);
  }
  if (node.exec()) {
    ExecutionPartCallSkimmer{*this}.Walk(*node.exec());
    HandleImpliedAsynchronousInScope(node.exec()->v);
  }
  EndScopeForNode(node);
  // Ensure that every object entity has a type.
  bool inModule{node.GetKind() == ProgramTree::Kind::Module ||
      node.GetKind() == ProgramTree::Kind::Submodule};
  for (auto &pair : *node.scope()) {
    Symbol &symbol{*pair.second};
    if (inModule && symbol.attrs().test(Attr::EXTERNAL) &&
        !symbol.test(Symbol::Flag::Function) &&
        !symbol.test(Symbol::Flag::Subroutine)) {
      // in a module, external proc without return type is subroutine
      symbol.set(
          symbol.GetType() ? Symbol::Flag::Function : Symbol::Flag::Subroutine);
    }
    ApplyImplicitRules(symbol);
  }
}

// Add SubprogramNameDetails symbols for module and internal subprograms and
// their ENTRY statements.
void ResolveNamesVisitor::AddSubpNames(ProgramTree &node) {
  auto kind{
      node.IsModule() ? SubprogramKind::Module : SubprogramKind::Internal};
  for (auto &child : node.children()) {
    auto &symbol{MakeSymbol(child.name(), SubprogramNameDetails{kind, child})};
    if (child.HasModulePrefix()) {
      SetExplicitAttr(symbol, Attr::MODULE);
    }
    auto childKind{child.GetKind()};
    if (childKind == ProgramTree::Kind::Function) {
      symbol.set(Symbol::Flag::Function);
    } else if (childKind == ProgramTree::Kind::Subroutine) {
      symbol.set(Symbol::Flag::Subroutine);
    } else {
      continue; // make ENTRY symbols only where valid
    }
    for (const auto &entryStmt : child.entryStmts()) {
      SubprogramNameDetails details{kind, child};
      auto &symbol{
          MakeSymbol(std::get<parser::Name>(entryStmt->t), std::move(details))};
      symbol.set(child.GetSubpFlag());
      if (child.HasModulePrefix()) {
        SetExplicitAttr(symbol, Attr::MODULE);
      }
    }
  }
  for (const auto &generic : node.genericSpecs()) {
    if (const auto *name{std::get_if<parser::Name>(&generic->u)}) {
      if (currScope().find(name->source) != currScope().end()) {
        // If this scope has both a generic interface and a contained
        // subprogram with the same name, create the generic's symbol
        // now so that any other generics of the same name that are pulled
        // into scope later via USE association will properly merge instead
        // of raising a bogus error due a conflict with the subprogram.
        CreateGeneric(*generic);
      }
    }
  }
}

// Push a new scope for this node or return false on error.
bool ResolveNamesVisitor::BeginScopeForNode(const ProgramTree &node) {
  switch (node.GetKind()) {
    SWITCH_COVERS_ALL_CASES
  case ProgramTree::Kind::Program:
    PushScope(Scope::Kind::MainProgram,
        &MakeSymbol(node.name(), MainProgramDetails{}));
    return true;
  case ProgramTree::Kind::Function:
  case ProgramTree::Kind::Subroutine:
    return BeginSubprogram(node.name(), node.GetSubpFlag(),
        node.HasModulePrefix(), node.bindingSpec(), &node.entryStmts());
  case ProgramTree::Kind::MpSubprogram:
    return BeginMpSubprogram(node.name());
  case ProgramTree::Kind::Module:
    BeginModule(node.name(), false);
    return true;
  case ProgramTree::Kind::Submodule:
    return BeginSubmodule(node.name(), node.GetParentId());
  case ProgramTree::Kind::BlockData:
    PushBlockDataScope(node.name());
    return true;
  }
}

void ResolveNamesVisitor::EndScopeForNode(const ProgramTree &node) {
  std::optional<parser::CharBlock> stmtSource;
  const std::optional<parser::LanguageBindingSpec> *binding{nullptr};
  common::visit(
      common::visitors{
          [&](const parser::Statement<parser::FunctionStmt> *stmt) {
            if (stmt) {
              stmtSource = stmt->source;
              if (const auto &maybeSuffix{
                      std::get<std::optional<parser::Suffix>>(
                          stmt->statement.t)}) {
                binding = &maybeSuffix->binding;
              }
            }
          },
          [&](const parser::Statement<parser::SubroutineStmt> *stmt) {
            if (stmt) {
              stmtSource = stmt->source;
              binding = &std::get<std::optional<parser::LanguageBindingSpec>>(
                  stmt->statement.t);
            }
          },
          [](const auto *) {},
      },
      node.stmt());
  EndSubprogram(stmtSource, binding, &node.entryStmts());
}

// Some analyses and checks, such as the processing of initializers of
// pointers, are deferred until all of the pertinent specification parts
// have been visited.  This deferred processing enables the use of forward
// references in these circumstances.
// Data statement objects with implicit derived types are finally
// resolved here.
class DeferredCheckVisitor {
public:
  explicit DeferredCheckVisitor(ResolveNamesVisitor &resolver)
      : resolver_{resolver} {}

  template <typename A> void Walk(const A &x) { parser::Walk(x, *this); }

  template <typename A> bool Pre(const A &) { return true; }
  template <typename A> void Post(const A &) {}

  void Post(const parser::DerivedTypeStmt &x) {
    const auto &name{std::get<parser::Name>(x.t)};
    if (Symbol * symbol{name.symbol}) {
      if (Scope * scope{symbol->scope()}) {
        if (scope->IsDerivedType()) {
          CHECK(outerScope_ == nullptr);
          outerScope_ = &resolver_.currScope();
          resolver_.SetScope(*scope);
        }
      }
    }
  }
  void Post(const parser::EndTypeStmt &) {
    if (outerScope_) {
      resolver_.SetScope(*outerScope_);
      outerScope_ = nullptr;
    }
  }

  void Post(const parser::ProcInterface &pi) {
    if (const auto *name{std::get_if<parser::Name>(&pi.u)}) {
      resolver_.CheckExplicitInterface(*name);
    }
  }
  bool Pre(const parser::EntityDecl &decl) {
    Init(std::get<parser::Name>(decl.t),
        std::get<std::optional<parser::Initialization>>(decl.t));
    return false;
  }
  bool Pre(const parser::ComponentDecl &decl) {
    Init(std::get<parser::Name>(decl.t),
        std::get<std::optional<parser::Initialization>>(decl.t));
    return false;
  }
  bool Pre(const parser::ProcDecl &decl) {
    if (const auto &init{
            std::get<std::optional<parser::ProcPointerInit>>(decl.t)}) {
      resolver_.PointerInitialization(std::get<parser::Name>(decl.t), *init);
    }
    return false;
  }
  void Post(const parser::TypeBoundProcedureStmt::WithInterface &tbps) {
    resolver_.CheckExplicitInterface(tbps.interfaceName);
  }
  void Post(const parser::TypeBoundProcedureStmt::WithoutInterface &tbps) {
    if (outerScope_) {
      resolver_.CheckBindings(tbps);
    }
  }
  bool Pre(const parser::DataStmtObject &) {
    ++dataStmtObjectNesting_;
    return true;
  }
  void Post(const parser::DataStmtObject &) { --dataStmtObjectNesting_; }
  void Post(const parser::Designator &x) {
    if (dataStmtObjectNesting_ > 0) {
      resolver_.ResolveDesignator(x);
    }
  }

private:
  void Init(const parser::Name &name,
      const std::optional<parser::Initialization> &init) {
    if (init) {
      if (const auto *target{
              std::get_if<parser::InitialDataTarget>(&init->u)}) {
        resolver_.PointerInitialization(name, *target);
      } else if (const auto *expr{
                     std::get_if<parser::ConstantExpr>(&init->u)}) {
        if (name.symbol) {
          if (const auto *object{name.symbol->detailsIf<ObjectEntityDetails>()};
              !object || !object->init()) {
            resolver_.NonPointerInitialization(name, *expr);
          }
        }
      }
    }
  }

  ResolveNamesVisitor &resolver_;
  Scope *outerScope_{nullptr};
  int dataStmtObjectNesting_{0};
};

// Perform checks and completions that need to happen after all of
// the specification parts but before any of the execution parts.
void ResolveNamesVisitor::FinishSpecificationParts(const ProgramTree &node) {
  if (!node.scope()) {
    return; // error occurred creating scope
  }
  auto flagRestorer{common::ScopedSet(inSpecificationPart_, true)};
  SetScope(*node.scope());
  // The initializers of pointers and non-PARAMETER objects, the default
  // initializers of components, and non-deferred type-bound procedure
  // bindings have not yet been traversed.
  // We do that now, when any forward references that appeared
  // in those initializers will resolve to the right symbols without
  // incurring spurious errors with IMPLICIT NONE or forward references
  // to nested subprograms.
  DeferredCheckVisitor{*this}.Walk(node.spec());
  for (Scope &childScope : currScope().children()) {
    if (childScope.IsParameterizedDerivedTypeInstantiation()) {
      FinishDerivedTypeInstantiation(childScope);
    }
  }
  for (const auto &child : node.children()) {
    FinishSpecificationParts(child);
  }
}

void ResolveNamesVisitor::FinishExecutionParts(const ProgramTree &node) {
  if (node.scope()) {
    SetScope(*node.scope());
    if (node.exec()) {
      DeferredCheckVisitor{*this}.Walk(*node.exec());
    }
    for (const auto &child : node.children()) {
      FinishExecutionParts(child);
    }
  }
}

// Duplicate and fold component object pointer default initializer designators
// using the actual type parameter values of each particular instantiation.
// Validation is done later in declaration checking.
void ResolveNamesVisitor::FinishDerivedTypeInstantiation(Scope &scope) {
  CHECK(scope.IsDerivedType() && !scope.symbol());
  if (DerivedTypeSpec * spec{scope.derivedTypeSpec()}) {
    spec->Instantiate(currScope());
    const Symbol &origTypeSymbol{spec->typeSymbol()};
    if (const Scope * origTypeScope{origTypeSymbol.scope()}) {
      CHECK(origTypeScope->IsDerivedType() &&
          origTypeScope->symbol() == &origTypeSymbol);
      auto &foldingContext{GetFoldingContext()};
      auto restorer{foldingContext.WithPDTInstance(*spec)};
      for (auto &pair : scope) {
        Symbol &comp{*pair.second};
        const Symbol &origComp{DEREF(FindInScope(*origTypeScope, comp.name()))};
        if (IsPointer(comp)) {
          if (auto *details{comp.detailsIf<ObjectEntityDetails>()}) {
            auto origDetails{origComp.get<ObjectEntityDetails>()};
            if (const MaybeExpr & init{origDetails.init()}) {
              SomeExpr newInit{*init};
              MaybeExpr folded{FoldExpr(std::move(newInit))};
              details->set_init(std::move(folded));
            }
          }
        }
      }
    }
  }
}

// Resolve names in the execution part of this node and its children
void ResolveNamesVisitor::ResolveExecutionParts(const ProgramTree &node) {
  if (!node.scope()) {
    return; // error occurred creating scope
  }
  SetScope(*node.scope());
  if (const auto *exec{node.exec()}) {
    Walk(*exec);
  }
  FinishNamelists();
  if (node.IsModule()) {
    // A second final pass to catch new symbols added from implicitly
    // typed names in NAMELIST groups or the specification parts of
    // module subprograms.
    ApplyDefaultAccess();
  }
  PopScope(); // converts unclassified entities into objects
  for (const auto &child : node.children()) {
    ResolveExecutionParts(child);
  }
}

void ResolveNamesVisitor::Post(const parser::Program &x) {
  // ensure that all temps were deallocated
  CHECK(!attrs_);
  CHECK(!cudaDataAttr_);
  CHECK(!GetDeclTypeSpec());
  // Top-level resolution to propagate information across program units after
  // each of them has been resolved separately.
  ResolveOmpTopLevelParts(context(), x);
}

// A singleton instance of the scope -> IMPLICIT rules mapping is
// shared by all instances of ResolveNamesVisitor and accessed by this
// pointer when the visitors (other than the top-level original) are
// constructed.
static ImplicitRulesMap *sharedImplicitRulesMap{nullptr};

bool ResolveNames(
    SemanticsContext &context, const parser::Program &program, Scope &top) {
  ImplicitRulesMap implicitRulesMap;
  auto restorer{common::ScopedSet(sharedImplicitRulesMap, &implicitRulesMap)};
  ResolveNamesVisitor{context, implicitRulesMap, top}.Walk(program);
  return !context.AnyFatalError();
}

// Processes a module (but not internal) function when it is referenced
// in a specification expression in a sibling procedure.
void ResolveSpecificationParts(
    SemanticsContext &context, const Symbol &subprogram) {
  auto originalLocation{context.location()};
  ImplicitRulesMap implicitRulesMap;
  bool localImplicitRulesMap{false};
  if (!sharedImplicitRulesMap) {
    sharedImplicitRulesMap = &implicitRulesMap;
    localImplicitRulesMap = true;
  }
  ResolveNamesVisitor visitor{
      context, *sharedImplicitRulesMap, context.globalScope()};
  const auto &details{subprogram.get<SubprogramNameDetails>()};
  ProgramTree &node{details.node()};
  const Scope &moduleScope{subprogram.owner()};
  if (localImplicitRulesMap) {
    visitor.BeginScope(const_cast<Scope &>(moduleScope));
  } else {
    visitor.SetScope(const_cast<Scope &>(moduleScope));
  }
  visitor.ResolveSpecificationParts(node);
  context.set_location(std::move(originalLocation));
  if (localImplicitRulesMap) {
    sharedImplicitRulesMap = nullptr;
  }
}

} // namespace Fortran::semantics
