//===-- lib/Semantics/expression.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 "flang/Semantics/expression.h"
#include "check-call.h"
#include "pointer-assignment.h"
#include "resolve-names-utils.h"
#include "resolve-names.h"
#include "flang/Common/Fortran.h"
#include "flang/Common/idioms.h"
#include "flang/Evaluate/common.h"
#include "flang/Evaluate/fold.h"
#include "flang/Evaluate/tools.h"
#include "flang/Parser/characters.h"
#include "flang/Parser/dump-parse-tree.h"
#include "flang/Parser/parse-tree-visitor.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/scope.h"
#include "flang/Semantics/semantics.h"
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <functional>
#include <optional>
#include <set>
#include <vector>

// Typedef for optional generic expressions (ubiquitous in this file)
using MaybeExpr =
    std::optional<Fortran::evaluate::Expr<Fortran::evaluate::SomeType>>;

// Much of the code that implements semantic analysis of expressions is
// tightly coupled with their typed representations in lib/Evaluate,
// and appears here in namespace Fortran::evaluate for convenience.
namespace Fortran::evaluate {

using common::LanguageFeature;
using common::NumericOperator;
using common::TypeCategory;

static inline std::string ToUpperCase(std::string_view str) {
  return parser::ToUpperCaseLetters(str);
}

struct DynamicTypeWithLength : public DynamicType {
  explicit DynamicTypeWithLength(const DynamicType &t) : DynamicType{t} {}
  std::optional<Expr<SubscriptInteger>> LEN() const;
  std::optional<Expr<SubscriptInteger>> length;
};

std::optional<Expr<SubscriptInteger>> DynamicTypeWithLength::LEN() const {
  if (length) {
    return length;
  } else {
    return GetCharLength();
  }
}

static std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
    const std::optional<parser::TypeSpec> &spec, FoldingContext &context) {
  if (spec) {
    if (const semantics::DeclTypeSpec *typeSpec{spec->declTypeSpec}) {
      // Name resolution sets TypeSpec::declTypeSpec only when it's valid
      // (viz., an intrinsic type with valid known kind or a non-polymorphic
      // & non-ABSTRACT derived type).
      if (const semantics::IntrinsicTypeSpec *intrinsic{
              typeSpec->AsIntrinsic()}) {
        TypeCategory category{intrinsic->category()};
        if (auto optKind{ToInt64(intrinsic->kind())}) {
          int kind{static_cast<int>(*optKind)};
          if (category == TypeCategory::Character) {
            const semantics::CharacterTypeSpec &cts{
                typeSpec->characterTypeSpec()};
            const semantics::ParamValue &len{cts.length()};
            // N.B. CHARACTER(LEN=*) is allowed in type-specs in ALLOCATE() &
            // type guards, but not in array constructors.
            DynamicTypeWithLength type{DynamicType{kind, len}};
            if (auto lenExpr{type.LEN()}) {
              type.length = Fold(context,
                  AsExpr(Extremum<SubscriptInteger>{Ordering::Greater,
                      Expr<SubscriptInteger>{0}, std::move(*lenExpr)}));
            }
            return type;
          } else {
            return DynamicTypeWithLength{DynamicType{category, kind}};
          }
        }
      } else if (const semantics::DerivedTypeSpec *derived{
                     typeSpec->AsDerived()}) {
        return DynamicTypeWithLength{DynamicType{*derived}};
      }
    }
  }
  return std::nullopt;
}

// Utilities to set a source location, if we have one, on an actual argument,
// when it is statically present.
static void SetArgSourceLocation(ActualArgument &x, parser::CharBlock at) {
  x.set_sourceLocation(at);
}
static void SetArgSourceLocation(
    std::optional<ActualArgument> &x, parser::CharBlock at) {
  if (x) {
    x->set_sourceLocation(at);
  }
}
static void SetArgSourceLocation(
    std::optional<ActualArgument> &x, std::optional<parser::CharBlock> at) {
  if (x && at) {
    x->set_sourceLocation(*at);
  }
}

class ArgumentAnalyzer {
public:
  explicit ArgumentAnalyzer(ExpressionAnalyzer &context)
      : context_{context}, source_{context.GetContextualMessages().at()},
        isProcedureCall_{false} {}
  ArgumentAnalyzer(ExpressionAnalyzer &context, parser::CharBlock source,
      bool isProcedureCall = false)
      : context_{context}, source_{source}, isProcedureCall_{isProcedureCall} {}
  bool fatalErrors() const { return fatalErrors_; }
  ActualArguments &&GetActuals() {
    CHECK(!fatalErrors_);
    return std::move(actuals_);
  }
  const Expr<SomeType> &GetExpr(std::size_t i) const {
    return DEREF(actuals_.at(i).value().UnwrapExpr());
  }
  Expr<SomeType> &&MoveExpr(std::size_t i) {
    return std::move(DEREF(actuals_.at(i).value().UnwrapExpr()));
  }
  void Analyze(const common::Indirection<parser::Expr> &x) {
    Analyze(x.value());
  }
  void Analyze(const parser::Expr &x) {
    actuals_.emplace_back(AnalyzeExpr(x));
    SetArgSourceLocation(actuals_.back(), x.source);
    fatalErrors_ |= !actuals_.back();
  }
  void Analyze(const parser::Variable &);
  void Analyze(const parser::ActualArgSpec &, bool isSubroutine);
  void ConvertBOZ(std::optional<DynamicType> *thisType, std::size_t,
      std::optional<DynamicType> otherType);

  bool IsIntrinsicRelational(
      RelationalOperator, const DynamicType &, const DynamicType &) const;
  bool IsIntrinsicLogical() const;
  bool IsIntrinsicNumeric(NumericOperator) const;
  bool IsIntrinsicConcat() const;

  bool CheckConformance();
  bool CheckAssignmentConformance();
  bool CheckForNullPointer(const char *where = "as an operand here");
  bool CheckForAssumedRank(const char *where = "as an operand here");

  // Find and return a user-defined operator or report an error.
  // The provided message is used if there is no such operator.
  // If a definedOpSymbolPtr is provided, the caller must check
  // for its accessibility.
  MaybeExpr TryDefinedOp(
      const char *, parser::MessageFixedText, bool isUserOp = false);
  template <typename E>
  MaybeExpr TryDefinedOp(E opr, parser::MessageFixedText msg) {
    return TryDefinedOp(
        context_.context().languageFeatures().GetNames(opr), msg);
  }
  // Find and return a user-defined assignment
  std::optional<ProcedureRef> TryDefinedAssignment();
  std::optional<ProcedureRef> GetDefinedAssignmentProc();
  std::optional<DynamicType> GetType(std::size_t) const;
  void Dump(llvm::raw_ostream &);

private:
  MaybeExpr TryDefinedOp(
      const std::vector<const char *> &, parser::MessageFixedText);
  MaybeExpr TryBoundOp(const Symbol &, int passIndex);
  std::optional<ActualArgument> AnalyzeExpr(const parser::Expr &);
  std::optional<ActualArgument> AnalyzeVariable(const parser::Variable &);
  MaybeExpr AnalyzeExprOrWholeAssumedSizeArray(const parser::Expr &);
  bool AreConformable() const;
  const Symbol *FindBoundOp(parser::CharBlock, int passIndex,
      const Symbol *&generic, bool isSubroutine);
  void AddAssignmentConversion(
      const DynamicType &lhsType, const DynamicType &rhsType);
  bool OkLogicalIntegerAssignment(TypeCategory lhs, TypeCategory rhs);
  int GetRank(std::size_t) const;
  bool IsBOZLiteral(std::size_t i) const {
    return evaluate::IsBOZLiteral(GetExpr(i));
  }
  void SayNoMatch(const std::string &, bool isAssignment = false);
  std::string TypeAsFortran(std::size_t);
  bool AnyUntypedOrMissingOperand();

  ExpressionAnalyzer &context_;
  ActualArguments actuals_;
  parser::CharBlock source_;
  bool fatalErrors_{false};
  const bool isProcedureCall_; // false for user-defined op or assignment
};

// Wraps a data reference in a typed Designator<>, and a procedure
// or procedure pointer reference in a ProcedureDesignator.
MaybeExpr ExpressionAnalyzer::Designate(DataRef &&ref) {
  const Symbol &last{ref.GetLastSymbol()};
  const Symbol &specific{BypassGeneric(last)};
  const Symbol &symbol{specific.GetUltimate()};
  if (semantics::IsProcedure(symbol)) {
    if (symbol.attrs().test(semantics::Attr::ABSTRACT)) {
      Say("Abstract procedure interface '%s' may not be used as a designator"_err_en_US,
          last.name());
    }
    if (auto *component{std::get_if<Component>(&ref.u)}) {
      if (!CheckDataRef(ref)) {
        return std::nullopt;
      }
      return Expr<SomeType>{ProcedureDesignator{std::move(*component)}};
    } else if (!std::holds_alternative<SymbolRef>(ref.u)) {
      DIE("unexpected alternative in DataRef");
    } else if (!symbol.attrs().test(semantics::Attr::INTRINSIC)) {
      if (symbol.has<semantics::GenericDetails>()) {
        Say("'%s' is not a specific procedure"_err_en_US, last.name());
      } else if (IsProcedurePointer(specific)) {
        // For procedure pointers, retain associations so that data accesses
        // from client modules will work.
        return Expr<SomeType>{ProcedureDesignator{specific}};
      } else {
        return Expr<SomeType>{ProcedureDesignator{symbol}};
      }
    } else if (auto interface{context_.intrinsics().IsSpecificIntrinsicFunction(
                   symbol.name().ToString())};
               interface && !interface->isRestrictedSpecific) {
      SpecificIntrinsic intrinsic{
          symbol.name().ToString(), std::move(*interface)};
      intrinsic.isRestrictedSpecific = interface->isRestrictedSpecific;
      return Expr<SomeType>{ProcedureDesignator{std::move(intrinsic)}};
    } else {
      Say("'%s' is not an unrestricted specific intrinsic procedure"_err_en_US,
          last.name());
    }
    return std::nullopt;
  } else if (MaybeExpr result{AsGenericExpr(std::move(ref))}) {
    return result;
  } else if (semantics::HadUseError(
                 context_, GetContextualMessages().at(), &symbol)) {
    return std::nullopt;
  } else {
    if (!context_.HasError(last) && !context_.HasError(symbol)) {
      AttachDeclaration(
          Say("'%s' is not an object that can appear in an expression"_err_en_US,
              last.name()),
          symbol);
      context_.SetError(last);
    }
    return std::nullopt;
  }
}

// Some subscript semantic checks must be deferred until all of the
// subscripts are in hand.
MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
  const Symbol &symbol{ref.GetLastSymbol().GetUltimate()};
  int symbolRank{symbol.Rank()};
  int subscripts{static_cast<int>(ref.size())};
  if (subscripts == 0) {
    return std::nullopt; // error recovery
  } else if (subscripts != symbolRank) {
    if (symbolRank != 0) {
      Say("Reference to rank-%d object '%s' has %d subscripts"_err_en_US,
          symbolRank, symbol.name(), subscripts);
    }
    return std::nullopt;
  } else if (symbol.has<semantics::ObjectEntityDetails>() ||
      symbol.has<semantics::AssocEntityDetails>()) {
    // C928 & C1002
    if (Triplet *last{std::get_if<Triplet>(&ref.subscript().back().u)}) {
      if (!last->upper() && IsAssumedSizeArray(symbol)) {
        Say("Assumed-size array '%s' must have explicit final "
            "subscript upper bound value"_err_en_US,
            symbol.name());
        return std::nullopt;
      }
    }
  } else {
    // Shouldn't get here from Analyze(ArrayElement) without a valid base,
    // which, if not an object, must be a construct entity from
    // SELECT TYPE/RANK or ASSOCIATE.
    CHECK(symbol.has<semantics::AssocEntityDetails>());
  }
  if (!semantics::IsNamedConstant(symbol) && !inDataStmtObject_) {
    // Subscripts of named constants are checked in folding.
    // Subscripts of DATA statement objects are checked in data statement
    // conversion to initializers.
    CheckSubscripts(ref);
  }
  return Designate(DataRef{std::move(ref)});
}

// Applies subscripts to a data reference.
MaybeExpr ExpressionAnalyzer::ApplySubscripts(
    DataRef &&dataRef, std::vector<Subscript> &&subscripts) {
  if (subscripts.empty()) {
    return std::nullopt; // error recovery
  }
  return common::visit(
      common::visitors{
          [&](SymbolRef &&symbol) {
            return CompleteSubscripts(ArrayRef{symbol, std::move(subscripts)});
          },
          [&](Component &&c) {
            return CompleteSubscripts(
                ArrayRef{std::move(c), std::move(subscripts)});
          },
          [&](auto &&) -> MaybeExpr {
            DIE("bad base for ArrayRef");
            return std::nullopt;
          },
      },
      std::move(dataRef.u));
}

void ExpressionAnalyzer::CheckSubscripts(ArrayRef &ref) {
  // Fold subscript expressions and check for an empty triplet.
  const Symbol &arraySymbol{ref.base().GetLastSymbol()};
  Shape lb{GetLBOUNDs(foldingContext_, NamedEntity{arraySymbol})};
  CHECK(lb.size() >= ref.subscript().size());
  Shape ub{GetUBOUNDs(foldingContext_, NamedEntity{arraySymbol})};
  CHECK(ub.size() >= ref.subscript().size());
  bool anyPossiblyEmptyDim{false};
  int dim{0};
  for (Subscript &ss : ref.subscript()) {
    if (Triplet * triplet{std::get_if<Triplet>(&ss.u)}) {
      auto expr{Fold(triplet->stride())};
      auto stride{ToInt64(expr)};
      triplet->set_stride(std::move(expr));
      std::optional<ConstantSubscript> lower, upper;
      if (auto expr{triplet->lower()}) {
        *expr = Fold(std::move(*expr));
        lower = ToInt64(*expr);
        triplet->set_lower(std::move(*expr));
      } else {
        lower = ToInt64(lb[dim]);
      }
      if (auto expr{triplet->upper()}) {
        *expr = Fold(std::move(*expr));
        upper = ToInt64(*expr);
        triplet->set_upper(std::move(*expr));
      } else {
        upper = ToInt64(ub[dim]);
      }
      if (stride) {
        if (*stride == 0) {
          Say("Stride of triplet must not be zero"_err_en_US);
          return;
        }
        if (lower && upper) {
          if (*stride > 0) {
            anyPossiblyEmptyDim |= *lower > *upper;
          } else {
            anyPossiblyEmptyDim |= *lower < *upper;
          }
        } else {
          anyPossiblyEmptyDim = true;
        }
      } else { // non-constant stride
        if (lower && upper && *lower == *upper) {
          // stride is not relevant
        } else {
          anyPossiblyEmptyDim = true;
        }
      }
    } else { // not triplet
      auto &expr{std::get<IndirectSubscriptIntegerExpr>(ss.u).value()};
      expr = Fold(std::move(expr));
      anyPossiblyEmptyDim |= expr.Rank() > 0; // vector subscript
    }
    ++dim;
  }
  if (anyPossiblyEmptyDim) {
    return;
  }
  dim = 0;
  for (Subscript &ss : ref.subscript()) {
    auto dimLB{ToInt64(lb[dim])};
    auto dimUB{ToInt64(ub[dim])};
    if (dimUB && dimLB && *dimUB < *dimLB) {
      AttachDeclaration(
          Warn(common::UsageWarning::SubscriptedEmptyArray,
              "Empty array dimension %d should not be subscripted as an element or non-empty array section"_err_en_US,
              dim + 1),
          arraySymbol);
      break;
    }
    std::optional<ConstantSubscript> val[2];
    int vals{0};
    if (auto *triplet{std::get_if<Triplet>(&ss.u)}) {
      auto stride{ToInt64(triplet->stride())};
      std::optional<ConstantSubscript> lower, upper;
      if (const auto *lowerExpr{triplet->GetLower()}) {
        lower = ToInt64(*lowerExpr);
      } else if (lb[dim]) {
        lower = ToInt64(*lb[dim]);
      }
      if (const auto *upperExpr{triplet->GetUpper()}) {
        upper = ToInt64(*upperExpr);
      } else if (ub[dim]) {
        upper = ToInt64(*ub[dim]);
      }
      if (lower) {
        val[vals++] = *lower;
        if (upper && *upper != lower && (stride && *stride != 0)) {
          // Normalize upper bound for non-unit stride
          // 1:10:2 -> 1:9:2, 10:1:-2 -> 10:2:-2
          val[vals++] = *lower + *stride * ((*upper - *lower) / *stride);
        }
      }
    } else {
      val[vals++] =
          ToInt64(std::get<IndirectSubscriptIntegerExpr>(ss.u).value());
    }
    for (int j{0}; j < vals; ++j) {
      if (val[j]) {
        std::optional<parser::MessageFixedText> msg;
        std::optional<ConstantSubscript> bound;
        if (dimLB && *val[j] < *dimLB) {
          msg =
              "Subscript %jd is less than lower bound %jd for dimension %d of array"_err_en_US;
          bound = *dimLB;
        } else if (dimUB && *val[j] > *dimUB) {
          msg =
              "Subscript %jd is greater than upper bound %jd for dimension %d of array"_err_en_US;
          bound = *dimUB;
          if (dim + 1 == arraySymbol.Rank() && IsDummy(arraySymbol) &&
              *bound == 1) {
            // Old-school overindexing of a dummy array isn't fatal when
            // it's on the last dimension and the extent is 1.
            msg->set_severity(parser::Severity::Warning);
          }
        }
        if (msg) {
          AttachDeclaration(
              Say(std::move(*msg), static_cast<std::intmax_t>(*val[j]),
                  static_cast<std::intmax_t>(bound.value()), dim + 1),
              arraySymbol);
        }
      }
    }
    ++dim;
  }
}

// C919a - only one part-ref of a data-ref may have rank > 0
bool ExpressionAnalyzer::CheckRanks(const DataRef &dataRef) {
  return common::visit(
      common::visitors{
          [this](const Component &component) {
            const Symbol &symbol{component.GetLastSymbol()};
            if (int componentRank{symbol.Rank()}; componentRank > 0) {
              if (int baseRank{component.base().Rank()}; baseRank > 0) {
                Say("Reference to whole rank-%d component '%s' of rank-%d array of derived type is not allowed"_err_en_US,
                    componentRank, symbol.name(), baseRank);
                return false;
              }
            } else {
              return CheckRanks(component.base());
            }
            return true;
          },
          [this](const ArrayRef &arrayRef) {
            if (const auto *component{arrayRef.base().UnwrapComponent()}) {
              int subscriptRank{0};
              for (const Subscript &subscript : arrayRef.subscript()) {
                subscriptRank += subscript.Rank();
              }
              if (subscriptRank > 0) {
                if (int componentBaseRank{component->base().Rank()};
                    componentBaseRank > 0) {
                  Say("Subscripts of component '%s' of rank-%d derived type array have rank %d but must all be scalar"_err_en_US,
                      component->GetLastSymbol().name(), componentBaseRank,
                      subscriptRank);
                  return false;
                }
              } else {
                return CheckRanks(component->base());
              }
            }
            return true;
          },
          [](const SymbolRef &) { return true; },
          [](const CoarrayRef &) { return true; },
      },
      dataRef.u);
}

// C911 - if the last name in a data-ref has an abstract derived type,
// it must also be polymorphic.
bool ExpressionAnalyzer::CheckPolymorphic(const DataRef &dataRef) {
  if (auto type{DynamicType::From(dataRef.GetLastSymbol())}) {
    if (type->category() == TypeCategory::Derived && !type->IsPolymorphic()) {
      const Symbol &typeSymbol{
          type->GetDerivedTypeSpec().typeSymbol().GetUltimate()};
      if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) {
        AttachDeclaration(
            Say("Reference to object with abstract derived type '%s' must be polymorphic"_err_en_US,
                typeSymbol.name()),
            typeSymbol);
        return false;
      }
    }
  }
  return true;
}

bool ExpressionAnalyzer::CheckDataRef(const DataRef &dataRef) {
  // Always check both, don't short-circuit
  bool ranksOk{CheckRanks(dataRef)};
  bool polyOk{CheckPolymorphic(dataRef)};
  return ranksOk && polyOk;
}

// Parse tree correction after a substring S(j:k) was misparsed as an
// array section.  Fortran substrings must have a range, not a
// single index.
static std::optional<parser::Substring> FixMisparsedSubstringDataRef(
    parser::DataRef &dataRef) {
  if (auto *ae{
          std::get_if<common::Indirection<parser::ArrayElement>>(&dataRef.u)}) {
    // ...%a(j:k) and "a" is a character scalar
    parser::ArrayElement &arrElement{ae->value()};
    if (arrElement.subscripts.size() == 1) {
      if (auto *triplet{std::get_if<parser::SubscriptTriplet>(
              &arrElement.subscripts.front().u)}) {
        if (!std::get<2 /*stride*/>(triplet->t).has_value()) {
          if (const Symbol *symbol{
                  parser::GetLastName(arrElement.base).symbol}) {
            const Symbol &ultimate{symbol->GetUltimate()};
            if (const semantics::DeclTypeSpec *type{ultimate.GetType()}) {
              if (ultimate.Rank() == 0 &&
                  type->category() == semantics::DeclTypeSpec::Character) {
                // The ambiguous S(j:k) was parsed as an array section
                // reference, but it's now clear that it's a substring.
                // Fix the parse tree in situ.
                return arrElement.ConvertToSubstring();
              }
            }
          }
        }
      }
    }
  }
  return std::nullopt;
}

// When a designator is a misparsed type-param-inquiry of a misparsed
// substring -- it looks like a structure component reference of an array
// slice -- fix the substring and then convert to an intrinsic function
// call to KIND() or LEN().  And when the designator is a misparsed
// substring, convert it into a substring reference in place.
MaybeExpr ExpressionAnalyzer::FixMisparsedSubstring(
    const parser::Designator &d) {
  auto &mutate{const_cast<parser::Designator &>(d)};
  if (auto *dataRef{std::get_if<parser::DataRef>(&mutate.u)}) {
    if (auto *sc{std::get_if<common::Indirection<parser::StructureComponent>>(
            &dataRef->u)}) {
      parser::StructureComponent &structComponent{sc->value()};
      parser::CharBlock which{structComponent.component.source};
      if (which == "kind" || which == "len") {
        if (auto substring{
                FixMisparsedSubstringDataRef(structComponent.base)}) {
          // ...%a(j:k)%kind or %len and "a" is a character scalar
          mutate.u = std::move(*substring);
          if (MaybeExpr substringExpr{Analyze(d)}) {
            return MakeFunctionRef(which,
                ActualArguments{ActualArgument{std::move(*substringExpr)}});
          }
        }
      }
    } else if (auto substring{FixMisparsedSubstringDataRef(*dataRef)}) {
      mutate.u = std::move(*substring);
    }
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) {
  auto restorer{GetContextualMessages().SetLocation(d.source)};
  if (auto substringInquiry{FixMisparsedSubstring(d)}) {
    return substringInquiry;
  }
  // These checks have to be deferred to these "top level" data-refs where
  // we can be sure that there are no following subscripts (yet).
  MaybeExpr result{Analyze(d.u)};
  if (result) {
    std::optional<DataRef> dataRef{ExtractDataRef(std::move(result))};
    if (!dataRef) {
      dataRef = ExtractDataRef(std::move(result), /*intoSubstring=*/true);
    }
    if (!dataRef) {
      dataRef = ExtractDataRef(std::move(result),
          /*intoSubstring=*/false, /*intoComplexPart=*/true);
    }
    if (dataRef && !CheckDataRef(*dataRef)) {
      result.reset();
    }
  }
  return result;
}

// A utility subroutine to repackage optional expressions of various levels
// of type specificity as fully general MaybeExpr values.
template <typename A> common::IfNoLvalue<MaybeExpr, A> AsMaybeExpr(A &&x) {
  return AsGenericExpr(std::move(x));
}
template <typename A> MaybeExpr AsMaybeExpr(std::optional<A> &&x) {
  if (x) {
    return AsMaybeExpr(std::move(*x));
  }
  return std::nullopt;
}

// Type kind parameter values for literal constants.
int ExpressionAnalyzer::AnalyzeKindParam(
    const std::optional<parser::KindParam> &kindParam, int defaultKind) {
  if (!kindParam) {
    return defaultKind;
  }
  std::int64_t kind{common::visit(
      common::visitors{
          [](std::uint64_t k) { return static_cast<std::int64_t>(k); },
          [&](const parser::Scalar<
              parser::Integer<parser::Constant<parser::Name>>> &n) {
            if (MaybeExpr ie{Analyze(n)}) {
              return ToInt64(*ie).value_or(defaultKind);
            }
            return static_cast<std::int64_t>(defaultKind);
          },
      },
      kindParam->u)};
  if (kind != static_cast<int>(kind)) {
    Say("Unsupported type kind value (%jd)"_err_en_US,
        static_cast<std::intmax_t>(kind));
    kind = defaultKind;
  }
  return static_cast<int>(kind);
}

// Common handling of parser::IntLiteralConstant, SignedIntLiteralConstant,
// and UnsignedLiteralConstant
template <typename TYPES, TypeCategory CAT> struct IntTypeVisitor {
  using Result = MaybeExpr;
  using Types = TYPES;
  template <typename T> Result Test() {
    if (T::kind >= kind) {
      const char *p{digits.begin()};
      using Int = typename T::Scalar;
      typename Int::ValueWithOverflow num{0, false};
      const char *typeName{
          CAT == TypeCategory::Integer ? "INTEGER" : "UNSIGNED"};
      if (isNegated) {
        auto unsignedNum{Int::Read(p, 10, false /*unsigned*/)};
        num.value = unsignedNum.value.Negate().value;
        num.overflow = unsignedNum.overflow ||
            (CAT == TypeCategory::Integer && num.value > Int{0});
        if (!num.overflow && num.value.Negate().overflow) {
          analyzer.Warn(LanguageFeature::BigIntLiterals, digits,
              "negated maximum INTEGER(KIND=%d) literal"_port_en_US, T::kind);
        }
      } else {
        num = Int::Read(p, 10, /*isSigned=*/CAT == TypeCategory::Integer);
      }
      if (num.overflow) {
        if constexpr (CAT == TypeCategory::Unsigned) {
          analyzer.Warn(common::UsageWarning::UnsignedLiteralTruncation,
              "Unsigned literal too large for UNSIGNED(KIND=%d); truncated"_warn_en_US,
              kind);
          return Expr<SomeType>{
              Expr<SomeKind<CAT>>{Expr<T>{Constant<T>{std::move(num.value)}}}};
        }
      } else {
        if (T::kind > kind) {
          if (!isDefaultKind ||
              !analyzer.context().IsEnabled(LanguageFeature::BigIntLiterals)) {
            return std::nullopt;
          } else {
            analyzer.Warn(LanguageFeature::BigIntLiterals, digits,
                "Integer literal is too large for default %s(KIND=%d); "
                "assuming %s(KIND=%d)"_port_en_US,
                typeName, kind, typeName, T::kind);
          }
        }
        return Expr<SomeType>{
            Expr<SomeKind<CAT>>{Expr<T>{Constant<T>{std::move(num.value)}}}};
      }
    }
    return std::nullopt;
  }
  ExpressionAnalyzer &analyzer;
  parser::CharBlock digits;
  std::int64_t kind;
  bool isDefaultKind;
  bool isNegated;
};

template <typename TYPES, TypeCategory CAT, typename PARSED>
MaybeExpr ExpressionAnalyzer::IntLiteralConstant(
    const PARSED &x, bool isNegated) {
  const auto &kindParam{std::get<std::optional<parser::KindParam>>(x.t)};
  bool isDefaultKind{!kindParam};
  int kind{AnalyzeKindParam(kindParam, GetDefaultKind(CAT))};
  const char *typeName{CAT == TypeCategory::Integer ? "INTEGER" : "UNSIGNED"};
  if (CheckIntrinsicKind(CAT, kind)) {
    auto digits{std::get<parser::CharBlock>(x.t)};
    if (MaybeExpr result{common::SearchTypes(IntTypeVisitor<TYPES, CAT>{
            *this, digits, kind, isDefaultKind, isNegated})}) {
      return result;
    } else if (isDefaultKind) {
      Say(digits,
          "Integer literal is too large for any allowable kind of %s"_err_en_US,
          typeName);
    } else {
      Say(digits, "Integer literal is too large for %s(KIND=%d)"_err_en_US,
          typeName, kind);
    }
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::IntLiteralConstant &x, bool isNegated) {
  auto restorer{
      GetContextualMessages().SetLocation(std::get<parser::CharBlock>(x.t))};
  return IntLiteralConstant<IntegerTypes, TypeCategory::Integer>(x, isNegated);
}

MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::SignedIntLiteralConstant &x) {
  auto restorer{GetContextualMessages().SetLocation(x.source)};
  return IntLiteralConstant<IntegerTypes, TypeCategory::Integer>(x);
}

MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::UnsignedLiteralConstant &x) {
  parser::CharBlock at{std::get<parser::CharBlock>(x.t)};
  auto restorer{GetContextualMessages().SetLocation(at)};
  if (!context().IsEnabled(common::LanguageFeature::Unsigned) &&
      !context().AnyFatalError()) {
    context().Say(
        at, "-funsigned is required to enable UNSIGNED constants"_err_en_US);
  }
  return IntLiteralConstant<UnsignedTypes, TypeCategory::Unsigned>(x);
}

template <typename TYPE>
Constant<TYPE> ReadRealLiteral(
    parser::CharBlock source, FoldingContext &context) {
  const char *p{source.begin()};
  auto valWithFlags{
      Scalar<TYPE>::Read(p, context.targetCharacteristics().roundingMode())};
  CHECK(p == source.end());
  RealFlagWarnings(context, valWithFlags.flags, "conversion of REAL literal");
  auto value{valWithFlags.value};
  if (context.targetCharacteristics().areSubnormalsFlushedToZero()) {
    value = value.FlushSubnormalToZero();
  }
  return {value};
}

struct RealTypeVisitor {
  using Result = std::optional<Expr<SomeReal>>;
  using Types = RealTypes;

  RealTypeVisitor(int k, parser::CharBlock lit, FoldingContext &ctx)
      : kind{k}, literal{lit}, context{ctx} {}

  template <typename T> Result Test() {
    if (kind == T::kind) {
      return {AsCategoryExpr(ReadRealLiteral<T>(literal, context))};
    }
    return std::nullopt;
  }

  int kind;
  parser::CharBlock literal;
  FoldingContext &context;
};

// Reads a real literal constant and encodes it with the right kind.
MaybeExpr ExpressionAnalyzer::Analyze(const parser::RealLiteralConstant &x) {
  // Use a local message context around the real literal for better
  // provenance on any messages.
  auto restorer{GetContextualMessages().SetLocation(x.real.source)};
  // If a kind parameter appears, it defines the kind of the literal and the
  // letter used in an exponent part must be 'E' (e.g., the 'E' in
  // "6.02214E+23").  In the absence of an explicit kind parameter, any
  // exponent letter determines the kind.  Otherwise, defaults apply.
  auto &defaults{context_.defaultKinds()};
  int defaultKind{defaults.GetDefaultKind(TypeCategory::Real)};
  const char *end{x.real.source.end()};
  char expoLetter{' '};
  std::optional<int> letterKind;
  for (const char *p{x.real.source.begin()}; p < end; ++p) {
    if (parser::IsLetter(*p)) {
      expoLetter = *p;
      switch (expoLetter) {
      case 'e':
        letterKind = defaults.GetDefaultKind(TypeCategory::Real);
        break;
      case 'd':
        letterKind = defaults.doublePrecisionKind();
        break;
      case 'q':
        letterKind = defaults.quadPrecisionKind();
        break;
      default:
        Say("Unknown exponent letter '%c'"_err_en_US, expoLetter);
      }
      break;
    }
  }
  if (letterKind) {
    defaultKind = *letterKind;
  }
  // C716 requires 'E' as an exponent.
  // Extension: allow exponent-letter matching the kind-param.
  auto kind{AnalyzeKindParam(x.kind, defaultKind)};
  if (letterKind && expoLetter != 'e') {
    if (kind != *letterKind) {
      Warn(common::LanguageFeature::ExponentMatchingKindParam,
          "Explicit kind parameter on real constant disagrees with exponent letter '%c'"_warn_en_US,
          expoLetter);
    } else if (x.kind) {
      Warn(common::LanguageFeature::ExponentMatchingKindParam,
          "Explicit kind parameter together with non-'E' exponent letter is not standard"_port_en_US);
    }
  }
  auto result{common::SearchTypes(
      RealTypeVisitor{kind, x.real.source, GetFoldingContext()})};
  if (!result) { // C717
    Say("Unsupported REAL(KIND=%d)"_err_en_US, kind);
  }
  return AsMaybeExpr(std::move(result));
}

MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::SignedRealLiteralConstant &x) {
  if (auto result{Analyze(std::get<parser::RealLiteralConstant>(x.t))}) {
    auto &realExpr{std::get<Expr<SomeReal>>(result->u)};
    if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) {
      if (sign == parser::Sign::Negative) {
        return AsGenericExpr(-std::move(realExpr));
      }
    }
    return result;
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::SignedComplexLiteralConstant &x) {
  auto result{Analyze(std::get<parser::ComplexLiteralConstant>(x.t))};
  if (!result) {
    return std::nullopt;
  } else if (std::get<parser::Sign>(x.t) == parser::Sign::Negative) {
    return AsGenericExpr(-std::move(std::get<Expr<SomeComplex>>(result->u)));
  } else {
    return result;
  }
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexPart &x) {
  return Analyze(x.u);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexLiteralConstant &z) {
  return AnalyzeComplex(Analyze(std::get<0>(z.t)), Analyze(std::get<1>(z.t)),
      "complex literal constant");
}

// CHARACTER literal processing.
MaybeExpr ExpressionAnalyzer::AnalyzeString(std::string &&string, int kind) {
  if (!CheckIntrinsicKind(TypeCategory::Character, kind)) {
    return std::nullopt;
  }
  switch (kind) {
  case 1:
    return AsGenericExpr(Constant<Type<TypeCategory::Character, 1>>{
        parser::DecodeString<std::string, parser::Encoding::LATIN_1>(
            string, true)});
  case 2:
    return AsGenericExpr(Constant<Type<TypeCategory::Character, 2>>{
        parser::DecodeString<std::u16string, parser::Encoding::UTF_8>(
            string, true)});
  case 4:
    return AsGenericExpr(Constant<Type<TypeCategory::Character, 4>>{
        parser::DecodeString<std::u32string, parser::Encoding::UTF_8>(
            string, true)});
  default:
    CRASH_NO_CASE;
  }
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::CharLiteralConstant &x) {
  int kind{
      AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t), 1)};
  auto value{std::get<std::string>(x.t)};
  return AnalyzeString(std::move(value), kind);
}

MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::HollerithLiteralConstant &x) {
  int kind{GetDefaultKind(TypeCategory::Character)};
  auto result{AnalyzeString(std::string{x.v}, kind)};
  if (auto *constant{UnwrapConstantValue<Ascii>(result)}) {
    constant->set_wasHollerith(true);
  }
  return result;
}

// .TRUE. and .FALSE. of various kinds
MaybeExpr ExpressionAnalyzer::Analyze(const parser::LogicalLiteralConstant &x) {
  auto kind{AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t),
      GetDefaultKind(TypeCategory::Logical))};
  bool value{std::get<bool>(x.t)};
  auto result{common::SearchTypes(
      TypeKindVisitor<TypeCategory::Logical, Constant, bool>{
          kind, std::move(value)})};
  if (!result) {
    Say("unsupported LOGICAL(KIND=%d)"_err_en_US, kind); // C728
  }
  return result;
}

// BOZ typeless literals
MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
  const char *p{x.v.c_str()};
  std::uint64_t base{16};
  switch (*p++) {
  case 'b':
    base = 2;
    break;
  case 'o':
    base = 8;
    break;
  case 'z':
    break;
  case 'x':
    break;
  default:
    CRASH_NO_CASE;
  }
  CHECK(*p == '"');
  ++p;
  auto value{BOZLiteralConstant::Read(p, base, false /*unsigned*/)};
  if (*p != '"') {
    Say("Invalid digit ('%c') in BOZ literal '%s'"_err_en_US, *p,
        x.v); // C7107, C7108
    return std::nullopt;
  }
  if (value.overflow) {
    Say("BOZ literal '%s' too large"_err_en_US, x.v);
    return std::nullopt;
  }
  return AsGenericExpr(std::move(value.value));
}

// Names and named constants
MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
  auto restorer{GetContextualMessages().SetLocation(n.source)};
  if (std::optional<int> kind{IsImpliedDo(n.source)}) {
    return AsMaybeExpr(ConvertToKind<TypeCategory::Integer>(
        *kind, AsExpr(ImpliedDoIndex{n.source})));
  }
  if (context_.HasError(n.symbol)) { // includes case of no symbol
    return std::nullopt;
  } else {
    const Symbol &ultimate{n.symbol->GetUltimate()};
    if (ultimate.has<semantics::TypeParamDetails>()) {
      // A bare reference to a derived type parameter within a parameterized
      // derived type definition.
      auto dyType{DynamicType::From(ultimate)};
      if (!dyType) {
        // When the integer kind of this type parameter is not known now,
        // it's either an error or because it depends on earlier-declared kind
        // type parameters.  So assume that it's a subscript integer for now
        // while processing other specification expressions in the PDT
        // definition; the right kind value will be used later in each of its
        // instantiations.
        int kind{SubscriptInteger::kind};
        if (const auto *typeSpec{ultimate.GetType()}) {
          if (const semantics::IntrinsicTypeSpec *
              intrinType{typeSpec->AsIntrinsic()}) {
            if (auto k{ToInt64(Fold(semantics::KindExpr{intrinType->kind()}))};
                k && IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) {
              kind = *k;
            }
          }
        }
        dyType = DynamicType{TypeCategory::Integer, kind};
      }
      return Fold(ConvertToType(
          *dyType, AsGenericExpr(TypeParamInquiry{std::nullopt, ultimate})));
    } else {
      if (n.symbol->attrs().test(semantics::Attr::VOLATILE)) {
        if (const semantics::Scope *pure{semantics::FindPureProcedureContaining(
                context_.FindScope(n.source))}) {
          SayAt(n,
              "VOLATILE variable '%s' may not be referenced in pure subprogram '%s'"_err_en_US,
              n.source, DEREF(pure->symbol()).name());
          n.symbol->attrs().reset(semantics::Attr::VOLATILE);
        }
      }
      if (!isWholeAssumedSizeArrayOk_ &&
          semantics::IsAssumedSizeArray(
              ResolveAssociations(*n.symbol))) { // C1002, C1014, C1231
        AttachDeclaration(
            SayAt(n,
                "Whole assumed-size array '%s' may not appear here without subscripts"_err_en_US,
                n.source),
            *n.symbol);
      }
      return Designate(DataRef{*n.symbol});
    }
  }
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::NamedConstant &n) {
  auto restorer{GetContextualMessages().SetLocation(n.v.source)};
  if (MaybeExpr value{Analyze(n.v)}) {
    Expr<SomeType> folded{Fold(std::move(*value))};
    if (IsConstantExpr(folded)) {
      return folded;
    }
    Say(n.v.source, "must be a constant"_err_en_US); // C718
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::NullInit &n) {
  auto restorer{AllowNullPointer()};
  if (MaybeExpr value{Analyze(n.v.value())}) {
    // Subtle: when the NullInit is a DataStmtConstant, it might
    // be a misparse of a structure constructor without parameters
    // or components (e.g., T()).  Checking the result to ensure
    // that a "=>" data entity initializer actually resolved to
    // a null pointer has to be done by the caller.
    return Fold(std::move(*value));
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::StmtFunctionStmt &stmtFunc) {
  inStmtFunctionDefinition_ = true;
  return Analyze(std::get<parser::Scalar<parser::Expr>>(stmtFunc.t));
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::InitialDataTarget &x) {
  return Analyze(x.value());
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtValue &x) {
  if (const auto &repeat{
          std::get<std::optional<parser::DataStmtRepeat>>(x.t)}) {
    x.repetitions = -1;
    if (MaybeExpr expr{Analyze(repeat->u)}) {
      Expr<SomeType> folded{Fold(std::move(*expr))};
      if (auto value{ToInt64(folded)}) {
        if (*value >= 0) { // C882
          x.repetitions = *value;
        } else {
          Say(FindSourceLocation(repeat),
              "Repeat count (%jd) for data value must not be negative"_err_en_US,
              *value);
        }
      }
    }
  }
  return Analyze(std::get<parser::DataStmtConstant>(x.t));
}

// Substring references
std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::GetSubstringBound(
    const std::optional<parser::ScalarIntExpr> &bound) {
  if (bound) {
    if (MaybeExpr expr{Analyze(*bound)}) {
      if (expr->Rank() > 1) {
        Say("substring bound expression has rank %d"_err_en_US, expr->Rank());
      }
      if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
        if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
          return {std::move(*ssIntExpr)};
        }
        return {Expr<SubscriptInteger>{
            Convert<SubscriptInteger, TypeCategory::Integer>{
                std::move(*intExpr)}}};
      } else {
        Say("substring bound expression is not INTEGER"_err_en_US);
      }
    }
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) {
  if (MaybeExpr baseExpr{Analyze(std::get<parser::DataRef>(ss.t))}) {
    if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*baseExpr))}) {
      if (MaybeExpr newBaseExpr{Designate(std::move(*dataRef))}) {
        if (std::optional<DataRef> checked{
                ExtractDataRef(std::move(*newBaseExpr))}) {
          const parser::SubstringRange &range{
              std::get<parser::SubstringRange>(ss.t)};
          std::optional<Expr<SubscriptInteger>> first{
              Fold(GetSubstringBound(std::get<0>(range.t)))};
          std::optional<Expr<SubscriptInteger>> last{
              Fold(GetSubstringBound(std::get<1>(range.t)))};
          const Symbol &symbol{checked->GetLastSymbol()};
          if (std::optional<DynamicType> dynamicType{
                  DynamicType::From(symbol)}) {
            if (dynamicType->category() == TypeCategory::Character) {
              auto lbValue{ToInt64(first)};
              if (!lbValue) {
                lbValue = 1;
              }
              auto ubValue{ToInt64(last)};
              auto len{dynamicType->knownLength()};
              if (!ubValue) {
                ubValue = len;
              }
              if (lbValue && ubValue && *lbValue > *ubValue) {
                // valid, substring is empty
              } else if (lbValue && *lbValue < 1 && (ubValue || !last)) {
                Say("Substring must begin at 1 or later, not %jd"_err_en_US,
                    static_cast<std::intmax_t>(*lbValue));
                return std::nullopt;
              } else if (ubValue && len && *ubValue > *len &&
                  (lbValue || !first)) {
                Say("Substring must end at %zd or earlier, not %jd"_err_en_US,
                    static_cast<std::intmax_t>(*len),
                    static_cast<std::intmax_t>(*ubValue));
                return std::nullopt;
              }
              return WrapperHelper<TypeCategory::Character, Designator,
                  Substring>(dynamicType->kind(),
                  Substring{std::move(checked.value()), std::move(first),
                      std::move(last)});
            }
          }
          Say("substring may apply only to CHARACTER"_err_en_US);
        }
      }
    }
  }
  return std::nullopt;
}

// CHARACTER literal substrings
MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::CharLiteralConstantSubstring &x) {
  const parser::SubstringRange &range{std::get<parser::SubstringRange>(x.t)};
  std::optional<Expr<SubscriptInteger>> lower{
      GetSubstringBound(std::get<0>(range.t))};
  std::optional<Expr<SubscriptInteger>> upper{
      GetSubstringBound(std::get<1>(range.t))};
  if (MaybeExpr string{Analyze(std::get<parser::CharLiteralConstant>(x.t))}) {
    if (auto *charExpr{std::get_if<Expr<SomeCharacter>>(&string->u)}) {
      Expr<SubscriptInteger> length{
          common::visit([](const auto &ckExpr) { return ckExpr.LEN().value(); },
              charExpr->u)};
      if (!lower) {
        lower = Expr<SubscriptInteger>{1};
      }
      if (!upper) {
        upper = Expr<SubscriptInteger>{
            static_cast<std::int64_t>(ToInt64(length).value())};
      }
      return common::visit(
          [&](auto &&ckExpr) -> MaybeExpr {
            using Result = ResultType<decltype(ckExpr)>;
            auto *cp{std::get_if<Constant<Result>>(&ckExpr.u)};
            CHECK(DEREF(cp).size() == 1);
            StaticDataObject::Pointer staticData{StaticDataObject::Create()};
            staticData->set_alignment(Result::kind)
                .set_itemBytes(Result::kind)
                .Push(cp->GetScalarValue().value(),
                    foldingContext_.targetCharacteristics().isBigEndian());
            Substring substring{std::move(staticData), std::move(lower.value()),
                std::move(upper.value())};
            return AsGenericExpr(
                Expr<Result>{Designator<Result>{std::move(substring)}});
          },
          std::move(charExpr->u));
    }
  }
  return std::nullopt;
}

// substring%KIND/LEN
MaybeExpr ExpressionAnalyzer::Analyze(const parser::SubstringInquiry &x) {
  if (MaybeExpr substring{Analyze(x.v)}) {
    CHECK(x.source.size() >= 8);
    int nameLen{x.source.end()[-1] == 'n' ? 3 /*LEN*/ : 4 /*KIND*/};
    parser::CharBlock name{
        x.source.end() - nameLen, static_cast<std::size_t>(nameLen)};
    CHECK(name == "len" || name == "kind");
    return MakeFunctionRef(
        name, ActualArguments{ActualArgument{std::move(*substring)}});
  } else {
    return std::nullopt;
  }
}

// Subscripted array references
std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::AsSubscript(
    MaybeExpr &&expr) {
  if (expr) {
    if (expr->Rank() > 1) {
      Say("Subscript expression has rank %d greater than 1"_err_en_US,
          expr->Rank());
    }
    if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
      if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
        return std::move(*ssIntExpr);
      } else {
        return Expr<SubscriptInteger>{
            Convert<SubscriptInteger, TypeCategory::Integer>{
                std::move(*intExpr)}};
      }
    } else {
      Say("Subscript expression is not INTEGER"_err_en_US);
    }
  }
  return std::nullopt;
}

std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::TripletPart(
    const std::optional<parser::Subscript> &s) {
  if (s) {
    return AsSubscript(Analyze(*s));
  } else {
    return std::nullopt;
  }
}

std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
    const parser::SectionSubscript &ss) {
  return common::visit(
      common::visitors{
          [&](const parser::SubscriptTriplet &t) -> std::optional<Subscript> {
            const auto &lower{std::get<0>(t.t)};
            const auto &upper{std::get<1>(t.t)};
            const auto &stride{std::get<2>(t.t)};
            auto result{Triplet{
                TripletPart(lower), TripletPart(upper), TripletPart(stride)}};
            if ((lower && !result.lower()) || (upper && !result.upper())) {
              return std::nullopt;
            } else {
              return std::make_optional<Subscript>(result);
            }
          },
          [&](const auto &s) -> std::optional<Subscript> {
            if (auto subscriptExpr{AsSubscript(Analyze(s))}) {
              return Subscript{std::move(*subscriptExpr)};
            } else {
              return std::nullopt;
            }
          },
      },
      ss.u);
}

// Empty result means an error occurred
std::vector<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscripts(
    const std::list<parser::SectionSubscript> &sss) {
  bool error{false};
  std::vector<Subscript> subscripts;
  for (const auto &s : sss) {
    if (auto subscript{AnalyzeSectionSubscript(s)}) {
      subscripts.emplace_back(std::move(*subscript));
    } else {
      error = true;
    }
  }
  return !error ? subscripts : std::vector<Subscript>{};
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) {
  MaybeExpr baseExpr;
  {
    auto restorer{AllowWholeAssumedSizeArray()};
    baseExpr = Analyze(ae.base);
  }
  if (baseExpr) {
    if (ae.subscripts.empty()) {
      // will be converted to function call later or error reported
    } else if (baseExpr->Rank() == 0) {
      if (const Symbol *symbol{GetLastSymbol(*baseExpr)}) {
        if (!context_.HasError(symbol)) {
          if (inDataStmtConstant_) {
            // Better error for NULL(X) with a MOLD= argument
            Say("'%s' must be an array or structure constructor if used with non-empty parentheses as a DATA statement constant"_err_en_US,
                symbol->name());
          } else {
            Say("'%s' is not an array"_err_en_US, symbol->name());
          }
          context_.SetError(*symbol);
        }
      }
    } else if (std::optional<DataRef> dataRef{
                   ExtractDataRef(std::move(*baseExpr))}) {
      return ApplySubscripts(
          std::move(*dataRef), AnalyzeSectionSubscripts(ae.subscripts));
    } else {
      Say("Subscripts may be applied only to an object, component, or array constant"_err_en_US);
    }
  }
  // error was reported: analyze subscripts without reporting more errors
  auto restorer{GetContextualMessages().DiscardMessages()};
  AnalyzeSectionSubscripts(ae.subscripts);
  return std::nullopt;
}

// Type parameter inquiries apply to data references, but don't depend
// on any trailing (co)subscripts.
static NamedEntity IgnoreAnySubscripts(Designator<SomeDerived> &&designator) {
  return common::visit(
      common::visitors{
          [](SymbolRef &&symbol) { return NamedEntity{symbol}; },
          [](Component &&component) {
            return NamedEntity{std::move(component)};
          },
          [](ArrayRef &&arrayRef) { return std::move(arrayRef.base()); },
          [](CoarrayRef &&coarrayRef) {
            return NamedEntity{coarrayRef.GetLastSymbol()};
          },
      },
      std::move(designator.u));
}

// Components, but not bindings, of parent derived types are explicitly
// represented as such.
std::optional<Component> ExpressionAnalyzer::CreateComponent(DataRef &&base,
    const Symbol &component, const semantics::Scope &scope,
    bool C919bAlreadyEnforced) {
  if (!C919bAlreadyEnforced && IsAllocatableOrPointer(component) &&
      base.Rank() > 0) { // C919b
    Say("An allocatable or pointer component reference must be applied to a scalar base"_err_en_US);
  }
  if (&component.owner() == &scope ||
      component.has<semantics::ProcBindingDetails>()) {
    return Component{std::move(base), component};
  }
  if (const Symbol *typeSymbol{scope.GetSymbol()}) {
    if (const Symbol *parentComponent{typeSymbol->GetParentComponent(&scope)}) {
      if (const auto *object{
              parentComponent->detailsIf<semantics::ObjectEntityDetails>()}) {
        if (const auto *parentType{object->type()}) {
          if (const semantics::Scope *parentScope{
                  parentType->derivedTypeSpec().scope()}) {
            return CreateComponent(
                DataRef{Component{std::move(base), *parentComponent}},
                component, *parentScope, C919bAlreadyEnforced);
          }
        }
      }
    }
  }
  return std::nullopt;
}

// Derived type component references and type parameter inquiries
MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
  Symbol *sym{sc.component.symbol};
  if (context_.HasError(sym)) {
    return std::nullopt;
  }
  const auto *misc{sym->detailsIf<semantics::MiscDetails>()};
  bool isTypeParamInquiry{sym->has<semantics::TypeParamDetails>() ||
      (misc &&
          (misc->kind() == semantics::MiscDetails::Kind::KindParamInquiry ||
              misc->kind() == semantics::MiscDetails::Kind::LenParamInquiry))};
  MaybeExpr base;
  if (isTypeParamInquiry) {
    auto restorer{AllowWholeAssumedSizeArray()};
    base = Analyze(sc.base);
  } else {
    base = Analyze(sc.base);
  }
  if (!base) {
    return std::nullopt;
  }
  const auto &name{sc.component.source};
  if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
    const auto *dtSpec{GetDerivedTypeSpec(dtExpr->GetType())};
    if (isTypeParamInquiry) {
      if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) {
        if (std::optional<DynamicType> dyType{DynamicType::From(*sym)}) {
          if (dyType->category() == TypeCategory::Integer) {
            auto restorer{GetContextualMessages().SetLocation(name)};
            return Fold(ConvertToType(*dyType,
                AsGenericExpr(TypeParamInquiry{
                    IgnoreAnySubscripts(std::move(*designator)), *sym})));
          }
        }
        Say(name, "Type parameter is not INTEGER"_err_en_US);
      } else {
        Say(name,
            "A type parameter inquiry must be applied to a designator"_err_en_US);
      }
    } else if (!dtSpec || !dtSpec->scope()) {
      CHECK(context_.AnyFatalError() || !foldingContext_.messages().empty());
      return std::nullopt;
    } else if (std::optional<DataRef> dataRef{
                   ExtractDataRef(std::move(*dtExpr))}) {
      auto restorer{GetContextualMessages().SetLocation(name)};
      if (auto component{
              CreateComponent(std::move(*dataRef), *sym, *dtSpec->scope())}) {
        return Designate(DataRef{std::move(*component)});
      } else {
        Say(name, "Component is not in scope of derived TYPE(%s)"_err_en_US,
            dtSpec->typeSymbol().name());
      }
    } else {
      Say(name,
          "Base of component reference must be a data reference"_err_en_US);
    }
  } else if (auto *details{sym->detailsIf<semantics::MiscDetails>()}) {
    // special part-ref: %re, %im, %kind, %len
    // Type errors on the base of %re/%im/%len are detected and
    // reported in name resolution.
    using MiscKind = semantics::MiscDetails::Kind;
    MiscKind kind{details->kind()};
    if (kind == MiscKind::ComplexPartRe || kind == MiscKind::ComplexPartIm) {
      if (auto *zExpr{std::get_if<Expr<SomeComplex>>(&base->u)}) {
        if (std::optional<DataRef> dataRef{ExtractDataRef(*zExpr)}) {
          // Represent %RE/%IM as a designator
          Expr<SomeReal> realExpr{common::visit(
              [&](const auto &z) {
                using PartType = typename ResultType<decltype(z)>::Part;
                auto part{kind == MiscKind::ComplexPartRe
                        ? ComplexPart::Part::RE
                        : ComplexPart::Part::IM};
                return AsCategoryExpr(Designator<PartType>{
                    ComplexPart{std::move(*dataRef), part}});
              },
              zExpr->u)};
          return AsGenericExpr(std::move(realExpr));
        }
      }
    } else if (isTypeParamInquiry) { // %kind or %len
      ActualArgument arg{std::move(*base)};
      SetArgSourceLocation(arg, name);
      return MakeFunctionRef(name, ActualArguments{std::move(arg)});
    } else {
      DIE("unexpected MiscDetails::Kind");
    }
  } else {
    Say(name, "derived type required before component reference"_err_en_US);
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) {
  if (auto maybeDataRef{ExtractDataRef(Analyze(x.base))}) {
    DataRef *dataRef{&*maybeDataRef};
    std::vector<Subscript> subscripts;
    SymbolVector reversed;
    if (auto *aRef{std::get_if<ArrayRef>(&dataRef->u)}) {
      subscripts = std::move(aRef->subscript());
      reversed.push_back(aRef->GetLastSymbol());
      if (Component *component{aRef->base().UnwrapComponent()}) {
        dataRef = &component->base();
      } else {
        dataRef = nullptr;
      }
    }
    if (dataRef) {
      while (auto *component{std::get_if<Component>(&dataRef->u)}) {
        reversed.push_back(component->GetLastSymbol());
        dataRef = &component->base();
      }
      if (auto *baseSym{std::get_if<SymbolRef>(&dataRef->u)}) {
        reversed.push_back(*baseSym);
      } else {
        Say("Base of coindexed named object has subscripts or cosubscripts"_err_en_US);
      }
    }
    std::vector<Expr<SubscriptInteger>> cosubscripts;
    bool cosubsOk{true};
    for (const auto &cosub :
        std::get<std::list<parser::Cosubscript>>(x.imageSelector.t)) {
      MaybeExpr coex{Analyze(cosub)};
      if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(coex)}) {
        cosubscripts.push_back(
            ConvertToType<SubscriptInteger>(std::move(*intExpr)));
      } else {
        cosubsOk = false;
      }
    }
    if (cosubsOk && !reversed.empty()) {
      int numCosubscripts{static_cast<int>(cosubscripts.size())};
      const Symbol &symbol{reversed.front()};
      if (numCosubscripts != GetCorank(symbol)) {
        Say("'%s' has corank %d, but coindexed reference has %d cosubscripts"_err_en_US,
            symbol.name(), GetCorank(symbol), numCosubscripts);
      }
    }
    for (const auto &imageSelSpec :
        std::get<std::list<parser::ImageSelectorSpec>>(x.imageSelector.t)) {
      common::visit(
          common::visitors{
              [&](const auto &x) { Analyze(x.v); },
          },
          imageSelSpec.u);
    }
    // Reverse the chain of symbols so that the base is first and coarray
    // ultimate component is last.
    if (cosubsOk) {
      return Designate(
          DataRef{CoarrayRef{SymbolVector{reversed.crbegin(), reversed.crend()},
              std::move(subscripts), std::move(cosubscripts)}});
    }
  }
  return std::nullopt;
}

int ExpressionAnalyzer::IntegerTypeSpecKind(
    const parser::IntegerTypeSpec &spec) {
  Expr<SubscriptInteger> value{
      AnalyzeKindSelector(TypeCategory::Integer, spec.v)};
  if (auto kind{ToInt64(value)}) {
    return static_cast<int>(*kind);
  }
  SayAt(spec, "Constant INTEGER kind value required here"_err_en_US);
  return GetDefaultKind(TypeCategory::Integer);
}

// Array constructors

// Inverts a collection of generic ArrayConstructorValues<SomeType> that
// all happen to have the same actual type T into one ArrayConstructor<T>.
template <typename T>
ArrayConstructorValues<T> MakeSpecific(
    ArrayConstructorValues<SomeType> &&from) {
  ArrayConstructorValues<T> to;
  for (ArrayConstructorValue<SomeType> &x : from) {
    common::visit(
        common::visitors{
            [&](common::CopyableIndirection<Expr<SomeType>> &&expr) {
              auto *typed{UnwrapExpr<Expr<T>>(expr.value())};
              to.Push(std::move(DEREF(typed)));
            },
            [&](ImpliedDo<SomeType> &&impliedDo) {
              to.Push(ImpliedDo<T>{impliedDo.name(),
                  std::move(impliedDo.lower()), std::move(impliedDo.upper()),
                  std::move(impliedDo.stride()),
                  MakeSpecific<T>(std::move(impliedDo.values()))});
            },
        },
        std::move(x.u));
  }
  return to;
}

class ArrayConstructorContext {
public:
  ArrayConstructorContext(
      ExpressionAnalyzer &c, std::optional<DynamicTypeWithLength> &&t)
      : exprAnalyzer_{c}, type_{std::move(t)} {}

  void Add(const parser::AcValue &);
  MaybeExpr ToExpr();

  // These interfaces allow *this to be used as a type visitor argument to
  // common::SearchTypes() to convert the array constructor to a typed
  // expression in ToExpr().
  using Result = MaybeExpr;
  using Types = AllTypes;
  template <typename T> Result Test() {
    if (type_ && type_->category() == T::category) {
      if constexpr (T::category == TypeCategory::Derived) {
        if (!type_->IsUnlimitedPolymorphic()) {
          return AsMaybeExpr(ArrayConstructor<T>{type_->GetDerivedTypeSpec(),
              MakeSpecific<T>(std::move(values_))});
        }
      } else if (type_->kind() == T::kind) {
        ArrayConstructor<T> result{MakeSpecific<T>(std::move(values_))};
        if constexpr (T::category == TypeCategory::Character) {
          if (auto len{LengthIfGood()}) {
            // The ac-do-variables may be treated as constant expressions,
            // if some conditions on ac-implied-do-control hold (10.1.12 (12)).
            // At the same time, they may be treated as constant expressions
            // only in the context of the ac-implied-do, but setting
            // the character length here may result in complete elimination
            // of the ac-implied-do. For example:
            //   character(10) :: c
            //   ... len([(c(i:i), integer(8)::i = 1,4)])
            // would be evaulated into:
            //   ... int(max(0_8,i-i+1_8),kind=4)
            // with a dangling reference to the ac-do-variable.
            // Prevent this by checking for the ac-do-variable references
            // in the 'len' expression.
            result.set_LEN(std::move(*len));
          }
        }
        return AsMaybeExpr(std::move(result));
      }
    }
    return std::nullopt;
  }

private:
  using ImpliedDoIntType = ResultType<ImpliedDoIndex>;

  std::optional<Expr<SubscriptInteger>> LengthIfGood() const {
    if (type_) {
      auto len{type_->LEN()};
      if (explicitType_ ||
          (len && IsConstantExpr(*len) && !ContainsAnyImpliedDoIndex(*len))) {
        return len;
      }
    }
    return std::nullopt;
  }
  bool NeedLength() const {
    return type_ && type_->category() == TypeCategory::Character &&
        !LengthIfGood();
  }
  void Push(MaybeExpr &&);
  void Add(const parser::AcValue::Triplet &);
  void Add(const parser::Expr &);
  void Add(const parser::AcImpliedDo &);
  void UnrollConstantImpliedDo(const parser::AcImpliedDo &,
      parser::CharBlock name, std::int64_t lower, std::int64_t upper,
      std::int64_t stride);

  template <int KIND>
  std::optional<Expr<Type<TypeCategory::Integer, KIND>>> ToSpecificInt(
      MaybeExpr &&y) {
    if (y) {
      Expr<SomeInteger> *intExpr{UnwrapExpr<Expr<SomeInteger>>(*y)};
      return Fold(exprAnalyzer_.GetFoldingContext(),
          ConvertToType<Type<TypeCategory::Integer, KIND>>(
              std::move(DEREF(intExpr))));
    } else {
      return std::nullopt;
    }
  }

  template <int KIND, typename A>
  std::optional<Expr<Type<TypeCategory::Integer, KIND>>> GetSpecificIntExpr(
      const A &x) {
    return ToSpecificInt<KIND>(exprAnalyzer_.Analyze(x));
  }

  // Nested array constructors all reference the same ExpressionAnalyzer,
  // which represents the nest of active implied DO loop indices.
  ExpressionAnalyzer &exprAnalyzer_;
  std::optional<DynamicTypeWithLength> type_;
  bool explicitType_{type_.has_value()};
  std::optional<std::int64_t> constantLength_;
  ArrayConstructorValues<SomeType> values_;
  std::uint64_t messageDisplayedSet_{0};
};

void ArrayConstructorContext::Push(MaybeExpr &&x) {
  if (!x) {
    return;
  }
  if (!type_) {
    if (auto *boz{std::get_if<BOZLiteralConstant>(&x->u)}) {
      // Treat an array constructor of BOZ as if default integer.
      exprAnalyzer_.Warn(common::LanguageFeature::BOZAsDefaultInteger,
          "BOZ literal in array constructor without explicit type is assumed to be default INTEGER"_port_en_US);
      x = AsGenericExpr(ConvertToKind<TypeCategory::Integer>(
          exprAnalyzer_.GetDefaultKind(TypeCategory::Integer),
          std::move(*boz)));
    }
  }
  std::optional<DynamicType> dyType{x->GetType()};
  if (!dyType) {
    if (auto *boz{std::get_if<BOZLiteralConstant>(&x->u)}) {
      if (!type_) {
        // Treat an array constructor of BOZ as if default integer.
        exprAnalyzer_.Warn(common::LanguageFeature::BOZAsDefaultInteger,
            "BOZ literal in array constructor without explicit type is assumed to be default INTEGER"_port_en_US);
        x = AsGenericExpr(ConvertToKind<TypeCategory::Integer>(
            exprAnalyzer_.GetDefaultKind(TypeCategory::Integer),
            std::move(*boz)));
        dyType = x.value().GetType();
      } else if (auto cast{ConvertToType(*type_, std::move(*x))}) {
        x = std::move(cast);
        dyType = *type_;
      } else {
        if (!(messageDisplayedSet_ & 0x80)) {
          exprAnalyzer_.Say(
              "BOZ literal is not suitable for use in this array constructor"_err_en_US);
          messageDisplayedSet_ |= 0x80;
        }
        return;
      }
    } else { // procedure name, &c.
      if (!(messageDisplayedSet_ & 0x40)) {
        exprAnalyzer_.Say(
            "Item is not suitable for use in an array constructor"_err_en_US);
        messageDisplayedSet_ |= 0x40;
      }
      return;
    }
  } else if (dyType->IsUnlimitedPolymorphic()) {
    if (!(messageDisplayedSet_ & 8)) {
      exprAnalyzer_.Say("Cannot have an unlimited polymorphic value in an "
                        "array constructor"_err_en_US); // C7113
      messageDisplayedSet_ |= 8;
    }
    return;
  } else if (dyType->category() == TypeCategory::Derived &&
      dyType->GetDerivedTypeSpec().typeSymbol().attrs().test(
          semantics::Attr::ABSTRACT)) { // F'2023 C7125
    if (!(messageDisplayedSet_ & 0x200)) {
      exprAnalyzer_.Say(
          "An item whose declared type is ABSTRACT may not appear in an array constructor"_err_en_US);
      messageDisplayedSet_ |= 0x200;
    }
  }
  DynamicTypeWithLength xType{dyType.value()};
  if (Expr<SomeCharacter> * charExpr{UnwrapExpr<Expr<SomeCharacter>>(*x)}) {
    CHECK(xType.category() == TypeCategory::Character);
    xType.length =
        common::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u);
  }
  if (!type_) {
    // If there is no explicit type-spec in an array constructor, the type
    // of the array is the declared type of all of the elements, which must
    // be well-defined and all match.
    // TODO: Possible language extension: use the most general type of
    // the values as the type of a numeric constructed array, convert all
    // of the other values to that type.  Alternative: let the first value
    // determine the type, and convert the others to that type.
    CHECK(!explicitType_);
    type_ = std::move(xType);
    constantLength_ = ToInt64(type_->length);
    values_.Push(std::move(*x));
  } else if (!explicitType_) {
    if (type_->IsTkCompatibleWith(xType) && xType.IsTkCompatibleWith(*type_)) {
      values_.Push(std::move(*x));
      auto xLen{xType.LEN()};
      if (auto thisLen{ToInt64(xLen)}) {
        if (constantLength_) {
          if (*thisLen != *constantLength_ && !(messageDisplayedSet_ & 1)) {
            exprAnalyzer_.Warn(
                common::LanguageFeature::DistinctArrayConstructorLengths,
                "Character literal in array constructor without explicit "
                "type has different length than earlier elements"_port_en_US);
            messageDisplayedSet_ |= 1;
          }
          if (*thisLen > *constantLength_) {
            // Language extension: use the longest literal to determine the
            // length of the array constructor's character elements, not the
            // first, when there is no explicit type.
            *constantLength_ = *thisLen;
            type_->length = std::move(xLen);
          }
        } else {
          constantLength_ = *thisLen;
          type_->length = std::move(xLen);
        }
      } else if (xLen && NeedLength()) {
        type_->length = std::move(xLen);
      }
    } else {
      if (!(messageDisplayedSet_ & 2)) {
        exprAnalyzer_.Say(
            "Values in array constructor must have the same declared type "
            "when no explicit type appears"_err_en_US); // C7110
        messageDisplayedSet_ |= 2;
      }
    }
  } else {
    if (auto cast{ConvertToType(*type_, std::move(*x))}) {
      values_.Push(std::move(*cast));
    } else if (!(messageDisplayedSet_ & 4)) {
      exprAnalyzer_.Say("Value in array constructor of type '%s' could not "
                        "be converted to the type of the array '%s'"_err_en_US,
          x->GetType()->AsFortran(), type_->AsFortran()); // C7111, C7112
      messageDisplayedSet_ |= 4;
    }
  }
}

void ArrayConstructorContext::Add(const parser::AcValue &x) {
  common::visit(
      common::visitors{
          [&](const parser::AcValue::Triplet &triplet) { Add(triplet); },
          [&](const common::Indirection<parser::Expr> &expr) {
            Add(expr.value());
          },
          [&](const common::Indirection<parser::AcImpliedDo> &impliedDo) {
            Add(impliedDo.value());
          },
      },
      x.u);
}

// Transforms l:u(:s) into (_,_=l,u(,s)) with an anonymous index '_'
void ArrayConstructorContext::Add(const parser::AcValue::Triplet &triplet) {
  MaybeExpr lowerExpr{exprAnalyzer_.Analyze(std::get<0>(triplet.t))};
  MaybeExpr upperExpr{exprAnalyzer_.Analyze(std::get<1>(triplet.t))};
  MaybeExpr strideExpr{exprAnalyzer_.Analyze(std::get<2>(triplet.t))};
  if (lowerExpr && upperExpr) {
    auto lowerType{lowerExpr->GetType()};
    auto upperType{upperExpr->GetType()};
    auto strideType{strideExpr ? strideExpr->GetType() : lowerType};
    if (lowerType && upperType && strideType) {
      int kind{lowerType->kind()};
      if (upperType->kind() > kind) {
        kind = upperType->kind();
      }
      if (strideType->kind() > kind) {
        kind = strideType->kind();
      }
      auto lower{ToSpecificInt<ImpliedDoIntType::kind>(std::move(lowerExpr))};
      auto upper{ToSpecificInt<ImpliedDoIntType::kind>(std::move(upperExpr))};
      if (lower && upper) {
        auto stride{
            ToSpecificInt<ImpliedDoIntType::kind>(std::move(strideExpr))};
        if (!stride) {
          stride = Expr<ImpliedDoIntType>{1};
        }
        DynamicType type{TypeCategory::Integer, kind};
        if (!type_) {
          type_ = DynamicTypeWithLength{type};
        }
        parser::CharBlock anonymous;
        if (auto converted{ConvertToType(type,
                AsGenericExpr(
                    Expr<ImpliedDoIntType>{ImpliedDoIndex{anonymous}}))}) {
          auto v{std::move(values_)};
          Push(std::move(converted));
          std::swap(v, values_);
          values_.Push(ImpliedDo<SomeType>{anonymous, std::move(*lower),
              std::move(*upper), std::move(*stride), std::move(v)});
        }
      }
    }
  }
}

void ArrayConstructorContext::Add(const parser::Expr &expr) {
  auto restorer{exprAnalyzer_.GetContextualMessages().SetLocation(expr.source)};
  Push(exprAnalyzer_.Analyze(expr));
}

void ArrayConstructorContext::Add(const parser::AcImpliedDo &impliedDo) {
  const auto &control{std::get<parser::AcImpliedDoControl>(impliedDo.t)};
  const auto &bounds{std::get<parser::AcImpliedDoControl::Bounds>(control.t)};
  exprAnalyzer_.Analyze(bounds.name);
  parser::CharBlock name{bounds.name.thing.thing.source};
  int kind{ImpliedDoIntType::kind};
  if (const Symbol * symbol{bounds.name.thing.thing.symbol}) {
    if (auto dynamicType{DynamicType::From(symbol)}) {
      if (dynamicType->category() == TypeCategory::Integer) {
        kind = dynamicType->kind();
      }
    }
  }
  std::optional<Expr<ImpliedDoIntType>> lower{
      GetSpecificIntExpr<ImpliedDoIntType::kind>(bounds.lower)};
  std::optional<Expr<ImpliedDoIntType>> upper{
      GetSpecificIntExpr<ImpliedDoIntType::kind>(bounds.upper)};
  if (lower && upper) {
    std::optional<Expr<ImpliedDoIntType>> stride{
        GetSpecificIntExpr<ImpliedDoIntType::kind>(bounds.step)};
    if (!stride) {
      stride = Expr<ImpliedDoIntType>{1};
    }
    if (exprAnalyzer_.AddImpliedDo(name, kind)) {
      // Check for constant bounds; the loop may require complete unrolling
      // of the parse tree if all bounds are constant in order to allow the
      // implied DO loop index to qualify as a constant expression.
      auto cLower{ToInt64(lower)};
      auto cUpper{ToInt64(upper)};
      auto cStride{ToInt64(stride)};
      if (!(messageDisplayedSet_ & 0x10) && cStride && *cStride == 0) {
        exprAnalyzer_.SayAt(bounds.step.value().thing.thing.value().source,
            "The stride of an implied DO loop must not be zero"_err_en_US);
        messageDisplayedSet_ |= 0x10;
      }
      bool isConstant{cLower && cUpper && cStride && *cStride != 0};
      bool isNonemptyConstant{isConstant &&
          ((*cStride > 0 && *cLower <= *cUpper) ||
              (*cStride < 0 && *cLower >= *cUpper))};
      bool isEmpty{isConstant && !isNonemptyConstant};
      bool unrollConstantLoop{false};
      parser::Messages buffer;
      auto saveMessagesDisplayed{messageDisplayedSet_};
      {
        auto messageRestorer{
            exprAnalyzer_.GetContextualMessages().SetMessages(buffer)};
        auto v{std::move(values_)};
        for (const auto &value :
            std::get<std::list<parser::AcValue>>(impliedDo.t)) {
          Add(value);
        }
        std::swap(v, values_);
        if (isNonemptyConstant && buffer.AnyFatalError()) {
          unrollConstantLoop = true;
        } else {
          values_.Push(ImpliedDo<SomeType>{name, std::move(*lower),
              std::move(*upper), std::move(*stride), std::move(v)});
        }
      }
      // F'2023 7.8 p5
      if (!(messageDisplayedSet_ & 0x100) && isEmpty && NeedLength()) {
        exprAnalyzer_.SayAt(name,
            "Array constructor implied DO loop has no iterations and indeterminate character length"_err_en_US);
        messageDisplayedSet_ |= 0x100;
      }
      if (unrollConstantLoop) {
        messageDisplayedSet_ = saveMessagesDisplayed;
        UnrollConstantImpliedDo(impliedDo, name, *cLower, *cUpper, *cStride);
      } else if (auto *messages{
                     exprAnalyzer_.GetContextualMessages().messages()}) {
        messages->Annex(std::move(buffer));
      }
      exprAnalyzer_.RemoveImpliedDo(name);
    } else if (!(messageDisplayedSet_ & 0x20)) {
      exprAnalyzer_.SayAt(name,
          "Implied DO index '%s' is active in a surrounding implied DO loop "
          "and may not have the same name"_err_en_US,
          name); // C7115
      messageDisplayedSet_ |= 0x20;
    }
  }
}

// Fortran considers an implied DO index of an array constructor to be
// a constant expression if the bounds of the implied DO loop are constant.
// Usually this doesn't matter, but if we emitted spurious messages as a
// result of not using constant values for the index while analyzing the
// items, we need to do it again the "hard" way with multiple iterations over
// the parse tree.
void ArrayConstructorContext::UnrollConstantImpliedDo(
    const parser::AcImpliedDo &impliedDo, parser::CharBlock name,
    std::int64_t lower, std::int64_t upper, std::int64_t stride) {
  auto &foldingContext{exprAnalyzer_.GetFoldingContext()};
  auto restorer{exprAnalyzer_.DoNotUseSavedTypedExprs()};
  for (auto &at{foldingContext.StartImpliedDo(name, lower)};
       (stride > 0 && at <= upper) || (stride < 0 && at >= upper);
       at += stride) {
    for (const auto &value :
        std::get<std::list<parser::AcValue>>(impliedDo.t)) {
      Add(value);
    }
  }
  foldingContext.EndImpliedDo(name);
}

MaybeExpr ArrayConstructorContext::ToExpr() {
  return common::SearchTypes(std::move(*this));
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
  const parser::AcSpec &acSpec{array.v};
  ArrayConstructorContext acContext{
      *this, AnalyzeTypeSpec(acSpec.type, GetFoldingContext())};
  for (const parser::AcValue &value : acSpec.values) {
    acContext.Add(value);
  }
  return acContext.ToExpr();
}

// Check if implicit conversion of expr to the symbol type is legal (if needed),
// and make it explicit if requested.
static MaybeExpr ImplicitConvertTo(const semantics::Symbol &sym,
    Expr<SomeType> &&expr, bool keepConvertImplicit) {
  if (!keepConvertImplicit) {
    return ConvertToType(sym, std::move(expr));
  } else {
    // Test if a convert could be inserted, but do not make it explicit to
    // preserve the information that expr is a variable.
    if (ConvertToType(sym, common::Clone(expr))) {
      return MaybeExpr{std::move(expr)};
    }
  }
  // Illegal implicit convert.
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::StructureConstructor &structure) {
  auto &parsedType{std::get<parser::DerivedTypeSpec>(structure.t)};
  parser::Name structureType{std::get<parser::Name>(parsedType.t)};
  parser::CharBlock &typeName{structureType.source};
  if (semantics::Symbol *typeSymbol{structureType.symbol}) {
    if (typeSymbol->has<semantics::DerivedTypeDetails>()) {
      semantics::DerivedTypeSpec dtSpec{typeName, typeSymbol->GetUltimate()};
      if (!CheckIsValidForwardReference(dtSpec)) {
        return std::nullopt;
      }
    }
  }
  if (!parsedType.derivedTypeSpec) {
    return std::nullopt;
  }
  const auto &spec{*parsedType.derivedTypeSpec};
  const Symbol &typeSymbol{spec.typeSymbol()};
  if (!spec.scope() || !typeSymbol.has<semantics::DerivedTypeDetails>()) {
    return std::nullopt; // error recovery
  }
  const semantics::Scope &scope{context_.FindScope(typeName)};
  const semantics::Scope *pureContext{FindPureProcedureContaining(scope)};
  const auto &typeDetails{typeSymbol.get<semantics::DerivedTypeDetails>()};
  const Symbol *parentComponent{typeDetails.GetParentComponent(*spec.scope())};

  if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { // C796
    AttachDeclaration(Say(typeName,
                          "ABSTRACT derived type '%s' may not be used in a "
                          "structure constructor"_err_en_US,
                          typeName),
        typeSymbol); // C7114
  }

  // This iterator traverses all of the components in the derived type and its
  // parents.  The symbols for whole parent components appear after their
  // own components and before the components of the types that extend them.
  // E.g., TYPE :: A; REAL X; END TYPE
  //       TYPE, EXTENDS(A) :: B; REAL Y; END TYPE
  // produces the component list X, A, Y.
  // The order is important below because a structure constructor can
  // initialize X or A by name, but not both.
  auto components{semantics::OrderedComponentIterator{spec}};
  auto nextAnonymous{components.begin()};
  auto afterLastParentComponentIter{components.end()};
  if (parentComponent) {
    for (auto iter{components.begin()}; iter != components.end(); ++iter) {
      if (iter->test(Symbol::Flag::ParentComp)) {
        afterLastParentComponentIter = iter;
        ++afterLastParentComponentIter;
      }
    }
  }

  std::set<parser::CharBlock> unavailable;
  bool anyKeyword{false};
  StructureConstructor result{spec};
  bool checkConflicts{true}; // until we hit one
  auto &messages{GetContextualMessages()};

  // NULL() can be a valid component
  auto restorer{AllowNullPointer()};

  for (const auto &component :
      std::get<std::list<parser::ComponentSpec>>(structure.t)) {
    const parser::Expr &expr{
        std::get<parser::ComponentDataSource>(component.t).v.value()};
    parser::CharBlock source{expr.source};
    auto restorer{messages.SetLocation(source)};
    const Symbol *symbol{nullptr};
    MaybeExpr value{Analyze(expr)};
    std::optional<DynamicType> valueType{DynamicType::From(value)};
    if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) {
      anyKeyword = true;
      source = kw->v.source;
      symbol = kw->v.symbol;
      if (!symbol) {
        // Skip overridden inaccessible parent components in favor of
        // their later overrides.
        for (const Symbol &sym : components) {
          if (sym.name() == source) {
            symbol = &sym;
          }
        }
      }
      if (!symbol) { // C7101
        Say(source,
            "Keyword '%s=' does not name a component of derived type '%s'"_err_en_US,
            source, typeName);
      }
    } else {
      if (anyKeyword) { // C7100
        Say(source,
            "Value in structure constructor lacks a component name"_err_en_US);
        checkConflicts = false; // stem cascade
      }
      // Here's a regrettably common extension of the standard: anonymous
      // initialization of parent components, e.g., T(PT(1)) rather than
      // T(1) or T(PT=PT(1)).  There may be multiple parent components.
      if (nextAnonymous == components.begin() && parentComponent && valueType &&
          context().IsEnabled(LanguageFeature::AnonymousParents)) {
        for (auto parent{components.begin()};
             parent != afterLastParentComponentIter; ++parent) {
          if (auto parentType{DynamicType::From(*parent)}; parentType &&
              parent->test(Symbol::Flag::ParentComp) &&
              valueType->IsEquivalentTo(*parentType)) {
            symbol = &*parent;
            nextAnonymous = ++parent;
            Warn(LanguageFeature::AnonymousParents, source,
                "Whole parent component '%s' in structure constructor should not be anonymous"_port_en_US,
                symbol->name());
            break;
          }
        }
      }
      while (!symbol && nextAnonymous != components.end()) {
        const Symbol &next{*nextAnonymous};
        ++nextAnonymous;
        if (!next.test(Symbol::Flag::ParentComp)) {
          symbol = &next;
        }
      }
      if (!symbol) {
        Say(source, "Unexpected value in structure constructor"_err_en_US);
      }
    }
    if (symbol) {
      const semantics::Scope &innermost{context_.FindScope(expr.source)};
      if (auto msg{CheckAccessibleSymbol(innermost, *symbol)}) {
        Say(expr.source, std::move(*msg));
      }
      if (checkConflicts) {
        auto componentIter{
            std::find(components.begin(), components.end(), *symbol)};
        if (unavailable.find(symbol->name()) != unavailable.cend()) {
          // C797, C798
          Say(source,
              "Component '%s' conflicts with another component earlier in "
              "this structure constructor"_err_en_US,
              symbol->name());
        } else if (symbol->test(Symbol::Flag::ParentComp)) {
          // Make earlier components unavailable once a whole parent appears.
          for (auto it{components.begin()}; it != componentIter; ++it) {
            unavailable.insert(it->name());
          }
        } else {
          // Make whole parent components unavailable after any of their
          // constituents appear.
          for (auto it{componentIter}; it != components.end(); ++it) {
            if (it->test(Symbol::Flag::ParentComp)) {
              unavailable.insert(it->name());
            }
          }
        }
      }
      unavailable.insert(symbol->name());
      if (value) {
        if (symbol->has<semantics::TypeParamDetails>()) {
          Say(expr.source,
              "Type parameter '%s' may not appear as a component of a structure constructor"_err_en_US,
              symbol->name());
        }
        if (!(symbol->has<semantics::ProcEntityDetails>() ||
                symbol->has<semantics::ObjectEntityDetails>())) {
          continue; // recovery
        }
        if (IsPointer(*symbol)) { // C7104, C7105, C1594(4)
          semantics::CheckStructConstructorPointerComponent(
              context_, *symbol, *value, innermost);
          result.Add(*symbol, Fold(std::move(*value)));
          continue;
        }
        if (IsNullPointer(*value)) {
          if (IsAllocatable(*symbol)) {
            if (IsBareNullPointer(&*value)) {
              // NULL() with no arguments allowed by 7.5.10 para 6 for
              // ALLOCATABLE.
              result.Add(*symbol, Expr<SomeType>{NullPointer{}});
              continue;
            }
            if (IsNullObjectPointer(*value)) {
              AttachDeclaration(
                  Warn(common::LanguageFeature::
                           NullMoldAllocatableComponentValue,
                      expr.source,
                      "NULL() with arguments is not standard conforming as the value for allocatable component '%s'"_port_en_US,
                      symbol->name()),
                  *symbol);
              // proceed to check type & shape
            } else {
              AttachDeclaration(
                  Say(expr.source,
                      "A NULL procedure pointer may not be used as the value for component '%s'"_err_en_US,
                      symbol->name()),
                  *symbol);
              continue;
            }
          } else {
            AttachDeclaration(
                Say(expr.source,
                    "A NULL pointer may not be used as the value for component '%s'"_err_en_US,
                    symbol->name()),
                *symbol);
            continue;
          }
        } else if (const Symbol * pointer{FindPointerComponent(*symbol)};
                   pointer && pureContext) { // C1594(4)
          if (const Symbol *
              visible{semantics::FindExternallyVisibleObject(
                  *value, *pureContext)}) {
            Say(expr.source,
                "The externally visible object '%s' may not be used in a pure procedure as the value for component '%s' which has the pointer component '%s'"_err_en_US,
                visible->name(), symbol->name(), pointer->name());
          }
        }
        // Make implicit conversion explicit to allow folding of the structure
        // constructors and help semantic checking, unless the component is
        // allocatable, in which case the value could be an unallocated
        // allocatable (see Fortran 2018 7.5.10 point 7). The explicit
        // convert would cause a segfault. Lowering will deal with
        // conditionally converting and preserving the lower bounds in this
        // case.
        if (MaybeExpr converted{ImplicitConvertTo(
                *symbol, std::move(*value), IsAllocatable(*symbol))}) {
          if (auto componentShape{GetShape(GetFoldingContext(), *symbol)}) {
            if (auto valueShape{GetShape(GetFoldingContext(), *converted)}) {
              if (GetRank(*componentShape) == 0 && GetRank(*valueShape) > 0) {
                AttachDeclaration(
                    Say(expr.source,
                        "Rank-%d array value is not compatible with scalar component '%s'"_err_en_US,
                        GetRank(*valueShape), symbol->name()),
                    *symbol);
              } else {
                auto checked{
                    CheckConformance(messages, *componentShape, *valueShape,
                        CheckConformanceFlags::RightIsExpandableDeferred,
                        "component", "value")};
                if (checked && *checked && GetRank(*componentShape) > 0 &&
                    GetRank(*valueShape) == 0 &&
                    (IsDeferredShape(*symbol) ||
                        !IsExpandableScalar(*converted, GetFoldingContext(),
                            *componentShape, true /*admit PURE call*/))) {
                  AttachDeclaration(
                      Say(expr.source,
                          "Scalar value cannot be expanded to shape of array component '%s'"_err_en_US,
                          symbol->name()),
                      *symbol);
                }
                if (checked.value_or(true)) {
                  result.Add(*symbol, std::move(*converted));
                }
              }
            } else {
              Say(expr.source, "Shape of value cannot be determined"_err_en_US);
            }
          } else {
            AttachDeclaration(
                Say(expr.source,
                    "Shape of component '%s' cannot be determined"_err_en_US,
                    symbol->name()),
                *symbol);
          }
        } else if (auto symType{DynamicType::From(symbol)}) {
          if (IsAllocatable(*symbol) && symType->IsUnlimitedPolymorphic() &&
              valueType) {
            // ok
          } else if (valueType) {
            AttachDeclaration(
                Say(expr.source,
                    "Value in structure constructor of type '%s' is "
                    "incompatible with component '%s' of type '%s'"_err_en_US,
                    valueType->AsFortran(), symbol->name(),
                    symType->AsFortran()),
                *symbol);
          } else {
            AttachDeclaration(
                Say(expr.source,
                    "Value in structure constructor is incompatible with "
                    "component '%s' of type %s"_err_en_US,
                    symbol->name(), symType->AsFortran()),
                *symbol);
          }
        }
      }
    }
  }

  // Ensure that unmentioned component objects have default initializers.
  for (const Symbol &symbol : components) {
    if (!symbol.test(Symbol::Flag::ParentComp) &&
        unavailable.find(symbol.name()) == unavailable.cend()) {
      if (IsAllocatable(symbol)) {
        // Set all remaining allocatables to explicit NULL().
        result.Add(symbol, Expr<SomeType>{NullPointer{}});
      } else {
        const auto *object{symbol.detailsIf<semantics::ObjectEntityDetails>()};
        if (object && object->init()) {
          result.Add(symbol, common::Clone(*object->init()));
        } else if (IsPointer(symbol)) {
          result.Add(symbol, Expr<SomeType>{NullPointer{}});
        } else if (object) { // C799
          AttachDeclaration(Say(typeName,
                                "Structure constructor lacks a value for "
                                "component '%s'"_err_en_US,
                                symbol.name()),
              symbol);
        }
      }
    }
  }

  return AsMaybeExpr(Expr<SomeDerived>{std::move(result)});
}

static std::optional<parser::CharBlock> GetPassName(
    const semantics::Symbol &proc) {
  return common::visit(
      [](const auto &details) {
        if constexpr (std::is_base_of_v<semantics::WithPassArg,
                          std::decay_t<decltype(details)>>) {
          return details.passName();
        } else {
          return std::optional<parser::CharBlock>{};
        }
      },
      proc.details());
}

static std::optional<int> GetPassIndex(const Symbol &proc) {
  CHECK(!proc.attrs().test(semantics::Attr::NOPASS));
  std::optional<parser::CharBlock> passName{GetPassName(proc)};
  const auto *interface {
    semantics::FindInterface(proc)
  };
  if (!passName || !interface) {
    return 0; // first argument is passed-object
  }
  const auto &subp{interface->get<semantics::SubprogramDetails>()};
  int index{0};
  for (const auto *arg : subp.dummyArgs()) {
    if (arg && arg->name() == passName) {
      return index;
    }
    ++index;
  }
  return std::nullopt;
}

// Injects an expression into an actual argument list as the "passed object"
// for a type-bound procedure reference that is not NOPASS.  Adds an
// argument keyword if possible, but not when the passed object goes
// before a positional argument.
// e.g., obj%tbp(x) -> tbp(obj,x).
static void AddPassArg(ActualArguments &actuals, const Expr<SomeDerived> &expr,
    const Symbol &component, bool isPassedObject = true) {
  if (component.attrs().test(semantics::Attr::NOPASS)) {
    return;
  }
  std::optional<int> passIndex{GetPassIndex(component)};
  if (!passIndex) {
    return; // error recovery
  }
  auto iter{actuals.begin()};
  int at{0};
  while (iter < actuals.end() && at < *passIndex) {
    if (*iter && (*iter)->keyword()) {
      iter = actuals.end();
      break;
    }
    ++iter;
    ++at;
  }
  ActualArgument passed{AsGenericExpr(common::Clone(expr))};
  passed.set_isPassedObject(isPassedObject);
  if (iter == actuals.end()) {
    if (auto passName{GetPassName(component)}) {
      passed.set_keyword(*passName);
    }
  }
  actuals.emplace(iter, std::move(passed));
}

// Return the compile-time resolution of a procedure binding, if possible.
static const Symbol *GetBindingResolution(
    const std::optional<DynamicType> &baseType, const Symbol &component) {
  const auto *binding{component.detailsIf<semantics::ProcBindingDetails>()};
  if (!binding) {
    return nullptr;
  }
  if (!component.attrs().test(semantics::Attr::NON_OVERRIDABLE) &&
      (!baseType || baseType->IsPolymorphic())) {
    return nullptr;
  }
  return &binding->symbol();
}

auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
    const parser::ProcComponentRef &pcr, ActualArguments &&arguments,
    bool isSubroutine) -> std::optional<CalleeAndArguments> {
  const parser::StructureComponent &sc{pcr.v.thing};
  if (MaybeExpr base{Analyze(sc.base)}) {
    if (const Symbol *sym{sc.component.symbol}) {
      if (context_.HasError(sym)) {
        return std::nullopt;
      }
      if (!IsProcedure(*sym)) {
        AttachDeclaration(
            Say(sc.component.source, "'%s' is not a procedure"_err_en_US,
                sc.component.source),
            *sym);
        return std::nullopt;
      }
      if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
        if (sym->has<semantics::GenericDetails>()) {
          const Symbol &generic{*sym};
          auto dyType{dtExpr->GetType()};
          AdjustActuals adjustment{
              [&](const Symbol &proc, ActualArguments &actuals) {
                if (!proc.attrs().test(semantics::Attr::NOPASS)) {
                  AddPassArg(actuals, std::move(*dtExpr), proc);
                }
                return true;
              }};
          auto pair{
              ResolveGeneric(generic, arguments, adjustment, isSubroutine)};
          sym = pair.first;
          if (!sym) {
            EmitGenericResolutionError(generic, pair.second, isSubroutine);
            return std::nullopt;
          }
          // re-resolve the name to the specific binding
          CHECK(sym->has<semantics::ProcBindingDetails>());
          // Use the most recent override of a binding, respecting
          // the rule that inaccessible bindings may not be overridden
          // outside their module.  Fortran doesn't allow a PUBLIC
          // binding to be overridden by a PRIVATE one.
          CHECK(dyType && dyType->category() == TypeCategory::Derived &&
              !dyType->IsUnlimitedPolymorphic());
          if (const Symbol *
              latest{DEREF(dyType->GetDerivedTypeSpec().typeSymbol().scope())
                         .FindComponent(sym->name())}) {
            if (sym->attrs().test(semantics::Attr::PRIVATE)) {
              const auto *bindingModule{FindModuleContaining(generic.owner())};
              const Symbol *s{latest};
              while (s && FindModuleContaining(s->owner()) != bindingModule) {
                if (const auto *parent{s->owner().GetDerivedTypeParent()}) {
                  s = parent->FindComponent(sym->name());
                } else {
                  s = nullptr;
                }
              }
              if (s && !s->attrs().test(semantics::Attr::PRIVATE)) {
                // The latest override in the same module as the binding
                // is public, so it can be overridden.
              } else {
                latest = s;
              }
            }
            if (latest) {
              sym = latest;
            }
          }
          sc.component.symbol = const_cast<Symbol *>(sym);
        }
        std::optional<DataRef> dataRef{ExtractDataRef(std::move(*dtExpr))};
        if (dataRef && !CheckDataRef(*dataRef)) {
          return std::nullopt;
        }
        if (dataRef && dataRef->Rank() > 0) {
          if (sym->has<semantics::ProcBindingDetails>() &&
              sym->attrs().test(semantics::Attr::NOPASS)) {
            // F'2023 C1529 seems unnecessary and most compilers don't
            // enforce it.
            AttachDeclaration(
                Warn(common::LanguageFeature::NopassScalarBase,
                    sc.component.source,
                    "Base of NOPASS type-bound procedure reference should be scalar"_port_en_US),
                *sym);
          } else if (IsProcedurePointer(*sym)) { // C919
            Say(sc.component.source,
                "Base of procedure component reference must be scalar"_err_en_US);
          }
        }
        if (const Symbol *resolution{
                GetBindingResolution(dtExpr->GetType(), *sym)}) {
          AddPassArg(arguments, std::move(*dtExpr), *sym, false);
          return CalleeAndArguments{
              ProcedureDesignator{*resolution}, std::move(arguments)};
        } else if (dataRef.has_value()) {
          if (sym->attrs().test(semantics::Attr::NOPASS)) {
            const auto *dtSpec{GetDerivedTypeSpec(dtExpr->GetType())};
            if (dtSpec && dtSpec->scope()) {
              if (auto component{CreateComponent(std::move(*dataRef), *sym,
                      *dtSpec->scope(), /*C919bAlreadyEnforced=*/true)}) {
                return CalleeAndArguments{
                    ProcedureDesignator{std::move(*component)},
                    std::move(arguments)};
              }
            }
            Say(sc.component.source,
                "Component is not in scope of base derived type"_err_en_US);
            return std::nullopt;
          } else {
            AddPassArg(arguments,
                Expr<SomeDerived>{Designator<SomeDerived>{std::move(*dataRef)}},
                *sym);
            return CalleeAndArguments{
                ProcedureDesignator{*sym}, std::move(arguments)};
          }
        }
      }
      Say(sc.component.source,
          "Base of procedure component reference is not a derived-type object"_err_en_US);
    }
  }
  CHECK(context_.AnyFatalError());
  return std::nullopt;
}

// Can actual be argument associated with dummy?
static bool CheckCompatibleArgument(bool isElemental,
    const ActualArgument &actual, const characteristics::DummyArgument &dummy,
    FoldingContext &foldingContext) {
  const auto *expr{actual.UnwrapExpr()};
  return common::visit(
      common::visitors{
          [&](const characteristics::DummyDataObject &x) {
            if (x.attrs.test(characteristics::DummyDataObject::Attr::Pointer) &&
                IsBareNullPointer(expr)) {
              // NULL() without MOLD= is compatible with any dummy data pointer
              // but cannot be allowed to lead to ambiguity.
              return true;
            } else if (!isElemental && actual.Rank() != x.type.Rank() &&
                !x.type.attrs().test(
                    characteristics::TypeAndShape::Attr::AssumedRank) &&
                !x.ignoreTKR.test(common::IgnoreTKR::Rank)) {
              return false;
            } else if (auto actualType{actual.GetType()}) {
              return x.type.type().IsTkCompatibleWith(*actualType, x.ignoreTKR);
            }
            return false;
          },
          [&](const characteristics::DummyProcedure &dummy) {
            if ((dummy.attrs.test(
                     characteristics::DummyProcedure::Attr::Optional) ||
                    dummy.attrs.test(
                        characteristics::DummyProcedure::Attr::Pointer)) &&
                IsBareNullPointer(expr)) {
              // NULL() is compatible with any dummy pointer
              // or optional dummy procedure.
              return true;
            }
            if (!expr || !IsProcedurePointerTarget(*expr)) {
              return false;
            }
            if (auto actualProc{characteristics::Procedure::Characterize(
                    *expr, foldingContext)}) {
              const auto &dummyResult{dummy.procedure.value().functionResult};
              const auto *dummyTypeAndShape{
                  dummyResult ? dummyResult->GetTypeAndShape() : nullptr};
              const auto &actualResult{actualProc->functionResult};
              const auto *actualTypeAndShape{
                  actualResult ? actualResult->GetTypeAndShape() : nullptr};
              if (dummyTypeAndShape && actualTypeAndShape) {
                // Return false when the function results' types are both
                // known and not compatible.
                return actualTypeAndShape->type().IsTkCompatibleWith(
                    dummyTypeAndShape->type());
              }
            }
            return true;
          },
          [&](const characteristics::AlternateReturn &) {
            return actual.isAlternateReturn();
          },
      },
      dummy.u);
}

// Are the actual arguments compatible with the dummy arguments of procedure?
static bool CheckCompatibleArguments(
    const characteristics::Procedure &procedure, const ActualArguments &actuals,
    FoldingContext &foldingContext) {
  bool isElemental{procedure.IsElemental()};
  const auto &dummies{procedure.dummyArguments};
  CHECK(dummies.size() == actuals.size());
  for (std::size_t i{0}; i < dummies.size(); ++i) {
    const characteristics::DummyArgument &dummy{dummies[i]};
    const std::optional<ActualArgument> &actual{actuals[i]};
    if (actual &&
        !CheckCompatibleArgument(isElemental, *actual, dummy, foldingContext)) {
      return false;
    }
  }
  return true;
}

static constexpr int cudaInfMatchingValue{std::numeric_limits<int>::max()};

// Compute the matching distance as described in section 3.2.3 of the CUDA
// Fortran references.
static int GetMatchingDistance(const common::LanguageFeatureControl &features,
    const characteristics::DummyArgument &dummy,
    const std::optional<ActualArgument> &actual) {
  bool isCudaManaged{features.IsEnabled(common::LanguageFeature::CudaManaged)};
  bool isCudaUnified{features.IsEnabled(common::LanguageFeature::CudaUnified)};
  CHECK(!(isCudaUnified && isCudaManaged) && "expect only one enabled.");

  std::optional<common::CUDADataAttr> actualDataAttr, dummyDataAttr;
  if (actual) {
    if (auto *expr{actual->UnwrapExpr()}) {
      const auto *actualLastSymbol{evaluate::GetLastSymbol(*expr)};
      if (actualLastSymbol) {
        actualLastSymbol = &semantics::ResolveAssociations(*actualLastSymbol);
        if (const auto *actualObject{actualLastSymbol
                    ? actualLastSymbol
                          ->detailsIf<semantics::ObjectEntityDetails>()
                    : nullptr}) {
          actualDataAttr = actualObject->cudaDataAttr();
        }
      }
    }
  }

  common::visit(common::visitors{
                    [&](const characteristics::DummyDataObject &object) {
                      dummyDataAttr = object.cudaDataAttr;
                    },
                    [&](const auto &) {},
                },
      dummy.u);

  if (!dummyDataAttr) {
    if (!actualDataAttr) {
      if (isCudaUnified || isCudaManaged) {
        return 3;
      }
      return 0;
    } else if (*actualDataAttr == common::CUDADataAttr::Device) {
      return cudaInfMatchingValue;
    } else if (*actualDataAttr == common::CUDADataAttr::Managed ||
        *actualDataAttr == common::CUDADataAttr::Unified) {
      return 3;
    }
  } else if (*dummyDataAttr == common::CUDADataAttr::Device) {
    if (!actualDataAttr) {
      if (isCudaUnified || isCudaManaged) {
        return 2;
      }
      return cudaInfMatchingValue;
    } else if (*actualDataAttr == common::CUDADataAttr::Device) {
      return 0;
    } else if (*actualDataAttr == common::CUDADataAttr::Managed ||
        *actualDataAttr == common::CUDADataAttr::Unified) {
      return 2;
    }
  } else if (*dummyDataAttr == common::CUDADataAttr::Managed) {
    if (!actualDataAttr) {
      return isCudaUnified ? 1 : isCudaManaged ? 0 : cudaInfMatchingValue;
    }
    if (*actualDataAttr == common::CUDADataAttr::Device) {
      return cudaInfMatchingValue;
    } else if (*actualDataAttr == common::CUDADataAttr::Managed) {
      return 0;
    } else if (*actualDataAttr == common::CUDADataAttr::Unified) {
      return 1;
    }
  } else if (*dummyDataAttr == common::CUDADataAttr::Unified) {
    if (!actualDataAttr) {
      return isCudaUnified ? 0 : isCudaManaged ? 1 : cudaInfMatchingValue;
    }
    if (*actualDataAttr == common::CUDADataAttr::Device) {
      return cudaInfMatchingValue;
    } else if (*actualDataAttr == common::CUDADataAttr::Managed) {
      return 1;
    } else if (*actualDataAttr == common::CUDADataAttr::Unified) {
      return 0;
    }
  }
  return cudaInfMatchingValue;
}

static int ComputeCudaMatchingDistance(
    const common::LanguageFeatureControl &features,
    const characteristics::Procedure &procedure,
    const ActualArguments &actuals) {
  const auto &dummies{procedure.dummyArguments};
  CHECK(dummies.size() == actuals.size());
  int distance{0};
  for (std::size_t i{0}; i < dummies.size(); ++i) {
    const characteristics::DummyArgument &dummy{dummies[i]};
    const std::optional<ActualArgument> &actual{actuals[i]};
    int d{GetMatchingDistance(features, dummy, actual)};
    if (d == cudaInfMatchingValue)
      return d;
    distance += d;
  }
  return distance;
}

// Handles a forward reference to a module function from what must
// be a specification expression.  Return false if the symbol is
// an invalid forward reference.
const Symbol *ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
  if (context_.HasError(symbol)) {
    return nullptr;
  }
  if (const auto *details{
          symbol.detailsIf<semantics::SubprogramNameDetails>()}) {
    if (details->kind() == semantics::SubprogramKind::Module) {
      // If this symbol is still a SubprogramNameDetails, we must be
      // checking a specification expression in a sibling module
      // procedure.  Resolve its names now so that its interface
      // is known.
      const semantics::Scope &scope{symbol.owner()};
      semantics::ResolveSpecificationParts(context_, symbol);
      const Symbol *resolved{nullptr};
      if (auto iter{scope.find(symbol.name())}; iter != scope.cend()) {
        resolved = &*iter->second;
      }
      if (!resolved || resolved->has<semantics::SubprogramNameDetails>()) {
        // When the symbol hasn't had its details updated, we must have
        // already been in the process of resolving the function's
        // specification part; but recursive function calls are not
        // allowed in specification parts (10.1.11 para 5).
        Say("The module function '%s' may not be referenced recursively in a specification expression"_err_en_US,
            symbol.name());
        context_.SetError(symbol);
      }
      return resolved;
    } else if (inStmtFunctionDefinition_) {
      semantics::ResolveSpecificationParts(context_, symbol);
      CHECK(symbol.has<semantics::SubprogramDetails>());
    } else { // 10.1.11 para 4
      Say("The internal function '%s' may not be referenced in a specification expression"_err_en_US,
          symbol.name());
      context_.SetError(symbol);
      return nullptr;
    }
  }
  return &symbol;
}

// Resolve a call to a generic procedure with given actual arguments.
// adjustActuals is called on procedure bindings to handle pass arg.
std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
    const Symbol &symbol, const ActualArguments &actuals,
    const AdjustActuals &adjustActuals, bool isSubroutine,
    bool mightBeStructureConstructor) {
  const Symbol *elemental{nullptr}; // matching elemental specific proc
  const Symbol *nonElemental{nullptr}; // matching non-elemental specific
  const Symbol &ultimate{symbol.GetUltimate()};
  int crtMatchingDistance{cudaInfMatchingValue};
  // Check for a match with an explicit INTRINSIC
  if (ultimate.attrs().test(semantics::Attr::INTRINSIC)) {
    parser::Messages buffer;
    auto restorer{foldingContext_.messages().SetMessages(buffer)};
    ActualArguments localActuals{actuals};
    if (context_.intrinsics().Probe(
            CallCharacteristics{ultimate.name().ToString(), isSubroutine},
            localActuals, foldingContext_) &&
        !buffer.AnyFatalError()) {
      return {&ultimate, false};
    }
  }
  if (const auto *details{ultimate.detailsIf<semantics::GenericDetails>()}) {
    for (const Symbol &specific0 : details->specificProcs()) {
      const Symbol &specific1{BypassGeneric(specific0)};
      if (isSubroutine != !IsFunction(specific1)) {
        continue;
      }
      const Symbol *specific{ResolveForward(specific1)};
      if (!specific) {
        continue;
      }
      if (std::optional<characteristics::Procedure> procedure{
              characteristics::Procedure::Characterize(
                  ProcedureDesignator{*specific}, context_.foldingContext(),
                  /*emitError=*/false)}) {
        ActualArguments localActuals{actuals};
        if (specific->has<semantics::ProcBindingDetails>()) {
          if (!adjustActuals.value()(*specific, localActuals)) {
            continue;
          }
        }
        if (semantics::CheckInterfaceForGeneric(*procedure, localActuals,
                context_, false /* no integer conversions */) &&
            CheckCompatibleArguments(
                *procedure, localActuals, foldingContext_)) {
          if ((procedure->IsElemental() && elemental) ||
              (!procedure->IsElemental() && nonElemental)) {
            int d{ComputeCudaMatchingDistance(
                context_.languageFeatures(), *procedure, localActuals)};
            if (d != crtMatchingDistance) {
              if (d > crtMatchingDistance) {
                continue;
              }
              // Matching distance is smaller than the previously matched
              // specific. Let it go thourgh so the current procedure is picked.
            } else {
              // 16.9.144(6): a bare NULL() is not allowed as an actual
              // argument to a generic procedure if the specific procedure
              // cannot be unambiguously distinguished
              // Underspecified external procedure actual arguments can
              // also lead to ambiguity.
              return {nullptr, true /* due to ambiguity */};
            }
          }
          if (!procedure->IsElemental()) {
            // takes priority over elemental match
            nonElemental = specific;
          } else {
            elemental = specific;
          }
          crtMatchingDistance = ComputeCudaMatchingDistance(
              context_.languageFeatures(), *procedure, localActuals);
        }
      }
    }
    if (nonElemental) {
      return {&AccessSpecific(symbol, *nonElemental), false};
    } else if (elemental) {
      return {&AccessSpecific(symbol, *elemental), false};
    }
    // Check parent derived type
    if (const auto *parentScope{symbol.owner().GetDerivedTypeParent()}) {
      if (const Symbol *extended{parentScope->FindComponent(symbol.name())}) {
        auto pair{ResolveGeneric(
            *extended, actuals, adjustActuals, isSubroutine, false)};
        if (pair.first) {
          return pair;
        }
      }
    }
    if (mightBeStructureConstructor && details->derivedType()) {
      return {details->derivedType(), false};
    }
  }
  // Check for generic or explicit INTRINSIC of the same name in outer scopes.
  // See 15.5.5.2 for details.
  if (!symbol.owner().IsGlobal() && !symbol.owner().IsDerivedType()) {
    for (const std::string &n : GetAllNames(context_, symbol.name())) {
      if (const Symbol *outer{symbol.owner().parent().FindSymbol(n)}) {
        auto pair{ResolveGeneric(*outer, actuals, adjustActuals, isSubroutine,
            mightBeStructureConstructor)};
        if (pair.first) {
          return pair;
        }
      }
    }
  }
  return {nullptr, false};
}

const Symbol &ExpressionAnalyzer::AccessSpecific(
    const Symbol &originalGeneric, const Symbol &specific) {
  if (const auto *hosted{
          originalGeneric.detailsIf<semantics::HostAssocDetails>()}) {
    return AccessSpecific(hosted->symbol(), specific);
  } else if (const auto *used{
                 originalGeneric.detailsIf<semantics::UseDetails>()}) {
    const auto &scope{originalGeneric.owner()};
    if (auto iter{scope.find(specific.name())}; iter != scope.end()) {
      if (const auto *useDetails{
              iter->second->detailsIf<semantics::UseDetails>()}) {
        const Symbol &usedSymbol{useDetails->symbol()};
        const auto *usedGeneric{
            usedSymbol.detailsIf<semantics::GenericDetails>()};
        if (&usedSymbol == &specific ||
            (usedGeneric && usedGeneric->specific() == &specific)) {
          return specific;
        }
      }
    }
    // Create a renaming USE of the specific procedure.
    auto rename{context_.SaveTempName(
        used->symbol().owner().GetName().value().ToString() + "$" +
        specific.owner().GetName().value().ToString() + "$" +
        specific.name().ToString())};
    return *const_cast<semantics::Scope &>(scope)
                .try_emplace(rename, specific.attrs(),
                    semantics::UseDetails{rename, specific})
                .first->second;
  } else {
    return specific;
  }
}

void ExpressionAnalyzer::EmitGenericResolutionError(
    const Symbol &symbol, bool dueToAmbiguity, bool isSubroutine) {
  Say(dueToAmbiguity
          ? "The actual arguments to the generic procedure '%s' matched multiple specific procedures, perhaps due to use of NULL() without MOLD= or an actual procedure with an implicit interface"_err_en_US
          : semantics::IsGenericDefinedOp(symbol)
          ? "No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US
          : isSubroutine
          ? "No specific subroutine of generic '%s' matches the actual arguments"_err_en_US
          : "No specific function of generic '%s' matches the actual arguments"_err_en_US,
      symbol.name());
}

auto ExpressionAnalyzer::GetCalleeAndArguments(
    const parser::ProcedureDesignator &pd, ActualArguments &&arguments,
    bool isSubroutine, bool mightBeStructureConstructor)
    -> std::optional<CalleeAndArguments> {
  return common::visit(common::visitors{
                           [&](const parser::Name &name) {
                             return GetCalleeAndArguments(name,
                                 std::move(arguments), isSubroutine,
                                 mightBeStructureConstructor);
                           },
                           [&](const parser::ProcComponentRef &pcr) {
                             return AnalyzeProcedureComponentRef(
                                 pcr, std::move(arguments), isSubroutine);
                           },
                       },
      pd.u);
}

auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
    ActualArguments &&arguments, bool isSubroutine,
    bool mightBeStructureConstructor) -> std::optional<CalleeAndArguments> {
  const Symbol *symbol{name.symbol};
  if (context_.HasError(symbol)) {
    return std::nullopt; // also handles null symbol
  }
  symbol = ResolveForward(*symbol);
  if (!symbol) {
    return std::nullopt;
  }
  name.symbol = const_cast<Symbol *>(symbol);
  const Symbol &ultimate{symbol->GetUltimate()};
  CheckForBadRecursion(name.source, ultimate);
  bool dueToAmbiguity{false};
  bool isGenericInterface{ultimate.has<semantics::GenericDetails>()};
  bool isExplicitIntrinsic{ultimate.attrs().test(semantics::Attr::INTRINSIC)};
  const Symbol *resolution{nullptr};
  if (isGenericInterface || isExplicitIntrinsic) {
    ExpressionAnalyzer::AdjustActuals noAdjustment;
    auto pair{ResolveGeneric(*symbol, arguments, noAdjustment, isSubroutine,
        mightBeStructureConstructor)};
    resolution = pair.first;
    dueToAmbiguity = pair.second;
    if (resolution) {
      if (context_.GetPPCBuiltinsScope() &&
          resolution->name().ToString().rfind("__ppc_", 0) == 0) {
        semantics::CheckPPCIntrinsic(
            *symbol, *resolution, arguments, GetFoldingContext());
      }
      // re-resolve name to the specific procedure
      name.symbol = const_cast<Symbol *>(resolution);
    }
  } else if (IsProcedure(ultimate) &&
      ultimate.attrs().test(semantics::Attr::ABSTRACT)) {
    Say("Abstract procedure interface '%s' may not be referenced"_err_en_US,
        name.source);
  } else {
    resolution = symbol;
  }
  if (resolution && context_.targetCharacteristics().isOSWindows()) {
    semantics::CheckWindowsIntrinsic(*resolution, GetFoldingContext());
  }
  if (!resolution || resolution->attrs().test(semantics::Attr::INTRINSIC)) {
    auto name{resolution ? resolution->name() : ultimate.name()};
    if (std::optional<SpecificCall> specificCall{context_.intrinsics().Probe(
            CallCharacteristics{name.ToString(), isSubroutine}, arguments,
            GetFoldingContext())}) {
      CheckBadExplicitType(*specificCall, *symbol);
      return CalleeAndArguments{
          ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
          std::move(specificCall->arguments)};
    } else {
      if (isGenericInterface) {
        EmitGenericResolutionError(*symbol, dueToAmbiguity, isSubroutine);
      }
      return std::nullopt;
    }
  }
  if (resolution->GetUltimate().has<semantics::DerivedTypeDetails>()) {
    if (mightBeStructureConstructor) {
      return CalleeAndArguments{
          semantics::SymbolRef{*resolution}, std::move(arguments)};
    }
  } else if (IsProcedure(*resolution)) {
    return CalleeAndArguments{
        ProcedureDesignator{*resolution}, std::move(arguments)};
  }
  if (!context_.HasError(*resolution)) {
    AttachDeclaration(
        Say(name.source, "'%s' is not a callable procedure"_err_en_US,
            name.source),
        *resolution);
  }
  return std::nullopt;
}

// Fortran 2018 expressly states (8.2 p3) that any declared type for a
// generic intrinsic function "has no effect" on the result type of a
// call to that intrinsic.  So one can declare "character*8 cos" and
// still get a real result from "cos(1.)".  This is a dangerous feature,
// especially since implementations are free to extend their sets of
// intrinsics, and in doing so might clash with a name in a program.
// So we emit a warning in this situation, and perhaps it should be an
// error -- any correctly working program can silence the message by
// simply deleting the pointless type declaration.
void ExpressionAnalyzer::CheckBadExplicitType(
    const SpecificCall &call, const Symbol &intrinsic) {
  if (intrinsic.GetUltimate().GetType()) {
    const auto &procedure{call.specificIntrinsic.characteristics.value()};
    if (const auto &result{procedure.functionResult}) {
      if (const auto *typeAndShape{result->GetTypeAndShape()}) {
        if (auto declared{
                typeAndShape->Characterize(intrinsic, GetFoldingContext())}) {
          if (!declared->type().IsTkCompatibleWith(typeAndShape->type())) {
            if (auto *msg{Warn(
                    common::UsageWarning::IgnoredIntrinsicFunctionType,
                    "The result type '%s' of the intrinsic function '%s' is not the explicit declared type '%s'"_warn_en_US,
                    typeAndShape->AsFortran(), intrinsic.name(),
                    declared->AsFortran())}) {
              msg->Attach(intrinsic.name(),
                  "Ignored declaration of intrinsic function '%s'"_en_US,
                  intrinsic.name());
            }
          }
        }
      }
    }
  }
}

void ExpressionAnalyzer::CheckForBadRecursion(
    parser::CharBlock callSite, const semantics::Symbol &proc) {
  if (const auto *scope{proc.scope()}) {
    if (scope->sourceRange().Contains(callSite)) {
      parser::Message *msg{nullptr};
      if (proc.attrs().test(semantics::Attr::NON_RECURSIVE)) { // 15.6.2.1(3)
        msg = Say("NON_RECURSIVE procedure '%s' cannot call itself"_err_en_US,
            callSite);
      } else if (IsAssumedLengthCharacter(proc) && IsExternal(proc)) {
        // TODO: Also catch assumed PDT type parameters
        msg = Say( // 15.6.2.1(3)
            "Assumed-length CHARACTER(*) function '%s' cannot call itself"_err_en_US,
            callSite);
      } else if (FindCUDADeviceContext(scope)) {
        msg = Say(
            "Device subprogram '%s' cannot call itself"_err_en_US, callSite);
      }
      AttachDeclaration(msg, proc);
    }
  }
}

template <typename A> static const Symbol *AssumedTypeDummy(const A &x) {
  if (const auto *designator{
          std::get_if<common::Indirection<parser::Designator>>(&x.u)}) {
    if (const auto *dataRef{
            std::get_if<parser::DataRef>(&designator->value().u)}) {
      if (const auto *name{std::get_if<parser::Name>(&dataRef->u)}) {
        return AssumedTypeDummy(*name);
      }
    }
  }
  return nullptr;
}
template <>
const Symbol *AssumedTypeDummy<parser::Name>(const parser::Name &name) {
  if (const Symbol *symbol{name.symbol}) {
    if (const auto *type{symbol->GetType()}) {
      if (type->category() == semantics::DeclTypeSpec::TypeStar) {
        return symbol;
      }
    }
  }
  return nullptr;
}
template <typename A>
static const Symbol *AssumedTypePointerOrAllocatableDummy(const A &object) {
  // It is illegal for allocatable of pointer objects to be TYPE(*), but at that
  // point it is not guaranteed that it has been checked the object has
  // POINTER or ALLOCATABLE attribute, so do not assume nullptr can be directly
  // returned.
  return common::visit(
      common::visitors{
          [&](const parser::StructureComponent &x) {
            return AssumedTypeDummy(x.component);
          },
          [&](const parser::Name &x) { return AssumedTypeDummy(x); },
      },
      object.u);
}
template <>
const Symbol *AssumedTypeDummy<parser::AllocateObject>(
    const parser::AllocateObject &x) {
  return AssumedTypePointerOrAllocatableDummy(x);
}
template <>
const Symbol *AssumedTypeDummy<parser::PointerObject>(
    const parser::PointerObject &x) {
  return AssumedTypePointerOrAllocatableDummy(x);
}

bool ExpressionAnalyzer::CheckIsValidForwardReference(
    const semantics::DerivedTypeSpec &dtSpec) {
  if (dtSpec.IsForwardReferenced()) {
    Say("Cannot construct value for derived type '%s' before it is defined"_err_en_US,
        dtSpec.name());
    return false;
  }
  return true;
}

std::optional<Chevrons> ExpressionAnalyzer::AnalyzeChevrons(
    const parser::CallStmt &call) {
  Chevrons result;
  auto checkLaunchArg{[&](const Expr<SomeType> &expr, const char *which) {
    if (auto dyType{expr.GetType()}) {
      if (dyType->category() == TypeCategory::Integer) {
        return true;
      }
      if (dyType->category() == TypeCategory::Derived &&
          !dyType->IsPolymorphic() &&
          IsBuiltinDerivedType(&dyType->GetDerivedTypeSpec(), "dim3")) {
        return true;
      }
    }
    Say("Kernel launch %s parameter must be either integer or TYPE(dim3)"_err_en_US,
        which);
    return false;
  }};
  if (const auto &chevrons{call.chevrons}) {
    auto &starOrExpr{std::get<0>(chevrons->t)};
    if (starOrExpr.v) {
      if (auto expr{Analyze(*starOrExpr.v)};
          expr && checkLaunchArg(*expr, "grid")) {
        result.emplace_back(*expr);
      } else {
        return std::nullopt;
      }
    } else {
      result.emplace_back(
          AsGenericExpr(evaluate::Constant<evaluate::CInteger>{-1}));
    }
    if (auto expr{Analyze(std::get<1>(chevrons->t))};
        expr && checkLaunchArg(*expr, "block")) {
      result.emplace_back(*expr);
    } else {
      return std::nullopt;
    }
    if (const auto &maybeExpr{std::get<2>(chevrons->t)}) {
      if (auto expr{Analyze(*maybeExpr)}) {
        result.emplace_back(*expr);
      } else {
        return std::nullopt;
      }
    }
    if (const auto &maybeExpr{std::get<3>(chevrons->t)}) {
      if (auto expr{Analyze(*maybeExpr)}) {
        result.emplace_back(*expr);
      } else {
        return std::nullopt;
      }
    }
  }
  return std::move(result);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::FunctionReference &funcRef,
    std::optional<parser::StructureConstructor> *structureConstructor) {
  const parser::Call &call{funcRef.v};
  auto restorer{GetContextualMessages().SetLocation(funcRef.source)};
  ArgumentAnalyzer analyzer{*this, funcRef.source, true /* isProcedureCall */};
  for (const auto &arg : std::get<std::list<parser::ActualArgSpec>>(call.t)) {
    analyzer.Analyze(arg, false /* not subroutine call */);
  }
  if (analyzer.fatalErrors()) {
    return std::nullopt;
  }
  bool mightBeStructureConstructor{structureConstructor != nullptr};
  if (std::optional<CalleeAndArguments> callee{GetCalleeAndArguments(
          std::get<parser::ProcedureDesignator>(call.t), analyzer.GetActuals(),
          false /* not subroutine */, mightBeStructureConstructor)}) {
    if (auto *proc{std::get_if<ProcedureDesignator>(&callee->u)}) {
      return MakeFunctionRef(
          funcRef.source, std::move(*proc), std::move(callee->arguments));
    }
    CHECK(std::holds_alternative<semantics::SymbolRef>(callee->u));
    const Symbol &symbol{*std::get<semantics::SymbolRef>(callee->u)};
    if (mightBeStructureConstructor) {
      // Structure constructor misparsed as function reference?
      const auto &designator{std::get<parser::ProcedureDesignator>(call.t)};
      if (const auto *name{std::get_if<parser::Name>(&designator.u)}) {
        semantics::Scope &scope{context_.FindScope(name->source)};
        semantics::DerivedTypeSpec dtSpec{name->source, symbol.GetUltimate()};
        if (!CheckIsValidForwardReference(dtSpec)) {
          return std::nullopt;
        }
        const semantics::DeclTypeSpec &type{
            semantics::FindOrInstantiateDerivedType(scope, std::move(dtSpec))};
        auto &mutableRef{const_cast<parser::FunctionReference &>(funcRef)};
        *structureConstructor =
            mutableRef.ConvertToStructureConstructor(type.derivedTypeSpec());
        return Analyze(structureConstructor->value());
      }
    }
    if (!context_.HasError(symbol)) {
      AttachDeclaration(
          Say("'%s' is called like a function but is not a procedure"_err_en_US,
              symbol.name()),
          symbol);
      context_.SetError(symbol);
    }
  }
  return std::nullopt;
}

static bool HasAlternateReturns(const evaluate::ActualArguments &args) {
  for (const auto &arg : args) {
    if (arg && arg->isAlternateReturn()) {
      return true;
    }
  }
  return false;
}

void ExpressionAnalyzer::Analyze(const parser::CallStmt &callStmt) {
  const parser::Call &call{callStmt.call};
  auto restorer{GetContextualMessages().SetLocation(callStmt.source)};
  ArgumentAnalyzer analyzer{*this, callStmt.source, true /* isProcedureCall */};
  const auto &actualArgList{std::get<std::list<parser::ActualArgSpec>>(call.t)};
  for (const auto &arg : actualArgList) {
    analyzer.Analyze(arg, true /* is subroutine call */);
  }
  if (auto chevrons{AnalyzeChevrons(callStmt)};
      chevrons && !analyzer.fatalErrors()) {
    if (std::optional<CalleeAndArguments> callee{
            GetCalleeAndArguments(std::get<parser::ProcedureDesignator>(call.t),
                analyzer.GetActuals(), true /* subroutine */)}) {
      ProcedureDesignator *proc{std::get_if<ProcedureDesignator>(&callee->u)};
      CHECK(proc);
      bool isKernel{false};
      if (const Symbol * procSym{proc->GetSymbol()}) {
        const Symbol &ultimate{procSym->GetUltimate()};
        if (const auto *subpDetails{
                ultimate.detailsIf<semantics::SubprogramDetails>()}) {
          if (auto attrs{subpDetails->cudaSubprogramAttrs()}) {
            isKernel = *attrs == common::CUDASubprogramAttrs::Global ||
                *attrs == common::CUDASubprogramAttrs::Grid_Global;
          }
        } else if (const auto *procDetails{
                       ultimate.detailsIf<semantics::ProcEntityDetails>()}) {
          isKernel = procDetails->isCUDAKernel();
        }
        if (isKernel && chevrons->empty()) {
          Say("'%s' is a kernel subroutine and must be called with kernel launch parameters in chevrons"_err_en_US,
              procSym->name());
        }
      }
      if (!isKernel && !chevrons->empty()) {
        Say("Kernel launch parameters in chevrons may not be used unless calling a kernel subroutine"_err_en_US);
      }
      if (CheckCall(callStmt.source, *proc, callee->arguments)) {
        callStmt.typedCall.Reset(
            new ProcedureRef{std::move(*proc), std::move(callee->arguments),
                HasAlternateReturns(callee->arguments)},
            ProcedureRef::Deleter);
        DEREF(callStmt.typedCall.get()).set_chevrons(std::move(*chevrons));
        return;
      }
    }
    if (!context_.AnyFatalError()) {
      std::string buf;
      llvm::raw_string_ostream dump{buf};
      parser::DumpTree(dump, callStmt);
      Say("Internal error: Expression analysis failed on CALL statement: %s"_err_en_US,
          buf);
    }
  }
}

const Assignment *ExpressionAnalyzer::Analyze(const parser::AssignmentStmt &x) {
  if (!x.typedAssignment) {
    ArgumentAnalyzer analyzer{*this};
    const auto &variable{std::get<parser::Variable>(x.t)};
    analyzer.Analyze(variable);
    analyzer.Analyze(std::get<parser::Expr>(x.t));
    std::optional<Assignment> assignment;
    if (!analyzer.fatalErrors()) {
      auto restorer{GetContextualMessages().SetLocation(variable.GetSource())};
      std::optional<ProcedureRef> procRef{analyzer.TryDefinedAssignment()};
      if (!procRef) {
        analyzer.CheckForNullPointer(
            "in a non-pointer intrinsic assignment statement");
        analyzer.CheckForAssumedRank("in an assignment statement");
        const Expr<SomeType> &lhs{analyzer.GetExpr(0)};
        if (auto dyType{lhs.GetType()};
            dyType && dyType->IsPolymorphic()) { // 10.2.1.2p1(1)
          const Symbol *lastWhole0{UnwrapWholeSymbolOrComponentDataRef(lhs)};
          const Symbol *lastWhole{
              lastWhole0 ? &lastWhole0->GetUltimate() : nullptr};
          if (!lastWhole || !IsAllocatable(*lastWhole)) {
            Say("Left-hand side of assignment may not be polymorphic unless assignment is to an entire allocatable"_err_en_US);
          } else if (evaluate::IsCoarray(*lastWhole)) {
            Say("Left-hand side of assignment may not be polymorphic if it is a coarray"_err_en_US);
          }
        }
      }
      assignment.emplace(analyzer.MoveExpr(0), analyzer.MoveExpr(1));
      if (procRef) {
        assignment->u = std::move(*procRef);
      }
    }
    x.typedAssignment.Reset(new GenericAssignmentWrapper{std::move(assignment)},
        GenericAssignmentWrapper::Deleter);
  }
  return common::GetPtrFromOptional(x.typedAssignment->v);
}

const Assignment *ExpressionAnalyzer::Analyze(
    const parser::PointerAssignmentStmt &x) {
  if (!x.typedAssignment) {
    MaybeExpr lhs{Analyze(std::get<parser::DataRef>(x.t))};
    MaybeExpr rhs;
    {
      auto restorer{AllowNullPointer()};
      rhs = Analyze(std::get<parser::Expr>(x.t));
    }
    if (!lhs || !rhs) {
      x.typedAssignment.Reset(
          new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter);
    } else {
      Assignment assignment{std::move(*lhs), std::move(*rhs)};
      common::visit(
          common::visitors{
              [&](const std::list<parser::BoundsRemapping> &list) {
                Assignment::BoundsRemapping bounds;
                for (const auto &elem : list) {
                  auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
                  auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
                  if (lower && upper) {
                    bounds.emplace_back(
                        Fold(std::move(*lower)), Fold(std::move(*upper)));
                  }
                }
                assignment.u = std::move(bounds);
              },
              [&](const std::list<parser::BoundsSpec> &list) {
                Assignment::BoundsSpec bounds;
                for (const auto &bound : list) {
                  if (auto lower{AsSubscript(Analyze(bound.v))}) {
                    bounds.emplace_back(Fold(std::move(*lower)));
                  }
                }
                assignment.u = std::move(bounds);
              },
          },
          std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u);
      x.typedAssignment.Reset(
          new GenericAssignmentWrapper{std::move(assignment)},
          GenericAssignmentWrapper::Deleter);
    }
  }
  return common::GetPtrFromOptional(x.typedAssignment->v);
}

static bool IsExternalCalledImplicitly(
    parser::CharBlock callSite, const Symbol *symbol) {
  return symbol && symbol->owner().IsGlobal() &&
      symbol->has<semantics::SubprogramDetails>() &&
      (!symbol->scope() /*ENTRY*/ ||
          !symbol->scope()->sourceRange().Contains(callSite));
}

std::optional<characteristics::Procedure> ExpressionAnalyzer::CheckCall(
    parser::CharBlock callSite, const ProcedureDesignator &proc,
    ActualArguments &arguments) {
  bool treatExternalAsImplicit{
      IsExternalCalledImplicitly(callSite, proc.GetSymbol())};
  const Symbol *procSymbol{proc.GetSymbol()};
  std::optional<characteristics::Procedure> chars;
  if (procSymbol && procSymbol->has<semantics::ProcEntityDetails>() &&
      procSymbol->owner().IsGlobal()) {
    // Unknown global external, implicit interface; assume
    // characteristics from the actual arguments, and check
    // for consistency with other references.
    chars = characteristics::Procedure::FromActuals(
        proc, arguments, context_.foldingContext());
    if (chars && procSymbol) {
      // Ensure calls over implicit interfaces are consistent
      auto name{procSymbol->name()};
      if (auto iter{implicitInterfaces_.find(name)};
          iter != implicitInterfaces_.end()) {
        std::string whyNot;
        if (!chars->IsCompatibleWith(iter->second.second,
                /*ignoreImplicitVsExplicit=*/false, &whyNot)) {
          if (auto *msg{Warn(
                  common::UsageWarning::IncompatibleImplicitInterfaces,
                  callSite,
                  "Reference to the procedure '%s' has an implicit interface that is distinct from another reference: %s"_warn_en_US,
                  name, whyNot)}) {
            msg->Attach(
                iter->second.first, "previous reference to '%s'"_en_US, name);
          }
        }
      } else {
        implicitInterfaces_.insert(
            std::make_pair(name, std::make_pair(callSite, *chars)));
      }
    }
  }
  if (!chars) {
    chars = characteristics::Procedure::Characterize(
        proc, context_.foldingContext(), /*emitError=*/true);
  }
  bool ok{true};
  if (chars) {
    std::string whyNot;
    if (treatExternalAsImplicit &&
        !chars->CanBeCalledViaImplicitInterface(&whyNot)) {
      if (auto *msg{Say(callSite,
              "References to the procedure '%s' require an explicit interface"_err_en_US,
              DEREF(procSymbol).name())};
          msg && !whyNot.empty()) {
        msg->Attach(callSite, "%s"_because_en_US, whyNot);
      }
    }
    const SpecificIntrinsic *specificIntrinsic{proc.GetSpecificIntrinsic()};
    bool procIsDummy{procSymbol && IsDummy(*procSymbol)};
    if (chars->functionResult &&
        chars->functionResult->IsAssumedLengthCharacter() &&
        !specificIntrinsic && !procIsDummy) {
      Say(callSite,
          "Assumed-length character function must be defined with a length to be called"_err_en_US);
    }
    ok &= semantics::CheckArguments(*chars, arguments, context_,
        context_.FindScope(callSite), treatExternalAsImplicit,
        /*ignoreImplicitVsExplicit=*/false, specificIntrinsic);
  }
  if (procSymbol && !IsPureProcedure(*procSymbol)) {
    if (const semantics::Scope *
        pure{semantics::FindPureProcedureContaining(
            context_.FindScope(callSite))}) {
      Say(callSite,
          "Procedure '%s' referenced in pure subprogram '%s' must be pure too"_err_en_US,
          procSymbol->name(), DEREF(pure->symbol()).name());
    }
  }
  if (ok && !treatExternalAsImplicit && procSymbol &&
      !(chars && chars->HasExplicitInterface())) {
    if (const Symbol *global{FindGlobal(*procSymbol)};
        global && global != procSymbol && IsProcedure(*global)) {
      // Check a known global definition behind a local interface
      if (auto globalChars{characteristics::Procedure::Characterize(
              *global, context_.foldingContext())}) {
        semantics::CheckArguments(*globalChars, arguments, context_,
            context_.FindScope(callSite), /*treatExternalAsImplicit=*/true,
            /*ignoreImplicitVsExplicit=*/false,
            nullptr /*not specific intrinsic*/);
      }
    }
  }
  return chars;
}

// Unary operations

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Parentheses &x) {
  if (MaybeExpr operand{Analyze(x.v.value())}) {
    if (const semantics::Symbol *symbol{GetLastSymbol(*operand)}) {
      if (const semantics::Symbol *result{FindFunctionResult(*symbol)}) {
        if (semantics::IsProcedurePointer(*result)) {
          Say("A function reference that returns a procedure "
              "pointer may not be parenthesized"_err_en_US); // C1003
        }
      }
    }
    return Parenthesize(std::move(*operand));
  }
  return std::nullopt;
}

static MaybeExpr NumericUnaryHelper(ExpressionAnalyzer &context,
    NumericOperator opr, const parser::Expr::IntrinsicUnary &x) {
  ArgumentAnalyzer analyzer{context};
  analyzer.Analyze(x.v);
  if (!analyzer.fatalErrors()) {
    if (analyzer.IsIntrinsicNumeric(opr)) {
      analyzer.CheckForNullPointer();
      analyzer.CheckForAssumedRank();
      if (opr == NumericOperator::Add) {
        return analyzer.MoveExpr(0);
      } else {
        return Negation(context.GetContextualMessages(), analyzer.MoveExpr(0));
      }
    } else {
      return analyzer.TryDefinedOp(AsFortran(opr),
          "Operand of unary %s must be numeric; have %s"_err_en_US);
    }
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::UnaryPlus &x) {
  return NumericUnaryHelper(*this, NumericOperator::Add, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Negate &x) {
  if (const auto *litConst{
          std::get_if<parser::LiteralConstant>(&x.v.value().u)}) {
    if (const auto *intConst{
            std::get_if<parser::IntLiteralConstant>(&litConst->u)}) {
      return Analyze(*intConst, true);
    }
  }
  return NumericUnaryHelper(*this, NumericOperator::Subtract, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NOT &x) {
  ArgumentAnalyzer analyzer{*this};
  analyzer.Analyze(x.v);
  if (!analyzer.fatalErrors()) {
    if (analyzer.IsIntrinsicLogical()) {
      analyzer.CheckForNullPointer();
      analyzer.CheckForAssumedRank();
      return AsGenericExpr(
          LogicalNegation(std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u)));
    } else {
      return analyzer.TryDefinedOp(LogicalOperator::Not,
          "Operand of %s must be LOGICAL; have %s"_err_en_US);
    }
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::PercentLoc &x) {
  // Represent %LOC() exactly as if it had been a call to the LOC() extension
  // intrinsic function.
  // Use the actual source for the name of the call for error reporting.
  std::optional<ActualArgument> arg;
  if (const Symbol *assumedTypeDummy{AssumedTypeDummy(x.v.value())}) {
    arg = ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}};
  } else if (MaybeExpr argExpr{Analyze(x.v.value())}) {
    arg = ActualArgument{std::move(*argExpr)};
  } else {
    return std::nullopt;
  }
  parser::CharBlock at{GetContextualMessages().at()};
  CHECK(at.size() >= 4);
  parser::CharBlock loc{at.begin() + 1, 3};
  CHECK(loc == "loc");
  return MakeFunctionRef(loc, ActualArguments{std::move(*arg)});
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedUnary &x) {
  const auto &name{std::get<parser::DefinedOpName>(x.t).v};
  ArgumentAnalyzer analyzer{*this, name.source};
  analyzer.Analyze(std::get<1>(x.t));
  return analyzer.TryDefinedOp(name.source.ToString().c_str(),
      "No operator %s defined for %s"_err_en_US, true);
}

// Binary (dyadic) operations

template <template <typename> class OPR, NumericOperator opr>
MaybeExpr NumericBinaryHelper(
    ExpressionAnalyzer &context, const parser::Expr::IntrinsicBinary &x) {
  ArgumentAnalyzer analyzer{context};
  analyzer.Analyze(std::get<0>(x.t));
  analyzer.Analyze(std::get<1>(x.t));
  if (!analyzer.fatalErrors()) {
    if (analyzer.IsIntrinsicNumeric(opr)) {
      analyzer.CheckForNullPointer();
      analyzer.CheckForAssumedRank();
      analyzer.CheckConformance();
      constexpr bool canBeUnsigned{opr != NumericOperator::Power};
      return NumericOperation<OPR, canBeUnsigned>(
          context.GetContextualMessages(), analyzer.MoveExpr(0),
          analyzer.MoveExpr(1), context.GetDefaultKind(TypeCategory::Real));
    } else {
      return analyzer.TryDefinedOp(AsFortran(opr),
          "Operands of %s must be numeric; have %s and %s"_err_en_US);
    }
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Power &x) {
  return NumericBinaryHelper<Power, NumericOperator::Power>(*this, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Multiply &x) {
  return NumericBinaryHelper<Multiply, NumericOperator::Multiply>(*this, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Divide &x) {
  return NumericBinaryHelper<Divide, NumericOperator::Divide>(*this, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Add &x) {
  return NumericBinaryHelper<Add, NumericOperator::Add>(*this, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Subtract &x) {
  return NumericBinaryHelper<Subtract, NumericOperator::Subtract>(*this, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(
    const parser::Expr::ComplexConstructor &z) {
  Warn(common::LanguageFeature::ComplexConstructor,
      "nonstandard usage: generalized COMPLEX constructor"_port_en_US);
  return AnalyzeComplex(Analyze(std::get<0>(z.t).value()),
      Analyze(std::get<1>(z.t).value()), "complex constructor");
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
  ArgumentAnalyzer analyzer{*this};
  analyzer.Analyze(std::get<0>(x.t));
  analyzer.Analyze(std::get<1>(x.t));
  if (!analyzer.fatalErrors()) {
    if (analyzer.IsIntrinsicConcat()) {
      analyzer.CheckForNullPointer();
      analyzer.CheckForAssumedRank();
      return common::visit(
          [&](auto &&x, auto &&y) -> MaybeExpr {
            using T = ResultType<decltype(x)>;
            if constexpr (std::is_same_v<T, ResultType<decltype(y)>>) {
              return AsGenericExpr(Concat<T::kind>{std::move(x), std::move(y)});
            } else {
              DIE("different types for intrinsic concat");
            }
          },
          std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(0).u).u),
          std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(1).u).u));
    } else {
      return analyzer.TryDefinedOp("//",
          "Operands of %s must be CHARACTER with the same kind; have %s and %s"_err_en_US);
    }
  }
  return std::nullopt;
}

// The Name represents a user-defined intrinsic operator.
// If the actuals match one of the specific procedures, return a function ref.
// Otherwise report the error in messages.
MaybeExpr ExpressionAnalyzer::AnalyzeDefinedOp(
    const parser::Name &name, ActualArguments &&actuals) {
  if (auto callee{GetCalleeAndArguments(name, std::move(actuals))}) {
    CHECK(std::holds_alternative<ProcedureDesignator>(callee->u));
    return MakeFunctionRef(name.source,
        std::move(std::get<ProcedureDesignator>(callee->u)),
        std::move(callee->arguments));
  } else {
    return std::nullopt;
  }
}

MaybeExpr RelationHelper(ExpressionAnalyzer &context, RelationalOperator opr,
    const parser::Expr::IntrinsicBinary &x) {
  ArgumentAnalyzer analyzer{context};
  analyzer.Analyze(std::get<0>(x.t));
  analyzer.Analyze(std::get<1>(x.t));
  if (!analyzer.fatalErrors()) {
    std::optional<DynamicType> leftType{analyzer.GetType(0)};
    std::optional<DynamicType> rightType{analyzer.GetType(1)};
    analyzer.ConvertBOZ(&leftType, 0, rightType);
    analyzer.ConvertBOZ(&rightType, 1, leftType);
    if (leftType && rightType &&
        analyzer.IsIntrinsicRelational(opr, *leftType, *rightType)) {
      analyzer.CheckForNullPointer("as a relational operand");
      analyzer.CheckForAssumedRank("as a relational operand");
      if (auto cmp{Relate(context.GetContextualMessages(), opr,
              analyzer.MoveExpr(0), analyzer.MoveExpr(1))}) {
        return AsMaybeExpr(ConvertToKind<TypeCategory::Logical>(
            context.GetDefaultKind(TypeCategory::Logical),
            AsExpr(std::move(*cmp))));
      }
    } else {
      return analyzer.TryDefinedOp(opr,
          leftType && leftType->category() == TypeCategory::Logical &&
                  rightType && rightType->category() == TypeCategory::Logical
              ? "LOGICAL operands must be compared using .EQV. or .NEQV."_err_en_US
              : "Operands of %s must have comparable types; have %s and %s"_err_en_US);
    }
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LT &x) {
  return RelationHelper(*this, RelationalOperator::LT, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LE &x) {
  return RelationHelper(*this, RelationalOperator::LE, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQ &x) {
  return RelationHelper(*this, RelationalOperator::EQ, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NE &x) {
  return RelationHelper(*this, RelationalOperator::NE, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GE &x) {
  return RelationHelper(*this, RelationalOperator::GE, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GT &x) {
  return RelationHelper(*this, RelationalOperator::GT, x);
}

MaybeExpr LogicalBinaryHelper(ExpressionAnalyzer &context, LogicalOperator opr,
    const parser::Expr::IntrinsicBinary &x) {
  ArgumentAnalyzer analyzer{context};
  analyzer.Analyze(std::get<0>(x.t));
  analyzer.Analyze(std::get<1>(x.t));
  if (!analyzer.fatalErrors()) {
    if (analyzer.IsIntrinsicLogical()) {
      analyzer.CheckForNullPointer("as a logical operand");
      analyzer.CheckForAssumedRank("as a logical operand");
      return AsGenericExpr(BinaryLogicalOperation(opr,
          std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u),
          std::get<Expr<SomeLogical>>(analyzer.MoveExpr(1).u)));
    } else {
      return analyzer.TryDefinedOp(
          opr, "Operands of %s must be LOGICAL; have %s and %s"_err_en_US);
    }
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::AND &x) {
  return LogicalBinaryHelper(*this, LogicalOperator::And, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::OR &x) {
  return LogicalBinaryHelper(*this, LogicalOperator::Or, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQV &x) {
  return LogicalBinaryHelper(*this, LogicalOperator::Eqv, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NEQV &x) {
  return LogicalBinaryHelper(*this, LogicalOperator::Neqv, x);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedBinary &x) {
  const auto &name{std::get<parser::DefinedOpName>(x.t).v};
  ArgumentAnalyzer analyzer{*this, name.source};
  analyzer.Analyze(std::get<1>(x.t));
  analyzer.Analyze(std::get<2>(x.t));
  return analyzer.TryDefinedOp(name.source.ToString().c_str(),
      "No operator %s defined for %s and %s"_err_en_US, true);
}

// Returns true if a parsed function reference should be converted
// into an array element reference.
static bool CheckFuncRefToArrayElement(semantics::SemanticsContext &context,
    const parser::FunctionReference &funcRef) {
  // Emit message if the function reference fix will end up an array element
  // reference with no subscripts, or subscripts on a scalar, because it will
  // not be possible to later distinguish in expressions between an empty
  // subscript list due to bad subscripts error recovery or because the
  // user did not put any.
  auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
  const auto *name{std::get_if<parser::Name>(&proc.u)};
  if (!name) {
    name = &std::get<parser::ProcComponentRef>(proc.u).v.thing.component;
  }
  if (!name->symbol) {
    return false;
  } else if (name->symbol->Rank() == 0) {
    if (const Symbol *function{
            semantics::IsFunctionResultWithSameNameAsFunction(*name->symbol)}) {
      auto &msg{context.Say(funcRef.source,
          function->flags().test(Symbol::Flag::StmtFunction)
              ? "Recursive call to statement function '%s' is not allowed"_err_en_US
              : "Recursive call to '%s' requires a distinct RESULT in its declaration"_err_en_US,
          name->source)};
      AttachDeclaration(&msg, *function);
      name->symbol = const_cast<Symbol *>(function);
    }
    return false;
  } else {
    if (std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t).empty()) {
      auto &msg{context.Say(funcRef.source,
          "Reference to array '%s' with empty subscript list"_err_en_US,
          name->source)};
      if (name->symbol) {
        AttachDeclaration(&msg, *name->symbol);
      }
    }
    return true;
  }
}

// Converts, if appropriate, an original misparse of ambiguous syntax like
// A(1) as a function reference into an array reference.
// Misparsed structure constructors are detected elsewhere after generic
// function call resolution fails.
template <typename... A>
static void FixMisparsedFunctionReference(
    semantics::SemanticsContext &context, const std::variant<A...> &constU) {
  // The parse tree is updated in situ when resolving an ambiguous parse.
  using uType = std::decay_t<decltype(constU)>;
  auto &u{const_cast<uType &>(constU)};
  if (auto *func{
          std::get_if<common::Indirection<parser::FunctionReference>>(&u)}) {
    parser::FunctionReference &funcRef{func->value()};
    // Ensure that there are no argument keywords
    for (const auto &arg :
        std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t)) {
      if (std::get<std::optional<parser::Keyword>>(arg.t)) {
        return;
      }
    }
    auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
    if (Symbol *origSymbol{
            common::visit(common::visitors{
                              [&](parser::Name &name) { return name.symbol; },
                              [&](parser::ProcComponentRef &pcr) {
                                return pcr.v.thing.component.symbol;
                              },
                          },
                proc.u)}) {
      Symbol &symbol{origSymbol->GetUltimate()};
      if (symbol.has<semantics::ObjectEntityDetails>() ||
          symbol.has<semantics::AssocEntityDetails>()) {
        // Note that expression in AssocEntityDetails cannot be a procedure
        // pointer as per C1105 so this cannot be a function reference.
        if constexpr (common::HasMember<common::Indirection<parser::Designator>,
                          uType>) {
          if (CheckFuncRefToArrayElement(context, funcRef)) {
            u = common::Indirection{funcRef.ConvertToArrayElementRef()};
          }
        } else {
          DIE("can't fix misparsed function as array reference");
        }
      }
    }
  }
}

// Common handling of parse tree node types that retain the
// representation of the analyzed expression.
template <typename PARSED>
MaybeExpr ExpressionAnalyzer::ExprOrVariable(
    const PARSED &x, parser::CharBlock source) {
  auto restorer{GetContextualMessages().SetLocation(source)};
  if constexpr (std::is_same_v<PARSED, parser::Expr> ||
      std::is_same_v<PARSED, parser::Variable>) {
    FixMisparsedFunctionReference(context_, x.u);
  }
  if (AssumedTypeDummy(x)) { // C710
    Say("TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
    ResetExpr(x);
    return std::nullopt;
  }
  MaybeExpr result;
  if constexpr (common::HasMember<parser::StructureConstructor,
                    std::decay_t<decltype(x.u)>> &&
      common::HasMember<common::Indirection<parser::FunctionReference>,
          std::decay_t<decltype(x.u)>>) {
    if (const auto *funcRef{
            std::get_if<common::Indirection<parser::FunctionReference>>(
                &x.u)}) {
      // Function references in Exprs might turn out to be misparsed structure
      // constructors; we have to try generic procedure resolution
      // first to be sure.
      std::optional<parser::StructureConstructor> ctor;
      result = Analyze(funcRef->value(), &ctor);
      if (result && ctor) {
        // A misparsed function reference is really a structure
        // constructor.  Repair the parse tree in situ.
        const_cast<PARSED &>(x).u = std::move(*ctor);
      }
    } else {
      result = Analyze(x.u);
    }
  } else {
    result = Analyze(x.u);
  }
  if (result) {
    if constexpr (std::is_same_v<PARSED, parser::Expr>) {
      if (!isNullPointerOk_ && IsNullPointer(*result)) {
        Say(source,
            "NULL() may not be used as an expression in this context"_err_en_US);
      }
    }
    SetExpr(x, Fold(std::move(*result)));
    return x.typedExpr->v;
  } else {
    ResetExpr(x);
    if (!context_.AnyFatalError()) {
      std::string buf;
      llvm::raw_string_ostream dump{buf};
      parser::DumpTree(dump, x);
      Say("Internal error: Expression analysis failed on: %s"_err_en_US, buf);
    }
    return std::nullopt;
  }
}

// This is an optional preliminary pass over parser::Expr subtrees.
// Given an expression tree, iteratively traverse it in a bottom-up order
// to analyze all of its subexpressions.  A later normal top-down analysis
// will then be able to use the results that will have been saved in the
// parse tree without having to recurse deeply.  This technique keeps
// absurdly deep expression parse trees from causing the analyzer to overflow
// its stack.
MaybeExpr ExpressionAnalyzer::IterativelyAnalyzeSubexpressions(
    const parser::Expr &top) {
  std::vector<const parser::Expr *> queue, finish;
  queue.push_back(&top);
  do {
    const parser::Expr &expr{*queue.back()};
    queue.pop_back();
    if (!expr.typedExpr) {
      const parser::Expr::IntrinsicUnary *unary{nullptr};
      const parser::Expr::IntrinsicBinary *binary{nullptr};
      common::visit(
          [&unary, &binary](auto &y) {
            if constexpr (std::is_convertible_v<decltype(&y),
                              decltype(unary)>) {
              // Don't evaluate a constant operand to Negate
              if (!std::holds_alternative<parser::LiteralConstant>(
                      y.v.value().u)) {
                unary = &y;
              }
            } else if constexpr (std::is_convertible_v<decltype(&y),
                                     decltype(binary)>) {
              binary = &y;
            }
          },
          expr.u);
      if (unary) {
        queue.push_back(&unary->v.value());
      } else if (binary) {
        queue.push_back(&std::get<0>(binary->t).value());
        queue.push_back(&std::get<1>(binary->t).value());
      }
      finish.push_back(&expr);
    }
  } while (!queue.empty());
  // Analyze the collected subexpressions in bottom-up order.
  // On an error, bail out and leave partial results in place.
  MaybeExpr result;
  for (auto riter{finish.rbegin()}; riter != finish.rend(); ++riter) {
    const parser::Expr &expr{**riter};
    result = ExprOrVariable(expr, expr.source);
    if (!result) {
      return result;
    }
  }
  return result; // last value was from analysis of "top"
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr &expr) {
  bool wasIterativelyAnalyzing{iterativelyAnalyzingSubexpressions_};
  MaybeExpr result;
  if (useSavedTypedExprs_) {
    if (expr.typedExpr) {
      return expr.typedExpr->v;
    }
    if (!wasIterativelyAnalyzing) {
      iterativelyAnalyzingSubexpressions_ = true;
      result = IterativelyAnalyzeSubexpressions(expr);
    }
  }
  if (!result) {
    result = ExprOrVariable(expr, expr.source);
  }
  iterativelyAnalyzingSubexpressions_ = wasIterativelyAnalyzing;
  return result;
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Variable &variable) {
  if (useSavedTypedExprs_ && variable.typedExpr) {
    return variable.typedExpr->v;
  }
  return ExprOrVariable(variable, variable.GetSource());
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::Selector &selector) {
  if (const auto *var{std::get_if<parser::Variable>(&selector.u)}) {
    if (!useSavedTypedExprs_ || !var->typedExpr) {
      parser::CharBlock source{var->GetSource()};
      auto restorer{GetContextualMessages().SetLocation(source)};
      FixMisparsedFunctionReference(context_, var->u);
      if (const auto *funcRef{
              std::get_if<common::Indirection<parser::FunctionReference>>(
                  &var->u)}) {
        // A Selector that parsed as a Variable might turn out during analysis
        // to actually be a structure constructor.  In that case, repair the
        // Variable parse tree node into an Expr
        std::optional<parser::StructureConstructor> ctor;
        if (MaybeExpr result{Analyze(funcRef->value(), &ctor)}) {
          if (ctor) {
            auto &writable{const_cast<parser::Selector &>(selector)};
            writable.u = parser::Expr{std::move(*ctor)};
            auto &expr{std::get<parser::Expr>(writable.u)};
            expr.source = source;
            SetExpr(expr, Fold(std::move(*result)));
            return expr.typedExpr->v;
          } else {
            SetExpr(*var, Fold(std::move(*result)));
            return var->typedExpr->v;
          }
        } else {
          ResetExpr(*var);
          if (context_.AnyFatalError()) {
            return std::nullopt;
          }
        }
      }
    }
    // Not a Variable -> FunctionReference
    auto restorer{AllowWholeAssumedSizeArray()};
    return Analyze(selector.u);
  } else { // Expr
    return Analyze(selector.u);
  }
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtConstant &x) {
  auto restorer{common::ScopedSet(inDataStmtConstant_, true)};
  return ExprOrVariable(x, x.source);
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::AllocateObject &x) {
  return ExprOrVariable(x, parser::FindSourceLocation(x));
}

MaybeExpr ExpressionAnalyzer::Analyze(const parser::PointerObject &x) {
  return ExprOrVariable(x, parser::FindSourceLocation(x));
}

Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
    TypeCategory category,
    const std::optional<parser::KindSelector> &selector) {
  int defaultKind{GetDefaultKind(category)};
  if (!selector) {
    return Expr<SubscriptInteger>{defaultKind};
  }
  return common::visit(
      common::visitors{
          [&](const parser::ScalarIntConstantExpr &x) {
            if (MaybeExpr kind{Analyze(x)}) {
              if (std::optional<std::int64_t> code{ToInt64(*kind)}) {
                if (CheckIntrinsicKind(category, *code)) {
                  return Expr<SubscriptInteger>{*code};
                }
              } else if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(*kind)}) {
                return ConvertToType<SubscriptInteger>(std::move(*intExpr));
              }
            }
            return Expr<SubscriptInteger>{defaultKind};
          },
          [&](const parser::KindSelector::StarSize &x) {
            std::intmax_t size = x.v;
            if (!CheckIntrinsicSize(category, size)) {
              size = defaultKind;
            } else if (category == TypeCategory::Complex) {
              size /= 2;
            }
            return Expr<SubscriptInteger>{size};
          },
      },
      selector->u);
}

int ExpressionAnalyzer::GetDefaultKind(common::TypeCategory category) {
  return context_.GetDefaultKind(category);
}

DynamicType ExpressionAnalyzer::GetDefaultKindOfType(
    common::TypeCategory category) {
  return {category, GetDefaultKind(category)};
}

bool ExpressionAnalyzer::CheckIntrinsicKind(
    TypeCategory category, std::int64_t kind) {
  if (foldingContext_.targetCharacteristics().IsTypeEnabled(
          category, kind)) { // C712, C714, C715, C727
    return true;
  } else if (foldingContext_.targetCharacteristics().CanSupportType(
                 category, kind)) {
    Warn(common::UsageWarning::BadTypeForTarget,
        "%s(KIND=%jd) is not an enabled type for this target"_warn_en_US,
        ToUpperCase(EnumToString(category)), kind);
    return true;
  } else {
    Say("%s(KIND=%jd) is not a supported type"_err_en_US,
        ToUpperCase(EnumToString(category)), kind);
    return false;
  }
}

bool ExpressionAnalyzer::CheckIntrinsicSize(
    TypeCategory category, std::int64_t size) {
  std::int64_t kind{size};
  if (category == TypeCategory::Complex) {
    // COMPLEX*16 == COMPLEX(KIND=8)
    if (size % 2 == 0) {
      kind = size / 2;
    } else {
      Say("COMPLEX*%jd is not a supported type"_err_en_US, size);
      return false;
    }
  }
  if (foldingContext_.targetCharacteristics().IsTypeEnabled(
          category, kind)) { // C712, C714, C715, C727
    return true;
  } else if (foldingContext_.targetCharacteristics().CanSupportType(
                 category, kind)) {
    Warn(common::UsageWarning::BadTypeForTarget,
        "%s*%jd is not an enabled type for this target"_warn_en_US,
        ToUpperCase(EnumToString(category)), size);
    return true;
  } else {
    Say("%s*%jd is not a supported type"_err_en_US,
        ToUpperCase(EnumToString(category)), size);
    return false;
  }
}

bool ExpressionAnalyzer::AddImpliedDo(parser::CharBlock name, int kind) {
  return impliedDos_.insert(std::make_pair(name, kind)).second;
}

void ExpressionAnalyzer::RemoveImpliedDo(parser::CharBlock name) {
  auto iter{impliedDos_.find(name)};
  if (iter != impliedDos_.end()) {
    impliedDos_.erase(iter);
  }
}

std::optional<int> ExpressionAnalyzer::IsImpliedDo(
    parser::CharBlock name) const {
  auto iter{impliedDos_.find(name)};
  if (iter != impliedDos_.cend()) {
    return {iter->second};
  } else {
    return std::nullopt;
  }
}

bool ExpressionAnalyzer::EnforceTypeConstraint(parser::CharBlock at,
    const MaybeExpr &result, TypeCategory category, bool defaultKind) {
  if (result) {
    if (auto type{result->GetType()}) {
      if (type->category() != category) { // C885
        Say(at, "Must have %s type, but is %s"_err_en_US,
            ToUpperCase(EnumToString(category)),
            ToUpperCase(type->AsFortran()));
        return false;
      } else if (defaultKind) {
        int kind{context_.GetDefaultKind(category)};
        if (type->kind() != kind) {
          Say(at, "Must have default kind(%d) of %s type, but is %s"_err_en_US,
              kind, ToUpperCase(EnumToString(category)),
              ToUpperCase(type->AsFortran()));
          return false;
        }
      }
    } else {
      Say(at, "Must have %s type, but is typeless"_err_en_US,
          ToUpperCase(EnumToString(category)));
      return false;
    }
  }
  return true;
}

MaybeExpr ExpressionAnalyzer::MakeFunctionRef(parser::CharBlock callSite,
    ProcedureDesignator &&proc, ActualArguments &&arguments) {
  if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&proc.u)}) {
    if (intrinsic->characteristics.value().attrs.test(
            characteristics::Procedure::Attr::NullPointer) &&
        arguments.empty()) {
      return Expr<SomeType>{NullPointer{}};
    }
  }
  if (const Symbol *symbol{proc.GetSymbol()}) {
    if (!ResolveForward(*symbol)) {
      return std::nullopt;
    }
  }
  if (auto chars{CheckCall(callSite, proc, arguments)}) {
    if (chars->functionResult) {
      const auto &result{*chars->functionResult};
      ProcedureRef procRef{std::move(proc), std::move(arguments)};
      if (result.IsProcedurePointer()) {
        return Expr<SomeType>{std::move(procRef)};
      } else {
        // Not a procedure pointer, so type and shape are known.
        return TypedWrapper<FunctionRef, ProcedureRef>(
            DEREF(result.GetTypeAndShape()).type(), std::move(procRef));
      }
    } else {
      Say("Function result characteristics are not known"_err_en_US);
    }
  }
  return std::nullopt;
}

MaybeExpr ExpressionAnalyzer::MakeFunctionRef(
    parser::CharBlock intrinsic, ActualArguments &&arguments) {
  if (std::optional<SpecificCall> specificCall{
          context_.intrinsics().Probe(CallCharacteristics{intrinsic.ToString()},
              arguments, GetFoldingContext())}) {
    return MakeFunctionRef(intrinsic,
        ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
        std::move(specificCall->arguments));
  } else {
    return std::nullopt;
  }
}

MaybeExpr ExpressionAnalyzer::AnalyzeComplex(
    MaybeExpr &&re, MaybeExpr &&im, const char *what) {
  if (re && re->Rank() > 0) {
    Warn(common::LanguageFeature::ComplexConstructor,
        "Real part of %s is not scalar"_port_en_US, what);
  }
  if (im && im->Rank() > 0) {
    Warn(common::LanguageFeature::ComplexConstructor,
        "Imaginary part of %s is not scalar"_port_en_US, what);
  }
  if (re && im) {
    ConformabilityCheck(GetContextualMessages(), *re, *im);
  }
  return AsMaybeExpr(ConstructComplex(GetContextualMessages(), std::move(re),
      std::move(im), GetDefaultKind(TypeCategory::Real)));
}

std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeVariable(
    const parser::Variable &x) {
  source_.ExtendToCover(x.GetSource());
  if (MaybeExpr expr{context_.Analyze(x)}) {
    if (!IsConstantExpr(*expr)) {
      ActualArgument actual{std::move(*expr)};
      SetArgSourceLocation(actual, x.GetSource());
      return actual;
    }
    const Symbol *symbol{GetLastSymbol(*expr)};
    if (!symbol) {
      context_.SayAt(x, "Assignment to constant '%s' is not allowed"_err_en_US,
          x.GetSource());
    } else if (IsProcedure(*symbol)) {
      if (auto *msg{context_.SayAt(x,
              "Assignment to procedure '%s' is not allowed"_err_en_US,
              symbol->name())}) {
        if (auto *subp{symbol->detailsIf<semantics::SubprogramDetails>()}) {
          if (subp->isFunction()) {
            const auto &result{subp->result().name()};
            msg->Attach(result, "Function result is '%s'"_en_US, result);
          }
        }
      }
    } else {
      context_.SayAt(
          x, "Assignment to '%s' is not allowed"_err_en_US, symbol->name());
    }
  }
  fatalErrors_ = true;
  return std::nullopt;
}

void ArgumentAnalyzer::Analyze(const parser::Variable &x) {
  if (auto actual = AnalyzeVariable(x)) {
    actuals_.emplace_back(std::move(actual));
  }
}

void ArgumentAnalyzer::Analyze(
    const parser::ActualArgSpec &arg, bool isSubroutine) {
  // TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
  std::optional<ActualArgument> actual;
  auto restorer{context_.AllowWholeAssumedSizeArray()};
  common::visit(
      common::visitors{
          [&](const common::Indirection<parser::Expr> &x) {
            actual = AnalyzeExpr(x.value());
          },
          [&](const parser::AltReturnSpec &label) {
            if (!isSubroutine) {
              context_.Say(
                  "alternate return specification may not appear on function reference"_err_en_US);
            }
            actual = ActualArgument(label.v);
          },
          [&](const parser::ActualArg::PercentRef &percentRef) {
            actual = AnalyzeExpr(percentRef.v);
            if (actual.has_value()) {
              actual->set_isPercentRef();
            }
          },
          [&](const parser::ActualArg::PercentVal &percentVal) {
            actual = AnalyzeExpr(percentVal.v);
            if (actual.has_value()) {
              actual->set_isPercentVal();
            }
          },
      },
      std::get<parser::ActualArg>(arg.t).u);
  if (actual) {
    if (const auto &argKW{std::get<std::optional<parser::Keyword>>(arg.t)}) {
      actual->set_keyword(argKW->v.source);
    }
    actuals_.emplace_back(std::move(*actual));
  } else {
    fatalErrors_ = true;
  }
}

bool ArgumentAnalyzer::IsIntrinsicRelational(RelationalOperator opr,
    const DynamicType &leftType, const DynamicType &rightType) const {
  CHECK(actuals_.size() == 2);
  return semantics::IsIntrinsicRelational(
      opr, leftType, GetRank(0), rightType, GetRank(1));
}

bool ArgumentAnalyzer::IsIntrinsicNumeric(NumericOperator opr) const {
  std::optional<DynamicType> leftType{GetType(0)};
  if (actuals_.size() == 1) {
    if (IsBOZLiteral(0)) {
      return opr == NumericOperator::Add; // unary '+'
    } else {
      return leftType && semantics::IsIntrinsicNumeric(*leftType);
    }
  } else {
    std::optional<DynamicType> rightType{GetType(1)};
    if (IsBOZLiteral(0) && rightType) { // BOZ opr Integer/Unsigned/Real
      auto cat1{rightType->category()};
      return cat1 == TypeCategory::Integer || cat1 == TypeCategory::Unsigned ||
          cat1 == TypeCategory::Real;
    } else if (IsBOZLiteral(1) && leftType) { // Integer/Unsigned/Real opr BOZ
      auto cat0{leftType->category()};
      return cat0 == TypeCategory::Integer || cat0 == TypeCategory::Unsigned ||
          cat0 == TypeCategory::Real;
    } else {
      return leftType && rightType &&
          semantics::IsIntrinsicNumeric(
              *leftType, GetRank(0), *rightType, GetRank(1));
    }
  }
}

bool ArgumentAnalyzer::IsIntrinsicLogical() const {
  if (std::optional<DynamicType> leftType{GetType(0)}) {
    if (actuals_.size() == 1) {
      return semantics::IsIntrinsicLogical(*leftType);
    } else if (std::optional<DynamicType> rightType{GetType(1)}) {
      return semantics::IsIntrinsicLogical(
          *leftType, GetRank(0), *rightType, GetRank(1));
    }
  }
  return false;
}

bool ArgumentAnalyzer::IsIntrinsicConcat() const {
  if (std::optional<DynamicType> leftType{GetType(0)}) {
    if (std::optional<DynamicType> rightType{GetType(1)}) {
      return semantics::IsIntrinsicConcat(
          *leftType, GetRank(0), *rightType, GetRank(1));
    }
  }
  return false;
}

bool ArgumentAnalyzer::CheckConformance() {
  if (actuals_.size() == 2) {
    const auto *lhs{actuals_.at(0).value().UnwrapExpr()};
    const auto *rhs{actuals_.at(1).value().UnwrapExpr()};
    if (lhs && rhs) {
      auto &foldingContext{context_.GetFoldingContext()};
      auto lhShape{GetShape(foldingContext, *lhs)};
      auto rhShape{GetShape(foldingContext, *rhs)};
      if (lhShape && rhShape) {
        if (!evaluate::CheckConformance(foldingContext.messages(), *lhShape,
                *rhShape, CheckConformanceFlags::EitherScalarExpandable,
                "left operand", "right operand")
                 .value_or(false /*fail when conformance is not known now*/)) {
          fatalErrors_ = true;
          return false;
        }
      }
    }
  }
  return true; // no proven problem
}

bool ArgumentAnalyzer::CheckAssignmentConformance() {
  if (actuals_.size() == 2 && actuals_[0] && actuals_[1]) {
    const auto *lhs{actuals_[0]->UnwrapExpr()};
    const auto *rhs{actuals_[1]->UnwrapExpr()};
    if (lhs && rhs) {
      auto &foldingContext{context_.GetFoldingContext()};
      auto lhShape{GetShape(foldingContext, *lhs)};
      auto rhShape{GetShape(foldingContext, *rhs)};
      if (lhShape && rhShape) {
        if (!evaluate::CheckConformance(foldingContext.messages(), *lhShape,
                *rhShape, CheckConformanceFlags::RightScalarExpandable,
                "left-hand side", "right-hand side")
                 .value_or(true /*ok when conformance is not known now*/)) {
          fatalErrors_ = true;
          return false;
        }
      }
    }
  }
  return true; // no proven problem
}

bool ArgumentAnalyzer::CheckForNullPointer(const char *where) {
  for (const std::optional<ActualArgument> &arg : actuals_) {
    if (arg) {
      if (const Expr<SomeType> *expr{arg->UnwrapExpr()}) {
        if (IsNullPointer(*expr)) {
          context_.Say(
              source_, "A NULL() pointer is not allowed %s"_err_en_US, where);
          fatalErrors_ = true;
          return false;
        }
      }
    }
  }
  return true;
}

bool ArgumentAnalyzer::CheckForAssumedRank(const char *where) {
  for (const std::optional<ActualArgument> &arg : actuals_) {
    if (arg && IsAssumedRank(arg->UnwrapExpr())) {
      context_.Say(source_,
          "An assumed-rank dummy argument is not allowed %s"_err_en_US, where);
      fatalErrors_ = true;
      return false;
    }
  }
  return true;
}

MaybeExpr ArgumentAnalyzer::TryDefinedOp(
    const char *opr, parser::MessageFixedText error, bool isUserOp) {
  if (AnyUntypedOrMissingOperand()) {
    context_.Say(error, ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1));
    return std::nullopt;
  }
  MaybeExpr result;
  bool anyPossibilities{false};
  std::optional<parser::MessageFormattedText> inaccessible;
  std::vector<const Symbol *> hit;
  std::string oprNameString{
      isUserOp ? std::string{opr} : "operator("s + opr + ')'};
  parser::CharBlock oprName{oprNameString};
  parser::Messages hitBuffer;
  {
    parser::Messages buffer;
    auto restorer{context_.GetContextualMessages().SetMessages(buffer)};
    const auto &scope{context_.context().FindScope(source_)};
    if (Symbol *symbol{scope.FindSymbol(oprName)}) {
      anyPossibilities = true;
      parser::Name name{symbol->name(), symbol};
      if (!fatalErrors_) {
        result = context_.AnalyzeDefinedOp(name, GetActuals());
      }
      if (result) {
        inaccessible = CheckAccessibleSymbol(scope, *symbol);
        if (inaccessible) {
          result.reset();
        } else {
          hit.push_back(symbol);
          hitBuffer = std::move(buffer);
        }
      }
    }
    for (std::size_t passIndex{0}; passIndex < actuals_.size(); ++passIndex) {
      buffer.clear();
      const Symbol *generic{nullptr};
      if (const Symbol *binding{
              FindBoundOp(oprName, passIndex, generic, false)}) {
        anyPossibilities = true;
        if (MaybeExpr thisResult{TryBoundOp(*binding, passIndex)}) {
          if (auto thisInaccessible{
                  CheckAccessibleSymbol(scope, DEREF(generic))}) {
            inaccessible = thisInaccessible;
          } else {
            result = std::move(thisResult);
            hit.push_back(binding);
            hitBuffer = std::move(buffer);
          }
        }
      }
    }
  }
  if (result) {
    if (hit.size() > 1) {
      if (auto *msg{context_.Say(
              "%zd matching accessible generic interfaces for %s were found"_err_en_US,
              hit.size(), ToUpperCase(opr))}) {
        for (const Symbol *symbol : hit) {
          AttachDeclaration(*msg, *symbol);
        }
      }
    }
    if (auto *msgs{context_.GetContextualMessages().messages()}) {
      msgs->Annex(std::move(hitBuffer));
    }
  } else if (inaccessible) {
    context_.Say(source_, std::move(*inaccessible));
  } else if (anyPossibilities) {
    SayNoMatch(ToUpperCase(oprNameString), false);
  } else if (actuals_.size() == 2 && !AreConformable()) {
    context_.Say(
        "Operands of %s are not conformable; have rank %d and rank %d"_err_en_US,
        ToUpperCase(opr), actuals_[0]->Rank(), actuals_[1]->Rank());
  } else if (CheckForNullPointer() && CheckForAssumedRank()) {
    context_.Say(error, ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1));
  }
  return result;
}

MaybeExpr ArgumentAnalyzer::TryDefinedOp(
    const std::vector<const char *> &oprs, parser::MessageFixedText error) {
  if (oprs.size() == 1) {
    return TryDefinedOp(oprs[0], error);
  }
  MaybeExpr result;
  std::vector<const char *> hit;
  parser::Messages hitBuffer;
  {
    for (std::size_t i{0}; i < oprs.size(); ++i) {
      parser::Messages buffer;
      auto restorer{context_.GetContextualMessages().SetMessages(buffer)};
      if (MaybeExpr thisResult{TryDefinedOp(oprs[i], error)}) {
        result = std::move(thisResult);
        hit.push_back(oprs[i]);
        hitBuffer = std::move(buffer);
      }
    }
  }
  if (hit.empty()) { // for the error
    result = TryDefinedOp(oprs[0], error);
  } else if (hit.size() > 1) {
    context_.Say(
        "Matching accessible definitions were found with %zd variant spellings of the generic operator ('%s', '%s')"_err_en_US,
        hit.size(), ToUpperCase(hit[0]), ToUpperCase(hit[1]));
  } else { // one hit; preserve errors
    context_.context().messages().Annex(std::move(hitBuffer));
  }
  return result;
}

MaybeExpr ArgumentAnalyzer::TryBoundOp(const Symbol &symbol, int passIndex) {
  ActualArguments localActuals{actuals_};
  const Symbol *proc{GetBindingResolution(GetType(passIndex), symbol)};
  if (!proc) {
    proc = &symbol;
    localActuals.at(passIndex).value().set_isPassedObject();
  }
  CheckConformance();
  return context_.MakeFunctionRef(
      source_, ProcedureDesignator{*proc}, std::move(localActuals));
}

std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() {
  using semantics::Tristate;
  const Expr<SomeType> &lhs{GetExpr(0)};
  const Expr<SomeType> &rhs{GetExpr(1)};
  std::optional<DynamicType> lhsType{lhs.GetType()};
  std::optional<DynamicType> rhsType{rhs.GetType()};
  int lhsRank{lhs.Rank()};
  int rhsRank{rhs.Rank()};
  Tristate isDefined{
      semantics::IsDefinedAssignment(lhsType, lhsRank, rhsType, rhsRank)};
  if (isDefined == Tristate::No) {
    // Make implicit conversion explicit, unless it is an assignment to a whole
    // allocatable (the explicit conversion would prevent the propagation of the
    // right hand side if it is a variable). Lowering will deal with the
    // conversion in this case.
    if (lhsType) {
      if (rhsType) {
        if (!IsAllocatableDesignator(lhs) || context_.inWhereBody()) {
          AddAssignmentConversion(*lhsType, *rhsType);
        }
      } else {
        if (lhsType->category() == TypeCategory::Integer ||
            lhsType->category() == TypeCategory::Unsigned ||
            lhsType->category() == TypeCategory::Real) {
          ConvertBOZ(nullptr, 1, lhsType);
        }
        if (IsBOZLiteral(1)) {
          context_.Say(
              "Right-hand side of this assignment may not be BOZ"_err_en_US);
          fatalErrors_ = true;
        }
      }
    }
    if (!fatalErrors_) {
      CheckAssignmentConformance();
    }
    return std::nullopt; // user-defined assignment not allowed for these args
  }
  auto restorer{context_.GetContextualMessages().SetLocation(source_)};
  if (std::optional<ProcedureRef> procRef{GetDefinedAssignmentProc()}) {
    if (context_.inWhereBody() && !procRef->proc().IsElemental()) { // C1032
      context_.Say(
          "Defined assignment in WHERE must be elemental, but '%s' is not"_err_en_US,
          DEREF(procRef->proc().GetSymbol()).name());
    }
    context_.CheckCall(source_, procRef->proc(), procRef->arguments());
    return std::move(*procRef);
  }
  if (isDefined == Tristate::Yes) {
    if (!lhsType || !rhsType || (lhsRank != rhsRank && rhsRank != 0) ||
        !OkLogicalIntegerAssignment(lhsType->category(), rhsType->category())) {
      SayNoMatch("ASSIGNMENT(=)", true);
    }
  } else if (!fatalErrors_) {
    CheckAssignmentConformance();
  }
  return std::nullopt;
}

bool ArgumentAnalyzer::OkLogicalIntegerAssignment(
    TypeCategory lhs, TypeCategory rhs) {
  if (!context_.context().languageFeatures().IsEnabled(
          common::LanguageFeature::LogicalIntegerAssignment)) {
    return false;
  }
  std::optional<parser::MessageFixedText> msg;
  if (lhs == TypeCategory::Integer && rhs == TypeCategory::Logical) {
    // allow assignment to LOGICAL from INTEGER as a legacy extension
    msg = "assignment of LOGICAL to INTEGER"_port_en_US;
  } else if (lhs == TypeCategory::Logical && rhs == TypeCategory::Integer) {
    // ... and assignment to LOGICAL from INTEGER
    msg = "assignment of INTEGER to LOGICAL"_port_en_US;
  } else {
    return false;
  }
  context_.Warn(
      common::LanguageFeature::LogicalIntegerAssignment, std::move(*msg));
  return true;
}

std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
  const Symbol *proc{nullptr};
  std::optional<int> passedObjectIndex;
  std::string oprNameString{"assignment(=)"};
  parser::CharBlock oprName{oprNameString};
  const auto &scope{context_.context().FindScope(source_)};
  // If multiple resolutions were possible, they will have been already
  // diagnosed.
  {
    auto restorer{context_.GetContextualMessages().DiscardMessages()};
    if (const Symbol *symbol{scope.FindSymbol(oprName)}) {
      ExpressionAnalyzer::AdjustActuals noAdjustment;
      proc =
          context_.ResolveGeneric(*symbol, actuals_, noAdjustment, true).first;
    }
    for (std::size_t i{0}; !proc && i < actuals_.size(); ++i) {
      const Symbol *generic{nullptr};
      if (const Symbol *binding{FindBoundOp(oprName, i, generic, true)}) {
        if (CheckAccessibleSymbol(scope, DEREF(generic))) {
          // ignore inaccessible type-bound ASSIGNMENT(=) generic
        } else if (const Symbol *
            resolution{GetBindingResolution(GetType(i), *binding)}) {
          proc = resolution;
        } else {
          proc = binding;
          passedObjectIndex = i;
        }
      }
    }
  }
  if (!proc) {
    return std::nullopt;
  }
  ActualArguments actualsCopy{actuals_};
  // Ensure that the RHS argument is not passed as a variable unless
  // the dummy argument has the VALUE attribute.
  if (evaluate::IsVariable(actualsCopy.at(1).value().UnwrapExpr())) {
    auto chars{evaluate::characteristics::Procedure::Characterize(
        *proc, context_.GetFoldingContext())};
    const auto *rhsDummy{chars && chars->dummyArguments.size() == 2
            ? std::get_if<evaluate::characteristics::DummyDataObject>(
                  &chars->dummyArguments.at(1).u)
            : nullptr};
    if (!rhsDummy ||
        !rhsDummy->attrs.test(
            evaluate::characteristics::DummyDataObject::Attr::Value)) {
      actualsCopy.at(1).value().Parenthesize();
    }
  }
  if (passedObjectIndex) {
    actualsCopy[*passedObjectIndex]->set_isPassedObject();
  }
  return ProcedureRef{ProcedureDesignator{*proc}, std::move(actualsCopy)};
}

void ArgumentAnalyzer::Dump(llvm::raw_ostream &os) {
  os << "source_: " << source_.ToString() << " fatalErrors_ = " << fatalErrors_
     << '\n';
  for (const auto &actual : actuals_) {
    if (!actual.has_value()) {
      os << "- error\n";
    } else if (const Symbol *symbol{actual->GetAssumedTypeDummy()}) {
      os << "- assumed type: " << symbol->name().ToString() << '\n';
    } else if (const Expr<SomeType> *expr{actual->UnwrapExpr()}) {
      expr->AsFortran(os << "- expr: ") << '\n';
    } else {
      DIE("bad ActualArgument");
    }
  }
}

std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeExpr(
    const parser::Expr &expr) {
  source_.ExtendToCover(expr.source);
  if (const Symbol *assumedTypeDummy{AssumedTypeDummy(expr)}) {
    ResetExpr(expr);
    if (isProcedureCall_) {
      ActualArgument arg{ActualArgument::AssumedType{*assumedTypeDummy}};
      SetArgSourceLocation(arg, expr.source);
      return std::move(arg);
    }
    context_.SayAt(expr.source,
        "TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
  } else if (MaybeExpr argExpr{AnalyzeExprOrWholeAssumedSizeArray(expr)}) {
    if (isProcedureCall_ || !IsProcedureDesignator(*argExpr)) {
      ActualArgument arg{std::move(*argExpr)};
      SetArgSourceLocation(arg, expr.source);
      return std::move(arg);
    }
    context_.SayAt(expr.source,
        IsFunctionDesignator(*argExpr)
            ? "Function call must have argument list"_err_en_US
            : "Subroutine name is not allowed here"_err_en_US);
  }
  return std::nullopt;
}

MaybeExpr ArgumentAnalyzer::AnalyzeExprOrWholeAssumedSizeArray(
    const parser::Expr &expr) {
  // If an expression's parse tree is a whole assumed-size array:
  //   Expr -> Designator -> DataRef -> Name
  // treat it as a special case for argument passing and bypass
  // the C1002/C1014 constraint checking in expression semantics.
  if (const auto *name{parser::Unwrap<parser::Name>(expr)}) {
    if (name->symbol && semantics::IsAssumedSizeArray(*name->symbol)) {
      auto restorer{context_.AllowWholeAssumedSizeArray()};
      return context_.Analyze(expr);
    }
  }
  auto restorer{context_.AllowNullPointer()};
  return context_.Analyze(expr);
}

bool ArgumentAnalyzer::AreConformable() const {
  CHECK(actuals_.size() == 2);
  return actuals_[0] && actuals_[1] &&
      evaluate::AreConformable(*actuals_[0], *actuals_[1]);
}

// Look for a type-bound operator in the type of arg number passIndex.
const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName,
    int passIndex, const Symbol *&generic, bool isSubroutine) {
  const auto *type{GetDerivedTypeSpec(GetType(passIndex))};
  const semantics::Scope *scope{type ? type->scope() : nullptr};
  if (scope) {
    // Use the original type definition's scope, since PDT
    // instantiations don't have redundant copies of bindings or
    // generics.
    scope = DEREF(scope->derivedTypeSpec()).typeSymbol().scope();
  }
  generic = scope ? scope->FindComponent(oprName) : nullptr;
  if (generic) {
    ExpressionAnalyzer::AdjustActuals adjustment{
        [&](const Symbol &proc, ActualArguments &) {
          return passIndex == GetPassIndex(proc).value_or(-1);
        }};
    auto pair{
        context_.ResolveGeneric(*generic, actuals_, adjustment, isSubroutine)};
    if (const Symbol *binding{pair.first}) {
      CHECK(binding->has<semantics::ProcBindingDetails>());
      // Use the most recent override of the binding, if any
      return scope->FindComponent(binding->name());
    } else {
      context_.EmitGenericResolutionError(*generic, pair.second, isSubroutine);
    }
  }
  return nullptr;
}

// If there is an implicit conversion between intrinsic types, make it explicit
void ArgumentAnalyzer::AddAssignmentConversion(
    const DynamicType &lhsType, const DynamicType &rhsType) {
  if (lhsType.category() == rhsType.category() &&
      (lhsType.category() == TypeCategory::Derived ||
          lhsType.kind() == rhsType.kind())) {
    // no conversion necessary
  } else if (auto rhsExpr{evaluate::Fold(context_.GetFoldingContext(),
                 evaluate::ConvertToType(lhsType, MoveExpr(1)))}) {
    std::optional<parser::CharBlock> source;
    if (actuals_[1]) {
      source = actuals_[1]->sourceLocation();
    }
    actuals_[1] = ActualArgument{*rhsExpr};
    SetArgSourceLocation(actuals_[1], source);
  } else {
    actuals_[1] = std::nullopt;
  }
}

std::optional<DynamicType> ArgumentAnalyzer::GetType(std::size_t i) const {
  return i < actuals_.size() ? actuals_[i].value().GetType() : std::nullopt;
}
int ArgumentAnalyzer::GetRank(std::size_t i) const {
  return i < actuals_.size() ? actuals_[i].value().Rank() : 0;
}

// If the argument at index i is a BOZ literal, convert its type to match the
// otherType.  If it's REAL, convert to REAL; if it's UNSIGNED, convert to
// UNSIGNED; otherwise, convert to INTEGER.
// Note that IBM supports comparing BOZ literals to CHARACTER operands.  That
// is not currently supported.
void ArgumentAnalyzer::ConvertBOZ(std::optional<DynamicType> *thisType,
    std::size_t i, std::optional<DynamicType> otherType) {
  if (IsBOZLiteral(i)) {
    Expr<SomeType> &&argExpr{MoveExpr(i)};
    auto *boz{std::get_if<BOZLiteralConstant>(&argExpr.u)};
    if (otherType && otherType->category() == TypeCategory::Real) {
      int kind{context_.context().GetDefaultKind(TypeCategory::Real)};
      MaybeExpr realExpr{
          ConvertToKind<TypeCategory::Real>(kind, std::move(*boz))};
      actuals_[i] = std::move(realExpr.value());
      if (thisType) {
        thisType->emplace(TypeCategory::Real, kind);
      }
    } else if (otherType && otherType->category() == TypeCategory::Unsigned) {
      int kind{context_.context().GetDefaultKind(TypeCategory::Unsigned)};
      MaybeExpr unsignedExpr{
          ConvertToKind<TypeCategory::Unsigned>(kind, std::move(*boz))};
      actuals_[i] = std::move(unsignedExpr.value());
      if (thisType) {
        thisType->emplace(TypeCategory::Unsigned, kind);
      }
    } else {
      int kind{context_.context().GetDefaultKind(TypeCategory::Integer)};
      MaybeExpr intExpr{
          ConvertToKind<TypeCategory::Integer>(kind, std::move(*boz))};
      actuals_[i] = std::move(*intExpr);
      if (thisType) {
        thisType->emplace(TypeCategory::Integer, kind);
      }
    }
  }
}

// Report error resolving opr when there is a user-defined one available
void ArgumentAnalyzer::SayNoMatch(const std::string &opr, bool isAssignment) {
  std::string type0{TypeAsFortran(0)};
  auto rank0{actuals_[0]->Rank()};
  if (actuals_.size() == 1) {
    if (rank0 > 0) {
      context_.Say("No intrinsic or user-defined %s matches "
                   "rank %d array of %s"_err_en_US,
          opr, rank0, type0);
    } else {
      context_.Say("No intrinsic or user-defined %s matches "
                   "operand type %s"_err_en_US,
          opr, type0);
    }
  } else {
    std::string type1{TypeAsFortran(1)};
    auto rank1{actuals_[1]->Rank()};
    if (rank0 > 0 && rank1 > 0 && rank0 != rank1) {
      context_.Say("No intrinsic or user-defined %s matches "
                   "rank %d array of %s and rank %d array of %s"_err_en_US,
          opr, rank0, type0, rank1, type1);
    } else if (isAssignment && rank0 != rank1) {
      if (rank0 == 0) {
        context_.Say("No intrinsic or user-defined %s matches "
                     "scalar %s and rank %d array of %s"_err_en_US,
            opr, type0, rank1, type1);
      } else {
        context_.Say("No intrinsic or user-defined %s matches "
                     "rank %d array of %s and scalar %s"_err_en_US,
            opr, rank0, type0, type1);
      }
    } else {
      context_.Say("No intrinsic or user-defined %s matches "
                   "operand types %s and %s"_err_en_US,
          opr, type0, type1);
    }
  }
}

std::string ArgumentAnalyzer::TypeAsFortran(std::size_t i) {
  if (i >= actuals_.size() || !actuals_[i]) {
    return "missing argument";
  } else if (std::optional<DynamicType> type{GetType(i)}) {
    return type->IsAssumedType()         ? "TYPE(*)"s
        : type->IsUnlimitedPolymorphic() ? "CLASS(*)"s
        : type->IsPolymorphic()          ? type->AsFortran()
        : type->category() == TypeCategory::Derived
        ? "TYPE("s + type->AsFortran() + ')'
        : type->category() == TypeCategory::Character
        ? "CHARACTER(KIND="s + std::to_string(type->kind()) + ')'
        : ToUpperCase(type->AsFortran());
  } else {
    return "untyped";
  }
}

bool ArgumentAnalyzer::AnyUntypedOrMissingOperand() {
  for (const auto &actual : actuals_) {
    if (!actual ||
        (!actual->GetType() && !IsBareNullPointer(actual->UnwrapExpr()))) {
      return true;
    }
  }
  return false;
}
} // namespace Fortran::evaluate

namespace Fortran::semantics {
evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector(
    SemanticsContext &context, common::TypeCategory category,
    const std::optional<parser::KindSelector> &selector) {
  evaluate::ExpressionAnalyzer analyzer{context};
  CHECK(context.location().has_value());
  auto restorer{
      analyzer.GetContextualMessages().SetLocation(*context.location())};
  return analyzer.AnalyzeKindSelector(category, selector);
}

ExprChecker::ExprChecker(SemanticsContext &context) : context_{context} {}

bool ExprChecker::Pre(const parser::DataStmtObject &obj) {
  exprAnalyzer_.set_inDataStmtObject(true);
  return true;
}

void ExprChecker::Post(const parser::DataStmtObject &obj) {
  exprAnalyzer_.set_inDataStmtObject(false);
}

bool ExprChecker::Pre(const parser::DataImpliedDo &ido) {
  parser::Walk(std::get<parser::DataImpliedDo::Bounds>(ido.t), *this);
  const auto &bounds{std::get<parser::DataImpliedDo::Bounds>(ido.t)};
  auto name{bounds.name.thing.thing};
  int kind{evaluate::ResultType<evaluate::ImpliedDoIndex>::kind};
  if (const auto dynamicType{evaluate::DynamicType::From(*name.symbol)}) {
    if (dynamicType->category() == TypeCategory::Integer) {
      kind = dynamicType->kind();
    }
  }
  exprAnalyzer_.AddImpliedDo(name.source, kind);
  parser::Walk(std::get<std::list<parser::DataIDoObject>>(ido.t), *this);
  exprAnalyzer_.RemoveImpliedDo(name.source);
  return false;
}

bool ExprChecker::Walk(const parser::Program &program) {
  parser::Walk(program, *this);
  return !context_.AnyFatalError();
}
} // namespace Fortran::semantics
