brintos

brintos / llvm-project-archived public Read only

0
0
Text · 396.7 KiB · 2a487a6 Raw
10780 lines · cpp
1//===-- lib/Semantics/resolve-names.cpp -----------------------------------===//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7 8#include "resolve-names.h"9#include "assignment.h"10#include "data-to-inits.h"11#include "definable.h"12#include "mod-file.h"13#include "pointer-assignment.h"14#include "resolve-directives.h"15#include "resolve-names-utils.h"16#include "rewrite-parse-tree.h"17#include "flang/Common/indirection.h"18#include "flang/Common/restorer.h"19#include "flang/Common/visit.h"20#include "flang/Evaluate/characteristics.h"21#include "flang/Evaluate/check-expression.h"22#include "flang/Evaluate/common.h"23#include "flang/Evaluate/fold-designator.h"24#include "flang/Evaluate/fold.h"25#include "flang/Evaluate/intrinsics.h"26#include "flang/Evaluate/tools.h"27#include "flang/Evaluate/type.h"28#include "flang/Parser/openmp-utils.h"29#include "flang/Parser/parse-tree-visitor.h"30#include "flang/Parser/parse-tree.h"31#include "flang/Parser/tools.h"32#include "flang/Semantics/attr.h"33#include "flang/Semantics/expression.h"34#include "flang/Semantics/openmp-modifiers.h"35#include "flang/Semantics/openmp-utils.h"36#include "flang/Semantics/program-tree.h"37#include "flang/Semantics/scope.h"38#include "flang/Semantics/semantics.h"39#include "flang/Semantics/symbol.h"40#include "flang/Semantics/tools.h"41#include "flang/Semantics/type.h"42#include "flang/Support/Fortran.h"43#include "flang/Support/default-kinds.h"44#include "llvm/ADT/StringSwitch.h"45#include "llvm/Support/raw_ostream.h"46#include <list>47#include <map>48#include <set>49#include <stack>50 51namespace Fortran::semantics {52 53using namespace parser::literals;54 55template <typename T> using Indirection = common::Indirection<T>;56using Message = parser::Message;57using Messages = parser::Messages;58using MessageFixedText = parser::MessageFixedText;59using MessageFormattedText = parser::MessageFormattedText;60 61class ResolveNamesVisitor;62class ScopeHandler;63 64// ImplicitRules maps initial character of identifier to the DeclTypeSpec65// representing the implicit type; std::nullopt if none.66// It also records the presence of IMPLICIT NONE statements.67// When inheritFromParent is set, defaults come from the parent rules.68class ImplicitRules {69public:70  ImplicitRules(SemanticsContext &context, const ImplicitRules *parent)71      : parent_{parent}, context_{context},72        inheritFromParent_{parent != nullptr} {}73  bool isImplicitNoneType() const;74  bool isImplicitNoneExternal() const;75  void set_isImplicitNoneType(bool x) { isImplicitNoneType_ = x; }76  void set_isImplicitNoneExternal(bool x) { isImplicitNoneExternal_ = x; }77  void set_inheritFromParent(bool x) { inheritFromParent_ = x; }78  // Get the implicit type for this name. May be null.79  const DeclTypeSpec *GetType(80      SourceName, bool respectImplicitNone = true) const;81  // Record the implicit type for the range of characters [fromLetter,82  // toLetter].83  void SetTypeMapping(const DeclTypeSpec &type, parser::Location fromLetter,84      parser::Location toLetter);85 86private:87  static char Incr(char ch);88 89  const ImplicitRules *parent_;90  SemanticsContext &context_;91  bool inheritFromParent_{false}; // look in parent if not specified here92  bool isImplicitNoneType_{93      context_.IsEnabled(common::LanguageFeature::ImplicitNoneTypeAlways)};94  bool isImplicitNoneExternal_{95      context_.IsEnabled(common::LanguageFeature::ImplicitNoneExternal)};96  // map_ contains the mapping between letters and types that were defined97  // by the IMPLICIT statements of the related scope. It does not contain98  // the default Fortran mappings nor the mapping defined in parents.99  std::map<char, common::Reference<const DeclTypeSpec>> map_;100 101  friend llvm::raw_ostream &operator<<(102      llvm::raw_ostream &, const ImplicitRules &);103  friend void ShowImplicitRule(104      llvm::raw_ostream &, const ImplicitRules &, char);105};106 107// scope -> implicit rules for that scope108using ImplicitRulesMap = std::map<const Scope *, ImplicitRules>;109 110// Track statement source locations and save messages.111class MessageHandler {112public:113  MessageHandler() { DIE("MessageHandler: default-constructed"); }114  explicit MessageHandler(SemanticsContext &c) : context_{&c} {}115  Messages &messages() { return context_->messages(); };116  const std::optional<SourceName> &currStmtSource() {117    return context_->location();118  }119  void set_currStmtSource(const std::optional<SourceName> &source) {120    context_->set_location(source);121  }122 123  // Emit a message associated with the current statement source.124  Message &Say(MessageFixedText &&);125  Message &Say(MessageFormattedText &&);126  // Emit a message about a SourceName127  Message &Say(const SourceName &, MessageFixedText &&);128  // Emit a formatted message associated with a source location.129  template <typename... A>130  Message &Say(const SourceName &source, MessageFixedText &&msg, A &&...args) {131    return context_->Say(source, std::move(msg), std::forward<A>(args)...);132  }133 134private:135  SemanticsContext *context_;136};137 138// Inheritance graph for the parse tree visitation classes that follow:139//   BaseVisitor140//   + AttrsVisitor141//   | + DeclTypeSpecVisitor142//   |   + ImplicitRulesVisitor143//   |     + ScopeHandler ------------------+144//   |       + ModuleVisitor -------------+ |145//   |       + GenericHandler -------+    | |146//   |       | + InterfaceVisitor    |    | |147//   |       +-+ SubprogramVisitor ==|==+ | |148//   + ArraySpecVisitor              |  | | |149//     + DeclarationVisitor <--------+  | | |150//       + ConstructVisitor             | | |151//         + ResolveNamesVisitor <------+-+-+152 153class BaseVisitor {154public:155  BaseVisitor() { DIE("BaseVisitor: default-constructed"); }156  BaseVisitor(157      SemanticsContext &c, ResolveNamesVisitor &v, ImplicitRulesMap &rules)158      : implicitRulesMap_{&rules}, this_{&v}, context_{&c}, messageHandler_{c} {159  }160  template <typename T> void Walk(const T &);161 162  MessageHandler &messageHandler() { return messageHandler_; }163  const std::optional<SourceName> &currStmtSource() {164    return context_->location();165  }166  SemanticsContext &context() const { return *context_; }167  evaluate::FoldingContext &GetFoldingContext() const {168    return context_->foldingContext();169  }170  bool IsIntrinsic(171      const SourceName &name, std::optional<Symbol::Flag> flag) const {172    if (!flag) {173      return context_->intrinsics().IsIntrinsic(name.ToString());174    } else if (flag == Symbol::Flag::Function) {175      return context_->intrinsics().IsIntrinsicFunction(name.ToString());176    } else if (flag == Symbol::Flag::Subroutine) {177      return context_->intrinsics().IsIntrinsicSubroutine(name.ToString());178    } else {179      DIE("expected Subroutine or Function flag");180    }181  }182 183  bool InModuleFile() const {184    return GetFoldingContext().moduleFileName().has_value();185  }186 187  // Make a placeholder symbol for a Name that otherwise wouldn't have one.188  // It is not in any scope and always has MiscDetails.189  void MakePlaceholder(const parser::Name &, MiscDetails::Kind);190 191  template <typename T> common::IfNoLvalue<T, T> FoldExpr(T &&expr) {192    return evaluate::Fold(GetFoldingContext(), std::move(expr));193  }194 195  template <typename T> MaybeExpr EvaluateExpr(const T &expr) {196    return FoldExpr(AnalyzeExpr(*context_, expr));197  }198 199  template <typename T>200  MaybeExpr EvaluateNonPointerInitializer(201      const Symbol &symbol, const T &expr, parser::CharBlock source) {202    if (!context().HasError(symbol)) {203      if (auto maybeExpr{AnalyzeExpr(*context_, expr)}) {204        auto restorer{GetFoldingContext().messages().SetLocation(source)};205        return evaluate::NonPointerInitializationExpr(206            symbol, std::move(*maybeExpr), GetFoldingContext());207      }208    }209    return std::nullopt;210  }211 212  template <typename T> MaybeIntExpr EvaluateIntExpr(const T &expr) {213    return semantics::EvaluateIntExpr(*context_, expr);214  }215 216  template <typename T>217  MaybeSubscriptIntExpr EvaluateSubscriptIntExpr(const T &expr) {218    if (MaybeIntExpr maybeIntExpr{EvaluateIntExpr(expr)}) {219      return FoldExpr(evaluate::ConvertToType<evaluate::SubscriptInteger>(220          std::move(*maybeIntExpr)));221    } else {222      return std::nullopt;223    }224  }225 226  template <typename... A> Message &Say(A &&...args) {227    return messageHandler_.Say(std::forward<A>(args)...);228  }229  template <typename... A>230  Message &Say(231      const parser::Name &name, MessageFixedText &&text, const A &...args) {232    return messageHandler_.Say(name.source, std::move(text), args...);233  }234 235protected:236  ImplicitRulesMap *implicitRulesMap_{nullptr};237 238private:239  ResolveNamesVisitor *this_;240  SemanticsContext *context_;241  MessageHandler messageHandler_;242};243 244// Provide Post methods to collect attributes into a member variable.245class AttrsVisitor : public virtual BaseVisitor {246public:247  bool BeginAttrs(); // always returns true248  Attrs GetAttrs();249  std::optional<common::CUDADataAttr> cudaDataAttr() { return cudaDataAttr_; }250  Attrs EndAttrs();251  bool SetPassNameOn(Symbol &);252  void SetBindNameOn(Symbol &);253  void Post(const parser::LanguageBindingSpec &);254  bool Pre(const parser::IntentSpec &);255  bool Pre(const parser::Pass &);256 257  bool CheckAndSet(Attr);258 259// Simple case: encountering CLASSNAME causes ATTRNAME to be set.260#define HANDLE_ATTR_CLASS(CLASSNAME, ATTRNAME) \261  bool Pre(const parser::CLASSNAME &) { \262    CheckAndSet(Attr::ATTRNAME); \263    return false; \264  }265  HANDLE_ATTR_CLASS(PrefixSpec::Elemental, ELEMENTAL)266  HANDLE_ATTR_CLASS(PrefixSpec::Impure, IMPURE)267  HANDLE_ATTR_CLASS(PrefixSpec::Module, MODULE)268  HANDLE_ATTR_CLASS(PrefixSpec::Non_Recursive, NON_RECURSIVE)269  HANDLE_ATTR_CLASS(PrefixSpec::Pure, PURE)270  HANDLE_ATTR_CLASS(PrefixSpec::Recursive, RECURSIVE)271  HANDLE_ATTR_CLASS(TypeAttrSpec::BindC, BIND_C)272  HANDLE_ATTR_CLASS(BindAttr::Deferred, DEFERRED)273  HANDLE_ATTR_CLASS(BindAttr::Non_Overridable, NON_OVERRIDABLE)274  HANDLE_ATTR_CLASS(Abstract, ABSTRACT)275  HANDLE_ATTR_CLASS(Allocatable, ALLOCATABLE)276  HANDLE_ATTR_CLASS(Asynchronous, ASYNCHRONOUS)277  HANDLE_ATTR_CLASS(Contiguous, CONTIGUOUS)278  HANDLE_ATTR_CLASS(External, EXTERNAL)279  HANDLE_ATTR_CLASS(Intrinsic, INTRINSIC)280  HANDLE_ATTR_CLASS(NoPass, NOPASS)281  HANDLE_ATTR_CLASS(Optional, OPTIONAL)282  HANDLE_ATTR_CLASS(Parameter, PARAMETER)283  HANDLE_ATTR_CLASS(Pointer, POINTER)284  HANDLE_ATTR_CLASS(Protected, PROTECTED)285  HANDLE_ATTR_CLASS(Save, SAVE)286  HANDLE_ATTR_CLASS(Target, TARGET)287  HANDLE_ATTR_CLASS(Value, VALUE)288  HANDLE_ATTR_CLASS(Volatile, VOLATILE)289#undef HANDLE_ATTR_CLASS290  bool Pre(const common::CUDADataAttr);291 292protected:293  std::optional<Attrs> attrs_;294  std::optional<common::CUDADataAttr> cudaDataAttr_;295 296  Attr AccessSpecToAttr(const parser::AccessSpec &x) {297    switch (x.v) {298    case parser::AccessSpec::Kind::Public:299      return Attr::PUBLIC;300    case parser::AccessSpec::Kind::Private:301      return Attr::PRIVATE;302    }303    llvm_unreachable("Switch covers all cases"); // suppress g++ warning304  }305  Attr IntentSpecToAttr(const parser::IntentSpec &x) {306    switch (x.v) {307    case parser::IntentSpec::Intent::In:308      return Attr::INTENT_IN;309    case parser::IntentSpec::Intent::Out:310      return Attr::INTENT_OUT;311    case parser::IntentSpec::Intent::InOut:312      return Attr::INTENT_INOUT;313    }314    llvm_unreachable("Switch covers all cases"); // suppress g++ warning315  }316 317private:318  bool IsDuplicateAttr(Attr);319  bool HaveAttrConflict(Attr, Attr, Attr);320  bool IsConflictingAttr(Attr);321 322  MaybeExpr bindName_; // from BIND(C, NAME="...")323  bool isCDefined_{false}; // BIND(C, NAME="...", CDEFINED) extension324  std::optional<SourceName> passName_; // from PASS(...)325};326 327// Find and create types from declaration-type-spec nodes.328class DeclTypeSpecVisitor : public AttrsVisitor {329public:330  using AttrsVisitor::Post;331  using AttrsVisitor::Pre;332  void Post(const parser::IntrinsicTypeSpec::DoublePrecision &);333  void Post(const parser::IntrinsicTypeSpec::DoubleComplex &);334  void Post(const parser::DeclarationTypeSpec::ClassStar &);335  void Post(const parser::DeclarationTypeSpec::TypeStar &);336  bool Pre(const parser::TypeGuardStmt &);337  void Post(const parser::TypeGuardStmt &);338  void Post(const parser::TypeSpec &);339 340  // Walk the parse tree of a type spec and return the DeclTypeSpec for it.341  template <typename T>342  const DeclTypeSpec *ProcessTypeSpec(const T &x, bool allowForward = false) {343    auto restorer{common::ScopedSet(state_, State{})};344    set_allowForwardReferenceToDerivedType(allowForward);345    BeginDeclTypeSpec();346    Walk(x);347    const auto *type{GetDeclTypeSpec()};348    EndDeclTypeSpec();349    return type;350  }351 352protected:353  struct State {354    bool expectDeclTypeSpec{false}; // should see decl-type-spec only when true355    const DeclTypeSpec *declTypeSpec{nullptr};356    struct {357      DerivedTypeSpec *type{nullptr};358      DeclTypeSpec::Category category{DeclTypeSpec::TypeDerived};359    } derived;360    bool allowForwardReferenceToDerivedType{false};361    const parser::Expr *originalKindParameter{nullptr};362  };363 364  bool allowForwardReferenceToDerivedType() const {365    return state_.allowForwardReferenceToDerivedType;366  }367  void set_allowForwardReferenceToDerivedType(bool yes) {368    state_.allowForwardReferenceToDerivedType = yes;369  }370  void set_inPDTDefinition(bool yes) { inPDTDefinition_ = yes; }371 372  const DeclTypeSpec *GetDeclTypeSpec() const;373  const parser::Expr *GetOriginalKindParameter() const;374  void BeginDeclTypeSpec();375  void EndDeclTypeSpec();376  void SetDeclTypeSpec(const DeclTypeSpec &);377  void SetDeclTypeSpecCategory(DeclTypeSpec::Category);378  DeclTypeSpec::Category GetDeclTypeSpecCategory() const {379    return state_.derived.category;380  }381  KindExpr GetKindParamExpr(382      TypeCategory, const std::optional<parser::KindSelector> &);383  void CheckForAbstractType(const Symbol &typeSymbol);384 385private:386  State state_;387  bool inPDTDefinition_{false};388 389  void MakeNumericType(TypeCategory, int kind);390};391 392// Visit ImplicitStmt and related parse tree nodes and updates implicit rules.393class ImplicitRulesVisitor : public DeclTypeSpecVisitor {394public:395  using DeclTypeSpecVisitor::Post;396  using DeclTypeSpecVisitor::Pre;397  using ImplicitNoneNameSpec = parser::ImplicitStmt::ImplicitNoneNameSpec;398 399  void Post(const parser::ParameterStmt &);400  bool Pre(const parser::ImplicitStmt &);401  bool Pre(const parser::LetterSpec &);402  bool Pre(const parser::ImplicitSpec &);403  void Post(const parser::ImplicitSpec &);404 405  const DeclTypeSpec *GetType(406      SourceName name, bool respectImplicitNoneType = true) {407    return implicitRules_->GetType(name, respectImplicitNoneType);408  }409  bool isImplicitNoneType() const {410    return implicitRules_->isImplicitNoneType();411  }412  bool isImplicitNoneType(const Scope &scope) const {413    return implicitRulesMap_->at(&scope).isImplicitNoneType();414  }415  bool isImplicitNoneExternal() const {416    return implicitRules_->isImplicitNoneExternal();417  }418  void set_inheritFromParent(bool x) {419    implicitRules_->set_inheritFromParent(x);420  }421 422protected:423  void BeginScope(const Scope &);424  void SetScope(const Scope &);425 426private:427  // implicit rules in effect for current scope428  ImplicitRules *implicitRules_{nullptr};429  std::optional<SourceName> prevImplicit_;430  std::optional<SourceName> prevImplicitNone_;431  std::optional<SourceName> prevImplicitNoneType_;432  std::optional<SourceName> prevParameterStmt_;433 434  bool HandleImplicitNone(const std::list<ImplicitNoneNameSpec> &nameSpecs);435};436 437// Track array specifications. They can occur in AttrSpec, EntityDecl,438// ObjectDecl, DimensionStmt, CommonBlockObject, BasedPointer, and439// ComponentDecl.440// 1. INTEGER, DIMENSION(10) :: x441// 2. INTEGER :: x(10)442// 3. ALLOCATABLE :: x(:)443// 4. DIMENSION :: x(10)444// 5. COMMON x(10)445// 6. POINTER(p,x(10))446class ArraySpecVisitor : public virtual BaseVisitor {447public:448  void Post(const parser::ArraySpec &);449  void Post(const parser::ComponentArraySpec &);450  void Post(const parser::CoarraySpec &);451  void Post(const parser::AttrSpec &) { PostAttrSpec(); }452  void Post(const parser::ComponentAttrSpec &) { PostAttrSpec(); }453 454protected:455  const ArraySpec &arraySpec();456  void set_arraySpec(const ArraySpec arraySpec) { arraySpec_ = arraySpec; }457  const ArraySpec &coarraySpec();458  void BeginArraySpec();459  void EndArraySpec();460  void ClearArraySpec() { arraySpec_.clear(); }461  void ClearCoarraySpec() { coarraySpec_.clear(); }462 463private:464  // arraySpec_/coarraySpec_ are populated from any ArraySpec/CoarraySpec465  ArraySpec arraySpec_;466  ArraySpec coarraySpec_;467  // When an ArraySpec is under an AttrSpec or ComponentAttrSpec, it is moved468  // into attrArraySpec_469  ArraySpec attrArraySpec_;470  ArraySpec attrCoarraySpec_;471 472  void PostAttrSpec();473};474 475// Manages a stack of function result information.  We defer the processing476// of a type specification that appears in the prefix of a FUNCTION statement477// until the function result variable appears in the specification part478// or the end of the specification part.  This allows for forward references479// in the type specification to resolve to local names.480class FuncResultStack {481public:482  explicit FuncResultStack(ScopeHandler &scopeHandler)483      : scopeHandler_{scopeHandler} {}484  ~FuncResultStack();485 486  struct FuncInfo {487    FuncInfo(const Scope &s, SourceName at) : scope{s}, source{at} {}488    const Scope &scope;489    SourceName source;490    // Parse tree of the type specification in the FUNCTION prefix491    const parser::DeclarationTypeSpec *parsedType{nullptr};492    // Name of the function RESULT in the FUNCTION suffix, if any493    const parser::Name *resultName{nullptr};494    // Result symbol495    Symbol *resultSymbol{nullptr};496    bool inFunctionStmt{false}; // true between Pre/Post of FunctionStmt497    // Functions with previous implicitly-typed references get those types498    // checked against their later definitions.499    const DeclTypeSpec *previousImplicitType{nullptr};500    SourceName previousName;501  };502 503  // Completes the definition of the top function's result.504  void CompleteFunctionResultType();505  // Completes the definition of a symbol if it is the top function's result.506  void CompleteTypeIfFunctionResult(Symbol &);507 508  FuncInfo *Top() { return stack_.empty() ? nullptr : &stack_.back(); }509  FuncInfo &Push(const Scope &scope, SourceName at) {510    return stack_.emplace_back(scope, at);511  }512  void Pop();513 514private:515  ScopeHandler &scopeHandler_;516  std::vector<FuncInfo> stack_;517};518 519// Manage a stack of Scopes520class ScopeHandler : public ImplicitRulesVisitor {521public:522  using ImplicitRulesVisitor::Post;523  using ImplicitRulesVisitor::Pre;524 525  Scope &currScope() { return DEREF(currScope_); }526  // The enclosing host procedure if current scope is in an internal procedure527  Scope *GetHostProcedure();528  // The innermost enclosing program unit scope, ignoring BLOCK and other529  // construct scopes.530  Scope &InclusiveScope();531  // The enclosing scope, skipping derived types.532  Scope &NonDerivedTypeScope();533 534  // Create a new scope and push it on the scope stack.535  void PushScope(Scope::Kind kind, Symbol *symbol);536  void PushScope(Scope &scope);537  void PopScope();538  void SetScope(Scope &);539 540  template <typename T> bool Pre(const parser::Statement<T> &x) {541    messageHandler().set_currStmtSource(x.source);542    currScope_->AddSourceRange(x.source);543    return true;544  }545  template <typename T> void Post(const parser::Statement<T> &) {546    messageHandler().set_currStmtSource(std::nullopt);547  }548 549  // Special messages: already declared; referencing symbol's declaration;550  // about a type; two names & locations551  void SayAlreadyDeclared(const parser::Name &, Symbol &);552  void SayAlreadyDeclared(const SourceName &, Symbol &);553  void SayAlreadyDeclared(const SourceName &, const SourceName &);554  void SayWithReason(555      const parser::Name &, Symbol &, MessageFixedText &&, Message &&);556  template <typename... A>557  Message &SayWithDecl(558      const parser::Name &, Symbol &, MessageFixedText &&, A &&...args);559  void SayLocalMustBeVariable(const parser::Name &, Symbol &);560  Message &SayDerivedType(561      const SourceName &, MessageFixedText &&, const Scope &);562  Message &Say2(const SourceName &, MessageFixedText &&, const SourceName &,563      MessageFixedText &&);564  Message &Say2(565      const SourceName &, MessageFixedText &&, Symbol &, MessageFixedText &&);566  Message &Say2(567      const parser::Name &, MessageFixedText &&, Symbol &, MessageFixedText &&);568 569  // Search for symbol by name in current, parent derived type, and570  // containing scopes571  Symbol *FindSymbol(const parser::Name &);572  Symbol *FindSymbol(const Scope &, const parser::Name &);573  // Search for name only in scope, not in enclosing scopes.574  Symbol *FindInScope(const Scope &, const parser::Name &);575  Symbol *FindInScope(const Scope &, const SourceName &);576  template <typename T> Symbol *FindInScope(const T &name) {577    return FindInScope(currScope(), name);578  }579  // Search for name in a derived type scope and its parents.580  Symbol *FindInTypeOrParents(const Scope &, const parser::Name &);581  Symbol *FindInTypeOrParents(const parser::Name &);582  Symbol *FindInScopeOrBlockConstructs(const Scope &, SourceName);583  Symbol *FindSeparateModuleProcedureInterface(const parser::Name &);584  void EraseSymbol(const parser::Name &);585  void EraseSymbol(const Symbol &symbol) { currScope().erase(symbol.name()); }586  // Make a new symbol with the name and attrs of an existing one587  Symbol &CopySymbol(const SourceName &, const Symbol &);588 589  // Make symbols in the current or named scope590  Symbol &MakeSymbol(Scope &, const SourceName &, Attrs);591  Symbol &MakeSymbol(const SourceName &, Attrs = Attrs{});592  Symbol &MakeSymbol(const parser::Name &, Attrs = Attrs{});593  Symbol &MakeHostAssocSymbol(const parser::Name &, const Symbol &);594 595  template <typename D>596  common::IfNoLvalue<Symbol &, D> MakeSymbol(597      const parser::Name &name, D &&details) {598    return MakeSymbol(name, Attrs{}, std::move(details));599  }600 601  template <typename D>602  common::IfNoLvalue<Symbol &, D> MakeSymbol(603      const parser::Name &name, const Attrs &attrs, D &&details) {604    return Resolve(name, MakeSymbol(name.source, attrs, std::move(details)));605  }606 607  template <typename D>608  common::IfNoLvalue<Symbol &, D> MakeSymbol(609      const SourceName &name, const Attrs &attrs, D &&details) {610    // Note: don't use FindSymbol here. If this is a derived type scope,611    // we want to detect whether the name is already declared as a component.612    auto *symbol{FindInScope(name)};613    if (!symbol) {614      symbol = &MakeSymbol(name, attrs);615      symbol->set_details(std::move(details));616      return *symbol;617    }618    if constexpr (std::is_same_v<DerivedTypeDetails, D>) {619      if (auto *d{symbol->detailsIf<GenericDetails>()}) {620        if (!d->specific()) {621          // derived type with same name as a generic622          auto *derivedType{d->derivedType()};623          if (!derivedType) {624            derivedType =625                &currScope().MakeSymbol(name, attrs, std::move(details));626            d->set_derivedType(*derivedType);627          } else if (derivedType->CanReplaceDetails(details)) {628            // was forward-referenced629            CheckDuplicatedAttrs(name, *symbol, attrs);630            SetExplicitAttrs(*derivedType, attrs);631            derivedType->set_details(std::move(details));632          } else {633            SayAlreadyDeclared(name, *derivedType);634          }635          return *derivedType;636        }637      }638    } else if constexpr (std::is_same_v<ProcEntityDetails, D>) {639      if (auto *d{symbol->detailsIf<GenericDetails>()}) {640        if (!d->derivedType()) {641          // procedure pointer with same name as a generic642          auto *specific{d->specific()};643          if (!specific) {644            specific = &currScope().MakeSymbol(name, attrs, std::move(details));645            d->set_specific(*specific);646          } else {647            SayAlreadyDeclared(name, *specific);648          }649          return *specific;650        }651      }652    }653    if (symbol->CanReplaceDetails(details)) {654      // update the existing symbol655      if constexpr (std::is_same_v<SubprogramDetails, D>) {656        // Dummy argument defined by explicit interface?657        details.set_isDummy(IsDummy(*symbol));658        if (symbol->has<ProcEntityDetails>()) {659          // Bare "EXTERNAL" dummy replaced with explicit INTERFACE660          context().Warn(common::LanguageFeature::RedundantAttribute, name,661              "Dummy argument '%s' was declared earlier as EXTERNAL"_warn_en_US,662              name);663        }664      }665      CheckDuplicatedAttrs(name, *symbol, attrs);666      SetExplicitAttrs(*symbol, attrs);667      symbol->set_details(std::move(details));668      return *symbol;669    } else if constexpr (std::is_same_v<UnknownDetails, D>) {670      CheckDuplicatedAttrs(name, *symbol, attrs);671      SetExplicitAttrs(*symbol, attrs);672      return *symbol;673    } else {674      if (!CheckPossibleBadForwardRef(*symbol)) {675        if (name.empty() && symbol->name().empty()) {676          // report the error elsewhere677          return *symbol;678        }679        Symbol &errSym{*symbol};680        if (auto *d{symbol->detailsIf<GenericDetails>()}) {681          if (d->specific()) {682            errSym = *d->specific();683          } else if (d->derivedType()) {684            errSym = *d->derivedType();685          }686        }687        SayAlreadyDeclared(name, errSym);688      }689      // replace the old symbol with a new one with correct details690      EraseSymbol(*symbol);691      auto &result{MakeSymbol(name, attrs, std::move(details))};692      context().SetError(result);693      return result;694    }695  }696 697  void MakeExternal(Symbol &);698 699  // C815 duplicated attribute checking; returns false on error700  bool CheckDuplicatedAttr(SourceName, Symbol &, Attr);701  bool CheckDuplicatedAttrs(SourceName, Symbol &, Attrs);702 703  void SetExplicitAttr(Symbol &symbol, Attr attr) const {704    symbol.attrs().set(attr);705    symbol.implicitAttrs().reset(attr);706  }707  void SetExplicitAttrs(Symbol &symbol, Attrs attrs) const {708    symbol.attrs() |= attrs;709    symbol.implicitAttrs() &= ~attrs;710  }711  void SetImplicitAttr(Symbol &symbol, Attr attr) const {712    symbol.attrs().set(attr);713    symbol.implicitAttrs().set(attr);714  }715  void SetCUDADataAttr(716      SourceName, Symbol &, std::optional<common::CUDADataAttr>);717 718protected:719  FuncResultStack &funcResultStack() { return funcResultStack_; }720 721  // Apply the implicit type rules to this symbol.722  void ApplyImplicitRules(Symbol &, bool allowForwardReference = false);723  bool ImplicitlyTypeForwardRef(Symbol &);724  void AcquireIntrinsicProcedureFlags(Symbol &);725  const DeclTypeSpec *GetImplicitType(726      Symbol &, bool respectImplicitNoneType = true);727  void CheckEntryDummyUse(SourceName, Symbol *);728  bool ConvertToObjectEntity(Symbol &);729  bool ConvertToProcEntity(Symbol &, std::optional<SourceName> = std::nullopt);730 731  const DeclTypeSpec &MakeNumericType(732      TypeCategory, const std::optional<parser::KindSelector> &);733  const DeclTypeSpec &MakeNumericType(TypeCategory, int);734  const DeclTypeSpec &MakeLogicalType(735      const std::optional<parser::KindSelector> &);736  const DeclTypeSpec &MakeLogicalType(int);737  void NotePossibleBadForwardRef(const parser::Name &);738  std::optional<SourceName> HadForwardRef(const Symbol &) const;739  bool CheckPossibleBadForwardRef(const Symbol &);740  bool ConvertToUseError(Symbol &, const SourceName &, const Symbol &used);741 742  bool inSpecificationPart_{false};743  bool deferImplicitTyping_{false};744  bool skipImplicitTyping_{false};745  bool inEquivalenceStmt_{false};746 747  // Some information is collected from a specification part for deferred748  // processing in DeclarationPartVisitor functions (e.g., CheckSaveStmts())749  // that are called by ResolveNamesVisitor::FinishSpecificationPart().  Since750  // specification parts can nest (e.g., INTERFACE bodies), the collected751  // information that is not contained in the scope needs to be packaged752  // and restorable.753  struct SpecificationPartState {754    std::set<SourceName> forwardRefs;755    // Collect equivalence sets and process at end of specification part756    std::vector<const std::list<parser::EquivalenceObject> *> equivalenceSets;757    // Names of all common block objects in the scope758    std::set<SourceName> commonBlockObjects;759    // Names of all names that show in a declare target declaration760    std::set<SourceName> declareTargetNames;761    // Info about SAVE statements and attributes in current scope762    struct {763      std::optional<SourceName> saveAll; // "SAVE" without entity list764      std::set<SourceName> entities; // names of entities with save attr765      std::set<SourceName> commons; // names of common blocks with save attr766    } saveInfo;767  } specPartState_;768 769  // Some declaration processing can and should be deferred to770  // ResolveExecutionParts() to avoid prematurely creating implicitly-typed771  // local symbols that should be host associations.772  struct DeferredDeclarationState {773    // The content of each namelist group774    std::list<const parser::NamelistStmt::Group *> namelistGroups;775  };776  DeferredDeclarationState *GetDeferredDeclarationState(bool add = false) {777    if (!add && deferred_.find(&currScope()) == deferred_.end()) {778      return nullptr;779    } else {780      return &deferred_.emplace(&currScope(), DeferredDeclarationState{})781                  .first->second;782    }783  }784 785  void SkipImplicitTyping(bool skip) {786    deferImplicitTyping_ = skipImplicitTyping_ = skip;787  }788 789  void NoteEarlyDeclaredDummyArgument(Symbol &symbol) {790    earlyDeclaredDummyArguments_.insert(symbol);791  }792  bool IsEarlyDeclaredDummyArgument(Symbol &symbol) {793    return earlyDeclaredDummyArguments_.find(symbol) !=794        earlyDeclaredDummyArguments_.end();795  }796  void ForgetEarlyDeclaredDummyArgument(Symbol &symbol) {797    earlyDeclaredDummyArguments_.erase(symbol);798  }799 800private:801  Scope *currScope_{nullptr};802  FuncResultStack funcResultStack_{*this};803  std::map<Scope *, DeferredDeclarationState> deferred_;804  UnorderedSymbolSet earlyDeclaredDummyArguments_;805};806 807class ModuleVisitor : public virtual ScopeHandler {808public:809  bool Pre(const parser::AccessStmt &);810  bool Pre(const parser::Only &);811  bool Pre(const parser::Rename::Names &);812  bool Pre(const parser::Rename::Operators &);813  bool Pre(const parser::UseStmt &);814  void Post(const parser::UseStmt &);815 816  void BeginModule(const parser::Name &, bool isSubmodule);817  bool BeginSubmodule(const parser::Name &, const parser::ParentIdentifier &);818  void ApplyDefaultAccess();819  Symbol &AddGenericUse(GenericDetails &, const SourceName &, const Symbol &);820  void AddAndCheckModuleUse(SourceName, bool isIntrinsic);821  void CollectUseRenames(const parser::UseStmt &);822  void ClearUseRenames() { useRenames_.clear(); }823  void ClearUseOnly() { useOnly_.clear(); }824  void ClearModuleUses() {825    intrinsicUses_.clear();826    nonIntrinsicUses_.clear();827  }828 829private:830  // The location of the last AccessStmt without access-ids, if any.831  std::optional<SourceName> prevAccessStmt_;832  // The scope of the module during a UseStmt833  Scope *useModuleScope_{nullptr};834  // Names that have appeared in a rename clause of USE statements835  std::set<std::pair<SourceName, SourceName>> useRenames_;836  // Names that have appeared in an ONLY clause of a USE statement837  std::set<std::pair<SourceName, Scope *>> useOnly_;838  // Intrinsic and non-intrinsic (explicit or not) module names that839  // have appeared in USE statements; used for C1406 warnings.840  std::set<SourceName> intrinsicUses_;841  std::set<SourceName> nonIntrinsicUses_;842 843  Symbol &SetAccess(const SourceName &, Attr attr, Symbol * = nullptr);844  // A rename in a USE statement: local => use845  struct SymbolRename {846    Symbol *local{nullptr};847    Symbol *use{nullptr};848  };849  // Record a use from useModuleScope_ of use Name/Symbol as local Name/Symbol850  SymbolRename AddUse(const SourceName &localName, const SourceName &useName);851  SymbolRename AddUse(const SourceName &, const SourceName &, Symbol *);852  void DoAddUse(853      SourceName, SourceName, Symbol &localSymbol, const Symbol &useSymbol);854  void AddUse(const GenericSpecInfo &);855  // Record a name appearing as the target of a USE rename clause856  void AddUseRename(SourceName name, SourceName moduleName) {857    useRenames_.emplace(std::make_pair(name, moduleName));858  }859  bool IsUseRenamed(const SourceName &name) const {860    return useModuleScope_ && useModuleScope_->symbol() &&861        useRenames_.find({name, useModuleScope_->symbol()->name()}) !=862        useRenames_.end();863  }864  // Record a name appearing in a USE ONLY clause865  void AddUseOnly(const SourceName &name) {866    useOnly_.emplace(std::make_pair(name, useModuleScope_));867  }868  bool IsUseOnly(const SourceName &name) const {869    return useOnly_.find({name, useModuleScope_}) != useOnly_.end();870  }871  Scope *FindModule(const parser::Name &, std::optional<bool> isIntrinsic,872      Scope *ancestor = nullptr);873};874 875class GenericHandler : public virtual ScopeHandler {876protected:877  using ProcedureKind = parser::ProcedureStmt::Kind;878  void ResolveSpecificsInGeneric(Symbol &, bool isEndOfSpecificationPart);879  void DeclaredPossibleSpecificProc(Symbol &);880 881  // Mappings of generics to their as-yet specific proc names and kinds882  using SpecificProcMapType =883      std::multimap<Symbol *, std::pair<const parser::Name *, ProcedureKind>>;884  SpecificProcMapType specificsForGenericProcs_;885  // inversion of SpecificProcMapType: maps pending proc names to generics886  using GenericProcMapType = std::multimap<SourceName, Symbol *>;887  GenericProcMapType genericsForSpecificProcs_;888};889 890class InterfaceVisitor : public virtual ScopeHandler,891                         public virtual GenericHandler {892public:893  bool Pre(const parser::InterfaceStmt &);894  void Post(const parser::InterfaceStmt &);895  void Post(const parser::EndInterfaceStmt &);896  bool Pre(const parser::GenericSpec &);897  bool Pre(const parser::ProcedureStmt &);898  bool Pre(const parser::GenericStmt &);899  void Post(const parser::GenericStmt &);900 901  bool inInterfaceBlock() const;902  bool isGeneric() const;903  bool isAbstract() const;904 905protected:906  Symbol &GetGenericSymbol() { return DEREF(genericInfo_.top().symbol); }907  // Add to generic the symbol for the subprogram with the same name908  void CheckGenericProcedures(Symbol &);909 910private:911  // A new GenericInfo is pushed for each interface block and generic stmt912  struct GenericInfo {913    GenericInfo(bool isInterface, bool isAbstract = false)914        : isInterface{isInterface}, isAbstract{isAbstract} {}915    bool isInterface; // in interface block916    bool isAbstract; // in abstract interface block917    Symbol *symbol{nullptr}; // the generic symbol being defined918  };919  std::stack<GenericInfo> genericInfo_;920  const GenericInfo &GetGenericInfo() const { return genericInfo_.top(); }921  void SetGenericSymbol(Symbol &symbol) { genericInfo_.top().symbol = &symbol; }922  void AddSpecificProcs(const std::list<parser::Name> &, ProcedureKind);923  void ResolveNewSpecifics();924};925 926class SubprogramVisitor : public virtual ScopeHandler, public InterfaceVisitor {927public:928  bool HandleStmtFunction(const parser::StmtFunctionStmt &);929  bool Pre(const parser::SubroutineStmt &);930  bool Pre(const parser::FunctionStmt &);931  void Post(const parser::FunctionStmt &);932  bool Pre(const parser::EntryStmt &);933  void Post(const parser::EntryStmt &);934  bool Pre(const parser::InterfaceBody::Subroutine &);935  void Post(const parser::InterfaceBody::Subroutine &);936  bool Pre(const parser::InterfaceBody::Function &);937  void Post(const parser::InterfaceBody::Function &);938  bool Pre(const parser::Suffix &);939  bool Pre(const parser::PrefixSpec &);940  bool Pre(const parser::PrefixSpec::Attributes &);941  void Post(const parser::PrefixSpec::Launch_Bounds &);942  void Post(const parser::PrefixSpec::Cluster_Dims &);943 944  bool BeginSubprogram(const parser::Name &, Symbol::Flag,945      bool hasModulePrefix = false,946      const parser::LanguageBindingSpec * = nullptr,947      const ProgramTree::EntryStmtList * = nullptr);948  bool BeginMpSubprogram(const parser::Name &);949  void PushBlockDataScope(const parser::Name &);950  void EndSubprogram(std::optional<parser::CharBlock> stmtSource = std::nullopt,951      const std::optional<parser::LanguageBindingSpec> * = nullptr,952      const ProgramTree::EntryStmtList * = nullptr);953 954protected:955  // Set when we see a stmt function that is really an array element assignment956  bool misparsedStmtFuncFound_{false};957 958private:959  // Edits an existing symbol created for earlier calls to a subprogram or ENTRY960  // so that it can be replaced by a later definition.961  bool HandlePreviousCalls(const parser::Name &, Symbol &, Symbol::Flag);962  const Symbol *CheckExtantProc(const parser::Name &, Symbol::Flag);963  // Create a subprogram symbol in the current scope and push a new scope.964  Symbol *PushSubprogramScope(const parser::Name &, Symbol::Flag,965      const parser::LanguageBindingSpec * = nullptr,966      bool hasModulePrefix = false);967  Symbol *GetSpecificFromGeneric(const parser::Name &);968  Symbol &PostSubprogramStmt();969  void CreateDummyArgument(SubprogramDetails &, const parser::Name &);970  void CreateEntry(const parser::EntryStmt &stmt, Symbol &subprogram);971  void PostEntryStmt(const parser::EntryStmt &stmt);972  void HandleLanguageBinding(Symbol *,973      std::optional<parser::CharBlock> stmtSource,974      const std::optional<parser::LanguageBindingSpec> *);975};976 977class DeclarationVisitor : public ArraySpecVisitor,978                           public virtual GenericHandler {979public:980  using ArraySpecVisitor::Post;981  using ScopeHandler::Post;982  using ScopeHandler::Pre;983 984  bool Pre(const parser::Initialization &);985  void Post(const parser::EntityDecl &);986  void Post(const parser::ObjectDecl &);987  void Post(const parser::PointerDecl &);988  bool Pre(const parser::BindStmt &) { return BeginAttrs(); }989  void Post(const parser::BindStmt &) { EndAttrs(); }990  bool Pre(const parser::BindEntity &);991  bool Pre(const parser::OldParameterStmt &);992  bool Pre(const parser::NamedConstantDef &);993  bool Pre(const parser::NamedConstant &);994  void Post(const parser::EnumDef &);995  bool Pre(const parser::Enumerator &);996  bool Pre(const parser::AccessSpec &);997  bool Pre(const parser::AsynchronousStmt &);998  bool Pre(const parser::ContiguousStmt &);999  bool Pre(const parser::ExternalStmt &);1000  bool Pre(const parser::IntentStmt &);1001  bool Pre(const parser::IntrinsicStmt &);1002  bool Pre(const parser::OptionalStmt &);1003  bool Pre(const parser::ProtectedStmt &);1004  bool Pre(const parser::ValueStmt &);1005  bool Pre(const parser::VolatileStmt &);1006  bool Pre(const parser::AllocatableStmt &) {1007    objectDeclAttr_ = Attr::ALLOCATABLE;1008    return true;1009  }1010  void Post(const parser::AllocatableStmt &) { objectDeclAttr_ = std::nullopt; }1011  bool Pre(const parser::TargetStmt &) {1012    objectDeclAttr_ = Attr::TARGET;1013    return true;1014  }1015  bool Pre(const parser::CUDAAttributesStmt &);1016  void Post(const parser::TargetStmt &) { objectDeclAttr_ = std::nullopt; }1017  void Post(const parser::DimensionStmt::Declaration &);1018  void Post(const parser::CodimensionDecl &);1019  bool Pre(const parser::TypeDeclarationStmt &);1020  void Post(const parser::TypeDeclarationStmt &);1021  void Post(const parser::IntegerTypeSpec &);1022  void Post(const parser::UnsignedTypeSpec &);1023  void Post(const parser::IntrinsicTypeSpec::Real &);1024  void Post(const parser::IntrinsicTypeSpec::Complex &);1025  void Post(const parser::IntrinsicTypeSpec::Logical &);1026  void Post(const parser::IntrinsicTypeSpec::Character &);1027  void Post(const parser::CharSelector::LengthAndKind &);1028  void Post(const parser::CharLength &);1029  void Post(const parser::LengthSelector &);1030  bool Pre(const parser::KindParam &);1031  bool Pre(const parser::VectorTypeSpec &);1032  void Post(const parser::VectorTypeSpec &);1033  bool Pre(const parser::DeclarationTypeSpec::Type &);1034  void Post(const parser::DeclarationTypeSpec::Type &);1035  bool Pre(const parser::DeclarationTypeSpec::Class &);1036  void Post(const parser::DeclarationTypeSpec::Class &);1037  void Post(const parser::DeclarationTypeSpec::Record &);1038  void Post(const parser::DerivedTypeSpec &);1039  bool Pre(const parser::DerivedTypeDef &);1040  bool Pre(const parser::DerivedTypeStmt &);1041  void Post(const parser::DerivedTypeStmt &);1042  bool Pre(const parser::TypeParamDefStmt &) { return BeginDecl(); }1043  void Post(const parser::TypeParamDefStmt &);1044  bool Pre(const parser::TypeAttrSpec::Extends &);1045  bool Pre(const parser::PrivateStmt &);1046  bool Pre(const parser::SequenceStmt &);1047  bool Pre(const parser::ComponentDefStmt &) { return BeginDecl(); }1048  void Post(const parser::ComponentDefStmt &) { EndDecl(); }1049  void Post(const parser::ComponentDecl &);1050  void Post(const parser::FillDecl &);1051  bool Pre(const parser::ProcedureDeclarationStmt &);1052  void Post(const parser::ProcedureDeclarationStmt &);1053  bool Pre(const parser::DataComponentDefStmt &); // returns false1054  bool Pre(const parser::ProcComponentDefStmt &);1055  void Post(const parser::ProcComponentDefStmt &);1056  bool Pre(const parser::ProcPointerInit &);1057  void Post(const parser::ProcInterface &);1058  void Post(const parser::ProcDecl &);1059  bool Pre(const parser::TypeBoundProcedurePart &);1060  void Post(const parser::TypeBoundProcedurePart &);1061  void Post(const parser::ContainsStmt &);1062  bool Pre(const parser::TypeBoundProcBinding &) { return BeginAttrs(); }1063  void Post(const parser::TypeBoundProcBinding &) { EndAttrs(); }1064  void Post(const parser::TypeBoundProcedureStmt::WithoutInterface &);1065  void Post(const parser::TypeBoundProcedureStmt::WithInterface &);1066  bool Pre(const parser::FinalProcedureStmt &);1067  bool Pre(const parser::TypeBoundGenericStmt &);1068  bool Pre(const parser::StructureDef &); // returns false1069  bool Pre(const parser::Union::UnionStmt &);1070  bool Pre(const parser::StructureField &);1071  void Post(const parser::StructureField &);1072  bool Pre(const parser::AllocateStmt &);1073  void Post(const parser::AllocateStmt &);1074  bool Pre(const parser::StructureConstructor &);1075  bool Pre(const parser::NamelistStmt::Group &);1076  bool Pre(const parser::IoControlSpec &);1077  bool Pre(const parser::CommonStmt::Block &);1078  bool Pre(const parser::CommonBlockObject &);1079  void Post(const parser::CommonBlockObject &);1080  bool Pre(const parser::EquivalenceStmt &);1081  bool Pre(const parser::SaveStmt &);1082  bool Pre(const parser::BasedPointer &);1083  void Post(const parser::BasedPointer &);1084 1085  void PointerInitialization(1086      const parser::Name &, const parser::InitialDataTarget &);1087  void PointerInitialization(1088      const parser::Name &, const parser::ProcPointerInit &);1089  bool CheckNonPointerInitialization(1090      const parser::Name &, bool inLegacyDataInitialization);1091  void NonPointerInitialization(1092      const parser::Name &, const parser::ConstantExpr &);1093  void LegacyDataInitialization(const parser::Name &,1094      const std::list<common::Indirection<parser::DataStmtValue>> &values);1095  void CheckExplicitInterface(const parser::Name &);1096  void CheckBindings(const parser::TypeBoundProcedureStmt::WithoutInterface &);1097 1098  const parser::Name *ResolveDesignator(const parser::Designator &);1099  int GetVectorElementKind(1100      TypeCategory category, const std::optional<parser::KindSelector> &kind);1101 1102protected:1103  bool BeginDecl();1104  void EndDecl();1105  Symbol &DeclareObjectEntity(const parser::Name &, Attrs = Attrs{});1106  // Make sure that there's an entity in an enclosing scope called Name1107  Symbol &FindOrDeclareEnclosingEntity(const parser::Name &);1108  // Declare a LOCAL/LOCAL_INIT/REDUCE entity while setting a locality flag. If1109  // there isn't a type specified it comes from the entity in the containing1110  // scope, or implicit rules.1111  void DeclareLocalEntity(const parser::Name &, Symbol::Flag);1112  // Declare a statement entity (i.e., an implied DO loop index for1113  // a DATA statement or an array constructor).  If there isn't an explict1114  // type specified, implicit rules apply. Return pointer to the new symbol,1115  // or nullptr on error.1116  Symbol *DeclareStatementEntity(const parser::DoVariable &,1117      const std::optional<parser::IntegerTypeSpec> &);1118  Symbol &MakeCommonBlockSymbol(const parser::Name &, SourceName);1119  Symbol &MakeCommonBlockSymbol(1120      const std::optional<parser::Name> &, SourceName);1121  bool CheckUseError(const parser::Name &);1122  void CheckAccessibility(const SourceName &, bool, Symbol &);1123  void CheckCommonBlocks();1124  void CheckSaveStmts();1125  void CheckEquivalenceSets();1126  bool CheckNotInBlock(const char *);1127  bool NameIsKnownOrIntrinsic(const parser::Name &);1128  void FinishNamelists();1129 1130  // Each of these returns a pointer to a resolved Name (i.e. with symbol)1131  // or nullptr in case of error.1132  const parser::Name *ResolveStructureComponent(1133      const parser::StructureComponent &);1134  const parser::Name *ResolveDataRef(const parser::DataRef &);1135  const parser::Name *ResolveName(const parser::Name &);1136  bool PassesSharedLocalityChecks(const parser::Name &name, Symbol &symbol);1137  Symbol *NoteInterfaceName(const parser::Name &);1138  bool IsUplevelReference(const Symbol &);1139 1140  std::optional<SourceName> BeginCheckOnIndexUseInOwnBounds(1141      const parser::DoVariable &name) {1142    std::optional<SourceName> result{checkIndexUseInOwnBounds_};1143    checkIndexUseInOwnBounds_ = parser::UnwrapRef<parser::Name>(name).source;1144    return result;1145  }1146  void EndCheckOnIndexUseInOwnBounds(const std::optional<SourceName> &restore) {1147    checkIndexUseInOwnBounds_ = restore;1148  }1149  void NoteScalarSpecificationArgument(const Symbol &symbol) {1150    mustBeScalar_.emplace(symbol);1151  }1152  // Declare an object or procedure entity.1153  // T is one of: EntityDetails, ObjectEntityDetails, ProcEntityDetails1154  template <typename T>1155  Symbol &DeclareEntity(const parser::Name &name, Attrs attrs) {1156    Symbol &symbol{MakeSymbol(name, attrs)};1157    if (context().HasError(symbol) || symbol.has<T>()) {1158      return symbol; // OK or error already reported1159    } else if (symbol.has<UnknownDetails>()) {1160      symbol.set_details(T{});1161      return symbol;1162    } else if (auto *details{symbol.detailsIf<EntityDetails>()}) {1163      symbol.set_details(T{std::move(*details)});1164      return symbol;1165    } else if (std::is_same_v<EntityDetails, T> &&1166        (symbol.has<ObjectEntityDetails>() ||1167            symbol.has<ProcEntityDetails>())) {1168      return symbol; // OK1169    } else if (auto *details{symbol.detailsIf<UseDetails>()}) {1170      Say(name.source,1171          "'%s' is use-associated from module '%s' and cannot be re-declared"_err_en_US,1172          name.source, GetUsedModule(*details).name());1173    } else if (auto *details{symbol.detailsIf<SubprogramNameDetails>()}) {1174      if (details->kind() == SubprogramKind::Module) {1175        Say2(name,1176            "Declaration of '%s' conflicts with its use as module procedure"_err_en_US,1177            symbol, "Module procedure definition"_en_US);1178      } else if (details->kind() == SubprogramKind::Internal) {1179        Say2(name,1180            "Declaration of '%s' conflicts with its use as internal procedure"_err_en_US,1181            symbol, "Internal procedure definition"_en_US);1182      } else {1183        DIE("unexpected kind");1184      }1185    } else if (std::is_same_v<ObjectEntityDetails, T> &&1186        symbol.has<ProcEntityDetails>()) {1187      SayWithDecl(1188          name, symbol, "'%s' is already declared as a procedure"_err_en_US);1189    } else if (std::is_same_v<ProcEntityDetails, T> &&1190        symbol.has<ObjectEntityDetails>()) {1191      if (FindCommonBlockContaining(symbol)) {1192        SayWithDecl(name, symbol,1193            "'%s' may not be a procedure as it is in a COMMON block"_err_en_US);1194      } else {1195        SayWithDecl(1196            name, symbol, "'%s' is already declared as an object"_err_en_US);1197      }1198    } else if (!CheckPossibleBadForwardRef(symbol)) {1199      SayAlreadyDeclared(name, symbol);1200    }1201    context().SetError(symbol);1202    return symbol;1203  }1204 1205private:1206  // The attribute corresponding to the statement containing an ObjectDecl1207  std::optional<Attr> objectDeclAttr_;1208  // Info about current character type while walking DeclTypeSpec.1209  // Also captures any "*length" specifier on an individual declaration.1210  struct {1211    std::optional<ParamValue> length;1212    std::optional<KindExpr> kind;1213  } charInfo_;1214  // Info about current derived type or STRUCTURE while walking1215  // DerivedTypeDef / StructureDef1216  struct {1217    const parser::Name *extends{nullptr}; // EXTENDS(name)1218    bool privateComps{false}; // components are private by default1219    bool privateBindings{false}; // bindings are private by default1220    bool sawContains{false}; // currently processing bindings1221    bool sequence{false}; // is a sequence type1222    const Symbol *type{nullptr}; // derived type being defined1223    bool isStructure{false}; // is a DEC STRUCTURE1224  } derivedTypeInfo_;1225  // In a ProcedureDeclarationStmt or ProcComponentDefStmt, this is1226  // the interface name, if any.1227  const parser::Name *interfaceName_{nullptr};1228  // Map type-bound generic to binding names of its specific bindings1229  std::multimap<Symbol *, const parser::Name *> genericBindings_;1230  // Info about current ENUM1231  struct EnumeratorState {1232    // Enum value must hold inside a C_INT (7.6.2).1233    std::optional<int> value{0};1234  } enumerationState_;1235  // Set for OldParameterStmt processing1236  bool inOldStyleParameterStmt_{false};1237  // Set when walking DATA & array constructor implied DO loop bounds1238  // to warn about use of the implied DO intex therein.1239  std::optional<SourceName> checkIndexUseInOwnBounds_;1240  bool isVectorType_{false};1241  UnorderedSymbolSet mustBeScalar_;1242 1243  bool HandleAttributeStmt(Attr, const std::list<parser::Name> &);1244  Symbol &HandleAttributeStmt(Attr, const parser::Name &);1245  Symbol &DeclareUnknownEntity(const parser::Name &, Attrs);1246  Symbol &DeclareProcEntity(1247      const parser::Name &, Attrs, const Symbol *interface);1248  void SetType(const parser::Name &, const DeclTypeSpec &);1249  std::optional<DerivedTypeSpec> ResolveDerivedType(const parser::Name &);1250  std::optional<DerivedTypeSpec> ResolveExtendsType(1251      const parser::Name &, const parser::Name *);1252  Symbol *MakeTypeSymbol(const SourceName &, Details &&);1253  Symbol *MakeTypeSymbol(const parser::Name &, Details &&);1254  bool OkToAddComponent(const parser::Name &, const Symbol *extends = nullptr);1255  ParamValue GetParamValue(1256      const parser::TypeParamValue &, common::TypeParamAttr attr);1257  Attrs HandleSaveName(const SourceName &, Attrs);1258  void AddSaveName(std::set<SourceName> &, const SourceName &);1259  bool HandleUnrestrictedSpecificIntrinsicFunction(const parser::Name &);1260  const parser::Name *FindComponent(const parser::Name *, const parser::Name &);1261  void Initialization(const parser::Name &, const parser::Initialization &,1262      bool inComponentDecl);1263  bool FindAndMarkDeclareTargetSymbol(const parser::Name &);1264  bool PassesLocalityChecks(1265      const parser::Name &name, Symbol &symbol, Symbol::Flag flag);1266  bool CheckForHostAssociatedImplicit(const parser::Name &);1267  bool HasCycle(const Symbol &, const Symbol *interface);1268  bool MustBeScalar(const Symbol &symbol) const {1269    return mustBeScalar_.find(symbol) != mustBeScalar_.end();1270  }1271  void DeclareIntrinsic(const parser::Name &);1272};1273 1274// Resolve construct entities and statement entities.1275// Check that construct names don't conflict with other names.1276class ConstructVisitor : public virtual DeclarationVisitor {1277public:1278  bool Pre(const parser::ConcurrentHeader &);1279  bool Pre(const parser::LocalitySpec::Local &);1280  bool Pre(const parser::LocalitySpec::LocalInit &);1281  bool Pre(const parser::LocalitySpec::Reduce &);1282  bool Pre(const parser::LocalitySpec::Shared &);1283  bool Pre(const parser::AcSpec &);1284  bool Pre(const parser::AcImpliedDo &);1285  bool Pre(const parser::DataImpliedDo &);1286  bool Pre(const parser::DataIDoObject &);1287  bool Pre(const parser::DataStmtObject &);1288  bool Pre(const parser::DataStmtValue &);1289  bool Pre(const parser::DoConstruct &);1290  void Post(const parser::DoConstruct &);1291  bool Pre(const parser::ForallConstruct &);1292  void Post(const parser::ForallConstruct &);1293  bool Pre(const parser::ForallStmt &);1294  void Post(const parser::ForallStmt &);1295  bool Pre(const parser::BlockConstruct &);1296  void Post(const parser::Selector &);1297  void Post(const parser::AssociateStmt &);1298  void Post(const parser::EndAssociateStmt &);1299  bool Pre(const parser::Association &);1300  void Post(const parser::SelectTypeStmt &);1301  void Post(const parser::SelectRankStmt &);1302  bool Pre(const parser::SelectTypeConstruct &);1303  void Post(const parser::SelectTypeConstruct &);1304  bool Pre(const parser::SelectTypeConstruct::TypeCase &);1305  void Post(const parser::SelectTypeConstruct::TypeCase &);1306  // Creates Block scopes with neither symbol name nor symbol details.1307  bool Pre(const parser::SelectRankConstruct::RankCase &);1308  void Post(const parser::SelectRankConstruct::RankCase &);1309  bool Pre(const parser::TypeGuardStmt::Guard &);1310  void Post(const parser::TypeGuardStmt::Guard &);1311  void Post(const parser::SelectRankCaseStmt::Rank &);1312  bool Pre(const parser::ChangeTeamStmt &);1313  void Post(const parser::EndChangeTeamStmt &);1314  void Post(const parser::CoarrayAssociation &);1315 1316  // Definitions of construct names1317  bool Pre(const parser::WhereConstructStmt &x) { return CheckDef(x.t); }1318  bool Pre(const parser::ForallConstructStmt &x) { return CheckDef(x.t); }1319  bool Pre(const parser::CriticalStmt &x) { return CheckDef(x.t); }1320  bool Pre(const parser::LabelDoStmt &) {1321    return false; // error recovery1322  }1323  bool Pre(const parser::NonLabelDoStmt &x) { return CheckDef(x.t); }1324  bool Pre(const parser::IfThenStmt &x) { return CheckDef(x.t); }1325  bool Pre(const parser::SelectCaseStmt &x) { return CheckDef(x.t); }1326  bool Pre(const parser::SelectRankConstruct &);1327  void Post(const parser::SelectRankConstruct &);1328  bool Pre(const parser::SelectRankStmt &x) {1329    return CheckDef(std::get<0>(x.t));1330  }1331  bool Pre(const parser::SelectTypeStmt &x) {1332    return CheckDef(std::get<0>(x.t));1333  }1334 1335  // References to construct names1336  void Post(const parser::MaskedElsewhereStmt &x) { CheckRef(x.t); }1337  void Post(const parser::ElsewhereStmt &x) { CheckRef(x.v); }1338  void Post(const parser::EndWhereStmt &x) { CheckRef(x.v); }1339  void Post(const parser::EndForallStmt &x) { CheckRef(x.v); }1340  void Post(const parser::EndCriticalStmt &x) { CheckRef(x.v); }1341  void Post(const parser::EndDoStmt &x) { CheckRef(x.v); }1342  void Post(const parser::ElseIfStmt &x) { CheckRef(x.t); }1343  void Post(const parser::ElseStmt &x) { CheckRef(x.v); }1344  void Post(const parser::EndIfStmt &x) { CheckRef(x.v); }1345  void Post(const parser::CaseStmt &x) { CheckRef(x.t); }1346  void Post(const parser::EndSelectStmt &x) { CheckRef(x.v); }1347  void Post(const parser::SelectRankCaseStmt &x) { CheckRef(x.t); }1348  void Post(const parser::TypeGuardStmt &x) { CheckRef(x.t); }1349  void Post(const parser::CycleStmt &x) { CheckRef(x.v); }1350  void Post(const parser::ExitStmt &x) { CheckRef(x.v); }1351 1352  void HandleImpliedAsynchronousInScope(const parser::Block &);1353 1354private:1355  // R1105 selector -> expr | variable1356  // expr is set in either case unless there were errors1357  struct Selector {1358    Selector() {}1359    Selector(const SourceName &source, MaybeExpr &&expr)1360        : source{source}, expr{std::move(expr)} {}1361    operator bool() const { return expr.has_value(); }1362    parser::CharBlock source;1363    MaybeExpr expr;1364  };1365  // association -> [associate-name =>] selector1366  struct Association {1367    const parser::Name *name{nullptr};1368    Selector selector;1369  };1370  std::vector<Association> associationStack_;1371  Association *currentAssociation_{nullptr};1372 1373  template <typename T> bool CheckDef(const T &t) {1374    return CheckDef(std::get<std::optional<parser::Name>>(t));1375  }1376  template <typename T> void CheckRef(const T &t) {1377    CheckRef(std::get<std::optional<parser::Name>>(t));1378  }1379  bool CheckDef(const std::optional<parser::Name> &);1380  void CheckRef(const std::optional<parser::Name> &);1381  const DeclTypeSpec &ToDeclTypeSpec(evaluate::DynamicType &&);1382  const DeclTypeSpec &ToDeclTypeSpec(1383      evaluate::DynamicType &&, MaybeSubscriptIntExpr &&length);1384  Symbol *MakeAssocEntity();1385  void SetTypeFromAssociation(Symbol &);1386  void SetAttrsFromAssociation(Symbol &);1387  Selector ResolveSelector(const parser::Selector &);1388  void ResolveIndexName(const parser::ConcurrentControl &control);1389  void SetCurrentAssociation(std::size_t n);1390  Association &GetCurrentAssociation();1391  void PushAssociation();1392  void PopAssociation(std::size_t count = 1);1393};1394 1395// Create scopes for OpenACC constructs1396class AccVisitor : public virtual DeclarationVisitor {1397public:1398  explicit AccVisitor(SemanticsContext &context) : context_{context} {}1399 1400  void AddAccSourceRange(const parser::CharBlock &);1401 1402  static bool NeedsScope(const parser::OpenACCBlockConstruct &);1403 1404  bool Pre(const parser::OpenACCBlockConstruct &);1405  void Post(const parser::OpenACCBlockConstruct &);1406  bool Pre(const parser::OpenACCCombinedConstruct &);1407  void Post(const parser::OpenACCCombinedConstruct &);1408  bool Pre(const parser::AccClause::UseDevice &x);1409  bool Pre(const parser::AccBeginBlockDirective &x) {1410    AddAccSourceRange(x.source);1411    return true;1412  }1413  void Post(const parser::AccBeginBlockDirective &) {1414    messageHandler().set_currStmtSource(std::nullopt);1415  }1416  bool Pre(const parser::AccEndBlockDirective &x) {1417    AddAccSourceRange(x.source);1418    return true;1419  }1420  void Post(const parser::AccEndBlockDirective &) {1421    messageHandler().set_currStmtSource(std::nullopt);1422  }1423  bool Pre(const parser::AccBeginCombinedDirective &x) {1424    AddAccSourceRange(x.source);1425    return true;1426  }1427  void Post(const parser::AccBeginCombinedDirective &) {1428    messageHandler().set_currStmtSource(std::nullopt);1429  }1430  bool Pre(const parser::AccEndCombinedDirective &x) {1431    AddAccSourceRange(x.source);1432    return true;1433  }1434  void Post(const parser::AccEndCombinedDirective &) {1435    messageHandler().set_currStmtSource(std::nullopt);1436  }1437  bool Pre(const parser::AccBeginLoopDirective &x) {1438    AddAccSourceRange(x.source);1439    return true;1440  }1441  void Post(const parser::AccBeginLoopDirective &x) {1442    messageHandler().set_currStmtSource(std::nullopt);1443  }1444  bool Pre(const parser::OpenACCStandaloneConstruct &x) {1445    currScope().AddSourceRange(x.source);1446    return true;1447  }1448  bool Pre(const parser::OpenACCCacheConstruct &x) {1449    currScope().AddSourceRange(x.source);1450    return true;1451  }1452  bool Pre(const parser::OpenACCWaitConstruct &x) {1453    currScope().AddSourceRange(x.source);1454    return true;1455  }1456  bool Pre(const parser::OpenACCAtomicConstruct &x) {1457    currScope().AddSourceRange(x.source);1458    return true;1459  }1460  bool Pre(const parser::OpenACCEndConstruct &x) {1461    currScope().AddSourceRange(x.source);1462    return true;1463  }1464  bool Pre(const parser::OpenACCDeclarativeConstruct &x) {1465    currScope().AddSourceRange(x.source);1466    return true;1467  }1468 1469  void CopySymbolWithDevice(const parser::Name *name);1470 1471private:1472  SemanticsContext &context_;1473};1474 1475bool AccVisitor::NeedsScope(const parser::OpenACCBlockConstruct &x) {1476  const auto &beginBlockDir{std::get<parser::AccBeginBlockDirective>(x.t)};1477  const auto &beginDir{std::get<parser::AccBlockDirective>(beginBlockDir.t)};1478  switch (beginDir.v) {1479  case llvm::acc::Directive::ACCD_data:1480  case llvm::acc::Directive::ACCD_host_data:1481  case llvm::acc::Directive::ACCD_kernels:1482  case llvm::acc::Directive::ACCD_parallel:1483  case llvm::acc::Directive::ACCD_serial:1484    return true;1485  default:1486    return false;1487  }1488}1489 1490void AccVisitor::AddAccSourceRange(const parser::CharBlock &source) {1491  messageHandler().set_currStmtSource(source);1492  currScope().AddSourceRange(source);1493}1494 1495bool AccVisitor::Pre(const parser::OpenACCBlockConstruct &x) {1496  if (NeedsScope(x)) {1497    PushScope(Scope::Kind::OpenACCConstruct, nullptr);1498  }1499  return true;1500}1501 1502void AccVisitor::CopySymbolWithDevice(const parser::Name *name) {1503  // When CUDA Fortran is enabled together with OpenACC, new1504  // symbols are created for the one appearing in the use_device1505  // clause. These new symbols have the CUDA Fortran device1506  // attribute.1507  if (context_.languageFeatures().IsEnabled(common::LanguageFeature::CUDA) &&1508      name->symbol) {1509    name->symbol = currScope().CopySymbol(*name->symbol);1510    if (auto *object{name->symbol->detailsIf<ObjectEntityDetails>()}) {1511      object->set_cudaDataAttr(common::CUDADataAttr::Device);1512    }1513  }1514}1515 1516bool AccVisitor::Pre(const parser::AccClause::UseDevice &x) {1517  for (const auto &accObject : x.v.v) {1518    Walk(accObject);1519    common::visit(1520        common::visitors{1521            [&](const parser::Designator &designator) {1522              if (const auto *name{1523                      parser::GetDesignatorNameIfDataRef(designator)}) {1524                CopySymbolWithDevice(name);1525              } else {1526                if (const auto *dataRef{1527                        std::get_if<parser::DataRef>(&designator.u)}) {1528                  using ElementIndirection =1529                      common::Indirection<parser::ArrayElement>;1530                  if (auto *ind{std::get_if<ElementIndirection>(&dataRef->u)}) {1531                    const parser::ArrayElement &arrayElement{ind->value()};1532                    const parser::DataRef &base{arrayElement.base};1533                    if (auto *name{std::get_if<parser::Name>(&base.u)}) {1534                      CopySymbolWithDevice(name);1535                    }1536                  }1537                }1538              }1539            },1540            [&](const parser::Name &name) {1541              // TODO: common block in use_device?1542            },1543        },1544        accObject.u);1545  }1546  return false;1547}1548 1549void AccVisitor::Post(const parser::OpenACCBlockConstruct &x) {1550  if (NeedsScope(x)) {1551    PopScope();1552  }1553}1554 1555bool AccVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {1556  PushScope(Scope::Kind::OpenACCConstruct, nullptr);1557  currScope().AddSourceRange(x.source);1558  return true;1559}1560 1561void AccVisitor::Post(const parser::OpenACCCombinedConstruct &x) { PopScope(); }1562 1563// Create scopes for OpenMP constructs1564class OmpVisitor : public virtual DeclarationVisitor {1565public:1566  void AddOmpSourceRange(const parser::CharBlock &);1567 1568  static bool NeedsScope(const parser::OmpBlockConstruct &);1569  static bool NeedsScope(const parser::OmpClause &);1570 1571  bool Pre(const parser::OpenMPRequiresConstruct &x) {1572    AddOmpSourceRange(x.source);1573    return true;1574  }1575  bool Pre(const parser::OmpBlockConstruct &);1576  void Post(const parser::OmpBlockConstruct &);1577  bool Pre(const parser::OmpBeginDirective &x) {1578    return Pre(static_cast<const parser::OmpDirectiveSpecification &>(x));1579  }1580  void Post(const parser::OmpBeginDirective &x) {1581    Post(static_cast<const parser::OmpDirectiveSpecification &>(x));1582  }1583  bool Pre(const parser::OmpEndDirective &x) {1584    return Pre(static_cast<const parser::OmpDirectiveSpecification &>(x));1585  }1586  void Post(const parser::OmpEndDirective &x) {1587    Post(static_cast<const parser::OmpDirectiveSpecification &>(x));1588  }1589 1590  bool Pre(const parser::OpenMPLoopConstruct &) {1591    PushScope(Scope::Kind::OtherConstruct, nullptr);1592    return true;1593  }1594  void Post(const parser::OpenMPLoopConstruct &) { PopScope(); }1595  bool Pre(const parser::OmpBeginLoopDirective &x) {1596    return Pre(static_cast<const parser::OmpDirectiveSpecification &>(x));1597  }1598  void Post(const parser::OmpBeginLoopDirective &x) {1599    Post(static_cast<const parser::OmpDirectiveSpecification &>(x));1600  }1601  bool Pre(const parser::OmpEndLoopDirective &x) {1602    return Pre(static_cast<const parser::OmpDirectiveSpecification &>(x));1603  }1604  void Post(const parser::OmpEndLoopDirective &x) {1605    Post(static_cast<const parser::OmpDirectiveSpecification &>(x));1606  }1607 1608  void Post(const parser::OmpTypeName &);1609  bool Pre(const parser::OmpStylizedDeclaration &);1610  void Post(const parser::OmpStylizedDeclaration &);1611  bool Pre(const parser::OmpStylizedInstance &);1612  void Post(const parser::OmpStylizedInstance &);1613 1614  bool Pre(const parser::OpenMPDeclareMapperConstruct &x) {1615    AddOmpSourceRange(x.source);1616    return true;1617  }1618 1619  bool Pre(const parser::OpenMPDeclareSimdConstruct &x) {1620    AddOmpSourceRange(x.source);1621    return true;1622  }1623 1624  bool Pre(const parser::OmpDeclareVariantDirective &x) {1625    AddOmpSourceRange(x.source);1626    return true;1627  }1628 1629  bool Pre(const parser::OpenMPDeclareReductionConstruct &x) {1630    AddOmpSourceRange(x.source);1631    return true;1632  }1633  bool Pre(const parser::OmpMapClause &);1634 1635  bool Pre(const parser::OpenMPSectionsConstruct &) {1636    PushScope(Scope::Kind::OtherConstruct, nullptr);1637    return true;1638  }1639  void Post(const parser::OpenMPSectionsConstruct &) { PopScope(); }1640  bool Pre(const parser::OmpBeginSectionsDirective &x) {1641    return Pre(static_cast<const parser::OmpDirectiveSpecification &>(x));1642  }1643  void Post(const parser::OmpBeginSectionsDirective &x) {1644    Post(static_cast<const parser::OmpDirectiveSpecification &>(x));1645  }1646  bool Pre(const parser::OmpEndSectionsDirective &x) {1647    return Pre(static_cast<const parser::OmpDirectiveSpecification &>(x));1648  }1649  void Post(const parser::OmpEndSectionsDirective &x) {1650    Post(static_cast<const parser::OmpDirectiveSpecification &>(x));1651  }1652  bool Pre(const parser::OpenMPThreadprivate &) {1653    SkipImplicitTyping(true);1654    return true;1655  }1656  void Post(const parser::OpenMPThreadprivate &) { SkipImplicitTyping(false); }1657  bool Pre(const parser::OpenMPDeclareTargetConstruct &x) {1658    auto addObjectName{[&](const parser::OmpObject &object) {1659      common::visit(1660          common::visitors{1661              [&](const parser::Designator &designator) {1662                if (const auto *name{1663                        parser::GetDesignatorNameIfDataRef(designator)}) {1664                  specPartState_.declareTargetNames.insert(name->source);1665                }1666              },1667              [&](const parser::Name &name) {1668                specPartState_.declareTargetNames.insert(name.source);1669              },1670              [&](const parser::OmpObject::Invalid &invalid) {1671                switch (invalid.v) {1672                  SWITCH_COVERS_ALL_CASES1673                case parser::OmpObject::Invalid::Kind::BlankCommonBlock:1674                  context().Say(invalid.source,1675                      "Blank common blocks are not allowed as directive or clause arguments"_err_en_US);1676                  break;1677                }1678              },1679          },1680          object.u);1681    }};1682 1683    for (const parser::OmpArgument &arg : x.v.Arguments().v) {1684      if (auto *object{omp::GetArgumentObject(arg)}) {1685        addObjectName(*object);1686      }1687    }1688 1689    for (const parser::OmpClause &clause : x.v.Clauses().v) {1690      if (auto *objects{parser::omp::GetOmpObjectList(clause)}) {1691        for (const parser::OmpObject &object : objects->v) {1692          addObjectName(object);1693        }1694      }1695    }1696 1697    SkipImplicitTyping(true);1698    return true;1699  }1700  void Post(const parser::OpenMPDeclareTargetConstruct &) {1701    SkipImplicitTyping(false);1702  }1703  bool Pre(const parser::OmpAllocateDirective &x) {1704    AddOmpSourceRange(x.source);1705    SkipImplicitTyping(true);1706    return true;1707  }1708  void Post(const parser::OmpAllocateDirective &) {1709    SkipImplicitTyping(false);1710    messageHandler().set_currStmtSource(std::nullopt);1711  }1712  bool Pre(const parser::OpenMPDeclarativeConstruct &x) {1713    AddOmpSourceRange(x.source);1714    // Without skipping implicit typing, declarative constructs1715    // can implicitly declare variables instead of only using the1716    // ones already declared in the Fortran sources.1717    SkipImplicitTyping(true);1718    declaratives_.push_back(&x);1719    return true;1720  }1721  void Post(const parser::OpenMPDeclarativeConstruct &) {1722    declaratives_.pop_back();1723    SkipImplicitTyping(false);1724    messageHandler().set_currStmtSource(std::nullopt);1725  }1726  bool Pre(const parser::OpenMPDepobjConstruct &x) {1727    AddOmpSourceRange(x.source);1728    return true;1729  }1730  void Post(const parser::OpenMPDepobjConstruct &x) {1731    messageHandler().set_currStmtSource(std::nullopt);1732  }1733  bool Pre(const parser::OpenMPAtomicConstruct &x) {1734    AddOmpSourceRange(x.source);1735    return true;1736  }1737  void Post(const parser::OpenMPAtomicConstruct &) {1738    messageHandler().set_currStmtSource(std::nullopt);1739  }1740  bool Pre(const parser::OmpClause &x) {1741    if (NeedsScope(x)) {1742      PushScope(Scope::Kind::OtherClause, nullptr);1743    }1744    return true;1745  }1746  void Post(const parser::OmpClause &x) {1747    if (NeedsScope(x)) {1748      PopScope();1749    }1750  }1751 1752  // These objects are handled explicitly, and the AST traversal should not1753  // reach a point where it calls the Pre functions for them.1754  bool Pre(const parser::OmpMapperSpecifier &x) {1755    llvm_unreachable("This function should not be reached by AST traversal");1756  }1757  bool Pre(const parser::OmpReductionSpecifier &x) {1758    llvm_unreachable("This function should not be reached by AST traversal");1759  }1760  bool Pre(const parser::OmpBaseVariantNames &x) {1761    llvm_unreachable("This function should not be reached by AST traversal");1762  }1763 1764  bool Pre(const parser::OmpDirectiveSpecification &x);1765  void Post(const parser::OmpDirectiveSpecification &) {1766    messageHandler().set_currStmtSource(std::nullopt);1767  }1768 1769  bool Pre(const parser::OpenMPConstruct &x) {1770    // Indicate that the current directive is not a declarative one.1771    declaratives_.push_back(nullptr);1772    return true;1773  }1774  void Post(const parser::OpenMPConstruct &) {1775    // Pop the null pointer.1776    declaratives_.pop_back();1777  }1778 1779private:1780  void ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,1781      const parser::OmpClauseList &clauses);1782  void ProcessReductionSpecifier(const parser::OmpReductionSpecifier &spec,1783      const parser::OmpClauseList &clauses);1784 1785  void ResolveCriticalName(const parser::OmpArgument &arg);1786 1787  std::vector<const parser::OpenMPDeclarativeConstruct *> declaratives_;1788};1789 1790bool OmpVisitor::NeedsScope(const parser::OmpBlockConstruct &x) {1791  switch (x.BeginDir().DirId()) {1792  case llvm::omp::Directive::OMPD_master:1793  case llvm::omp::Directive::OMPD_ordered:1794    return false;1795  default:1796    return true;1797  }1798}1799 1800bool OmpVisitor::NeedsScope(const parser::OmpClause &x) {1801  // Iterators contain declarations, whose scope extends until the end1802  // the clause.1803  return llvm::omp::canHaveIterator(x.Id());1804}1805 1806void OmpVisitor::AddOmpSourceRange(const parser::CharBlock &source) {1807  messageHandler().set_currStmtSource(source);1808  currScope().AddSourceRange(source);1809}1810 1811bool OmpVisitor::Pre(const parser::OmpBlockConstruct &x) {1812  if (NeedsScope(x)) {1813    PushScope(Scope::Kind::OtherConstruct, nullptr);1814  }1815  return true;1816}1817 1818void OmpVisitor::Post(const parser::OmpBlockConstruct &x) {1819  if (NeedsScope(x)) {1820    PopScope();1821  }1822}1823 1824void OmpVisitor::Post(const parser::OmpTypeName &x) {1825  x.declTypeSpec = GetDeclTypeSpec();1826}1827 1828bool OmpVisitor::Pre(const parser::OmpStylizedDeclaration &x) {1829  BeginDecl();1830  Walk(x.type.get());1831  Walk(x.var);1832  return true;1833}1834 1835void OmpVisitor::Post(const parser::OmpStylizedDeclaration &x) { //1836  EndDecl();1837}1838 1839bool OmpVisitor::Pre(const parser::OmpStylizedInstance &x) {1840  PushScope(Scope::Kind::OtherConstruct, nullptr);1841  return true;1842}1843 1844void OmpVisitor::Post(const parser::OmpStylizedInstance &x) { //1845  PopScope();1846}1847 1848bool OmpVisitor::Pre(const parser::OmpMapClause &x) {1849  auto &mods{OmpGetModifiers(x)};1850  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {1851    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {1852      // TODO: Do we need a specific flag or type here, to distinghuish against1853      // other ConstructName things? Leaving this for the full implementation1854      // of mapper lowering.1855      auto &ultimate{symbol->GetUltimate()};1856      auto *misc{ultimate.detailsIf<MiscDetails>()};1857      auto *md{ultimate.detailsIf<MapperDetails>()};1858      if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))1859        context().Say(mapper->v.source,1860            "Name '%s' should be a mapper name"_err_en_US, mapper->v.source);1861      else1862        mapper->v.symbol = symbol;1863    } else {1864      // Allow the special 'default' mapper identifier without prior1865      // declaration so lowering can recognize and handle it. Emit an1866      // error for any other missing mapper identifier.1867      if (mapper->v.source.ToString() == "default") {1868        mapper->v.symbol = &MakeSymbol(1869            mapper->v, MiscDetails{MiscDetails::Kind::ConstructName});1870      } else {1871        context().Say(1872            mapper->v.source, "'%s' not declared"_err_en_US, mapper->v.source);1873      }1874    }1875  }1876  return true;1877}1878 1879void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,1880    const parser::OmpClauseList &clauses) {1881  // This "manually" walks the tree of the construct, because we need1882  // to resolve the type before the map clauses are processed - when1883  // just following the natural flow, the map clauses gets processed before1884  // the type has been fully processed.1885  BeginDeclTypeSpec();1886  auto &mapperName{std::get<std::string>(spec.t)};1887  // Create or update the mapper symbol with MapperDetails and1888  // keep track of the declarative construct for module emission.1889  SourceName mapperSource{context().SaveTempName(std::string{mapperName})};1890  Symbol &mapperSym{MakeSymbol(mapperSource, Attrs{})};1891  if (!mapperSym.detailsIf<MapperDetails>()) {1892    mapperSym.set_details(MapperDetails{});1893  }1894  if (!context().langOptions().OpenMPSimd) {1895    mapperSym.get<MapperDetails>().AddDecl(declaratives_.back());1896  }1897  PushScope(Scope::Kind::OtherConstruct, nullptr);1898  Walk(std::get<parser::TypeSpec>(spec.t));1899  auto &varName{std::get<parser::Name>(spec.t)};1900  DeclareObjectEntity(varName);1901  EndDeclTypeSpec();1902 1903  Walk(clauses);1904  PopScope();1905}1906 1907parser::CharBlock MakeNameFromOperator(1908    const parser::DefinedOperator::IntrinsicOperator &op,1909    SemanticsContext &context) {1910  switch (op) {1911  case parser::DefinedOperator::IntrinsicOperator::Multiply:1912    return parser::CharBlock{"op.*", 4};1913  case parser::DefinedOperator::IntrinsicOperator::Add:1914    return parser::CharBlock{"op.+", 4};1915  case parser::DefinedOperator::IntrinsicOperator::Subtract:1916    return parser::CharBlock{"op.-", 4};1917 1918  case parser::DefinedOperator::IntrinsicOperator::AND:1919    return parser::CharBlock{"op.AND", 6};1920  case parser::DefinedOperator::IntrinsicOperator::OR:1921    return parser::CharBlock{"op.OR", 6};1922  case parser::DefinedOperator::IntrinsicOperator::EQV:1923    return parser::CharBlock{"op.EQV", 7};1924  case parser::DefinedOperator::IntrinsicOperator::NEQV:1925    return parser::CharBlock{"op.NEQV", 8};1926 1927  default:1928    context.Say("Unsupported operator in DECLARE REDUCTION"_err_en_US);1929    return parser::CharBlock{"op.?", 4};1930  }1931}1932 1933parser::CharBlock MangleSpecialFunctions(const parser::CharBlock &name) {1934  return llvm::StringSwitch<parser::CharBlock>(name.ToString())1935      .Case("max", {"op.max", 6})1936      .Case("min", {"op.min", 6})1937      .Case("iand", {"op.iand", 7})1938      .Case("ior", {"op.ior", 6})1939      .Case("ieor", {"op.ieor", 7})1940      .Default(name);1941}1942 1943std::string MangleDefinedOperator(const parser::CharBlock &name) {1944  CHECK(name[0] == '.' && name[name.size() - 1] == '.');1945  return "op" + name.ToString();1946}1947 1948void OmpVisitor::ProcessReductionSpecifier(1949    const parser::OmpReductionSpecifier &spec,1950    const parser::OmpClauseList &clauses) {1951  const parser::Name *name{nullptr};1952  parser::CharBlock mangledName;1953  UserReductionDetails reductionDetailsTemp;1954  const auto &id{std::get<parser::OmpReductionIdentifier>(spec.t)};1955  if (auto *procDes{std::get_if<parser::ProcedureDesignator>(&id.u)}) {1956    name = std::get_if<parser::Name>(&procDes->u);1957    // This shouldn't be a procedure component: this is the name of the1958    // reduction being declared.1959    CHECK(name);1960    // Prevent the symbol from conflicting with the builtin function name1961    mangledName = MangleSpecialFunctions(name->source);1962    // Note: the Name inside the parse tree is not updated because it is const.1963    // All lookups must use MangleSpecialFunctions.1964  } else {1965    const auto &defOp{std::get<parser::DefinedOperator>(id.u)};1966    if (const auto *definedOp{std::get_if<parser::DefinedOpName>(&defOp.u)}) {1967      name = &definedOp->v;1968      mangledName = context().SaveTempName(MangleDefinedOperator(name->source));1969    } else {1970      mangledName = MakeNameFromOperator(1971          std::get<parser::DefinedOperator::IntrinsicOperator>(defOp.u),1972          context());1973    }1974  }1975 1976  // Use reductionDetailsTemp if we can't find the symbol (this is1977  // the first, or only, instance with this name). The details then1978  // gets stored in the symbol when it's created.1979  UserReductionDetails *reductionDetails{&reductionDetailsTemp};1980  Symbol *symbol{currScope().FindSymbol(mangledName)};1981  if (symbol) {1982    // If we found a symbol, we append the type info to the1983    // existing reductionDetails.1984    reductionDetails = symbol->detailsIf<UserReductionDetails>();1985 1986    if (!reductionDetails) {1987      context().Say(1988          "Duplicate definition of '%s' in DECLARE REDUCTION"_err_en_US,1989          mangledName);1990      return;1991    }1992  }1993 1994  reductionDetails->AddDecl(declaratives_.back());1995 1996  // Do not walk OmpTypeNameList. The types on the list will be visited1997  // during procesing of OmpCombinerExpression.1998  Walk(std::get<std::optional<parser::OmpCombinerExpression>>(spec.t));1999  Walk(clauses);2000 2001  for (auto &type : std::get<parser::OmpTypeNameList>(spec.t).v) {2002    // The declTypeSpec can be null if there is some semantic error.2003    if (type.declTypeSpec) {2004      reductionDetails->AddType(*type.declTypeSpec);2005    }2006  }2007 2008  if (!symbol) {2009    symbol = &MakeSymbol(mangledName, Attrs{}, std::move(*reductionDetails));2010  }2011  if (name) {2012    name->symbol = symbol;2013  }2014}2015 2016void OmpVisitor::ResolveCriticalName(const parser::OmpArgument &arg) {2017  auto &globalScope{[&]() -> Scope & {2018    for (Scope *s{&currScope()};; s = &s->parent()) {2019      if (s->IsTopLevel()) {2020        return *s;2021      }2022    }2023    llvm_unreachable("Cannot find global scope");2024  }()};2025 2026  if (auto *object{parser::Unwrap<parser::OmpObject>(arg.u)}) {2027    if (auto *desg{omp::GetDesignatorFromObj(*object)}) {2028      if (auto *name{parser::GetDesignatorNameIfDataRef(*desg)}) {2029        if (auto *symbol{FindInScope(globalScope, *name)}) {2030          if (!symbol->test(Symbol::Flag::OmpCriticalLock)) {2031            SayWithDecl(*name, *symbol,2032                "CRITICAL construct name '%s' conflicts with a previous declaration"_warn_en_US,2033                name->ToString());2034          }2035        } else {2036          name->symbol = &MakeSymbol(globalScope, name->source, Attrs{});2037          name->symbol->set(Symbol::Flag::OmpCriticalLock);2038        }2039      }2040    }2041  }2042}2043 2044bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) {2045  AddOmpSourceRange(x.source);2046 2047  const parser::OmpArgumentList &args{x.Arguments()};2048  const parser::OmpClauseList &clauses{x.Clauses()};2049  bool visitClauses{true};2050 2051  for (const parser::OmpArgument &arg : args.v) {2052    common::visit( //2053        common::visitors{2054            [&](const parser::OmpMapperSpecifier &spec) {2055              ProcessMapperSpecifier(spec, clauses);2056              visitClauses = false;2057            },2058            [&](const parser::OmpReductionSpecifier &spec) {2059              ProcessReductionSpecifier(spec, clauses);2060              visitClauses = false;2061            },2062            [&](const parser::OmpBaseVariantNames &names) {2063              Walk(std::get<0>(names.t));2064              Walk(std::get<1>(names.t));2065            },2066            [&](const parser::OmpLocator &locator) {2067              // Manually resolve names in CRITICAL directives. This is because2068              // these names do not denote Fortran objects, and the CRITICAL2069              // directive causes them to be "auto-declared", i.e. inserted into2070              // the global scope. More specifically, they are not expected to2071              // have explicit declarations, and if they do the behavior is2072              // unspeficied.2073              if (x.DirId() == llvm::omp::Directive::OMPD_critical) {2074                ResolveCriticalName(arg);2075              } else {2076                Walk(locator);2077              }2078            },2079        },2080        arg.u);2081  }2082 2083  if (visitClauses) {2084    Walk(clauses);2085  }2086 2087  return false;2088}2089 2090// Walk the parse tree and resolve names to symbols.2091class ResolveNamesVisitor : public virtual ScopeHandler,2092                            public ModuleVisitor,2093                            public SubprogramVisitor,2094                            public ConstructVisitor,2095                            public OmpVisitor,2096                            public AccVisitor {2097public:2098  using AccVisitor::Post;2099  using AccVisitor::Pre;2100  using ArraySpecVisitor::Post;2101  using ConstructVisitor::Post;2102  using ConstructVisitor::Pre;2103  using DeclarationVisitor::Post;2104  using DeclarationVisitor::Pre;2105  using ImplicitRulesVisitor::Post;2106  using ImplicitRulesVisitor::Pre;2107  using InterfaceVisitor::Post;2108  using InterfaceVisitor::Pre;2109  using ModuleVisitor::Post;2110  using ModuleVisitor::Pre;2111  using OmpVisitor::Post;2112  using OmpVisitor::Pre;2113  using ScopeHandler::Post;2114  using ScopeHandler::Pre;2115  using SubprogramVisitor::Post;2116  using SubprogramVisitor::Pre;2117 2118  ResolveNamesVisitor(2119      SemanticsContext &context, ImplicitRulesMap &rules, Scope &top)2120      : BaseVisitor{context, *this, rules}, AccVisitor(context),2121        topScope_{top} {2122    PushScope(top);2123  }2124 2125  Scope &topScope() const { return topScope_; }2126 2127  // Default action for a parse tree node is to visit children.2128  template <typename T> bool Pre(const T &) { return true; }2129  template <typename T> void Post(const T &) {}2130 2131  bool Pre(const parser::SpecificationPart &);2132  bool Pre(const parser::Program &);2133  void Post(const parser::Program &);2134  bool Pre(const parser::ImplicitStmt &);2135  void Post(const parser::PointerObject &);2136  void Post(const parser::AllocateObject &);2137  bool Pre(const parser::PointerAssignmentStmt &);2138  void Post(const parser::Designator &);2139  void Post(const parser::SubstringInquiry &);2140  template <typename A, typename B>2141  void Post(const parser::LoopBounds<A, B> &x) {2142    ResolveName(parser::UnwrapRef<parser::Name>(x.name));2143  }2144  void Post(const parser::ProcComponentRef &);2145  bool Pre(const parser::FunctionReference &);2146  bool Pre(const parser::CallStmt &);2147  bool Pre(const parser::ImportStmt &);2148  void Post(const parser::TypeGuardStmt &);2149  bool Pre(const parser::StmtFunctionStmt &);2150  bool Pre(const parser::DefinedOpName &);2151  bool Pre(const parser::ProgramUnit &);2152  void Post(const parser::AssignStmt &);2153  void Post(const parser::AssignedGotoStmt &);2154  void Post(const parser::CompilerDirective &);2155 2156  // These nodes should never be reached: they are handled in ProgramUnit2157  bool Pre(const parser::MainProgram &) {2158    llvm_unreachable("This node is handled in ProgramUnit");2159  }2160  bool Pre(const parser::FunctionSubprogram &) {2161    llvm_unreachable("This node is handled in ProgramUnit");2162  }2163  bool Pre(const parser::SubroutineSubprogram &) {2164    llvm_unreachable("This node is handled in ProgramUnit");2165  }2166  bool Pre(const parser::SeparateModuleSubprogram &) {2167    llvm_unreachable("This node is handled in ProgramUnit");2168  }2169  bool Pre(const parser::Module &) {2170    llvm_unreachable("This node is handled in ProgramUnit");2171  }2172  bool Pre(const parser::Submodule &) {2173    llvm_unreachable("This node is handled in ProgramUnit");2174  }2175  bool Pre(const parser::BlockData &) {2176    llvm_unreachable("This node is handled in ProgramUnit");2177  }2178 2179  void NoteExecutablePartCall(Symbol::Flag, SourceName, bool hasCUDAChevrons);2180 2181  friend void ResolveSpecificationParts(SemanticsContext &, const Symbol &);2182 2183private:2184  // Kind of procedure we are expecting to see in a ProcedureDesignator2185  std::optional<Symbol::Flag> expectedProcFlag_;2186  std::optional<SourceName> prevImportStmt_;2187  Scope &topScope_;2188 2189  void PreSpecificationConstruct(const parser::SpecificationConstruct &);2190  void EarlyDummyTypeDeclaration(2191      const parser::Statement<common::Indirection<parser::TypeDeclarationStmt>>2192          &);2193  void CreateCommonBlockSymbols(const parser::CommonStmt &);2194  void CreateObjectSymbols(const std::list<parser::ObjectDecl> &, Attr);2195  void CreateGeneric(const parser::GenericSpec &);2196  void FinishSpecificationPart(const std::list<parser::DeclarationConstruct> &);2197  void AnalyzeStmtFunctionStmt(const parser::StmtFunctionStmt &);2198  void CheckImports();2199  void CheckImport(const SourceName &, const SourceName &);2200  void HandleCall(Symbol::Flag, const parser::Call &);2201  void HandleProcedureName(Symbol::Flag, const parser::Name &);2202  bool CheckImplicitNoneExternal(const SourceName &, const Symbol &);2203  bool SetProcFlag(const parser::Name &, Symbol &, Symbol::Flag);2204  void ResolveSpecificationParts(ProgramTree &);2205  void AddSubpNames(ProgramTree &);2206  bool BeginScopeForNode(const ProgramTree &);2207  void EndScopeForNode(const ProgramTree &);2208  void FinishSpecificationParts(const ProgramTree &);2209  void FinishExecutionParts(const ProgramTree &);2210  void FinishDerivedTypeInstantiation(Scope &);2211  void ResolveExecutionParts(const ProgramTree &);2212  void UseCUDABuiltinNames();2213  void HandleDerivedTypesInImplicitStmts(const parser::ImplicitPart &,2214      const std::list<parser::DeclarationConstruct> &);2215};2216 2217// ImplicitRules implementation2218 2219bool ImplicitRules::isImplicitNoneType() const {2220  if (isImplicitNoneType_) {2221    return true;2222  } else if (map_.empty() && inheritFromParent_) {2223    return parent_->isImplicitNoneType();2224  } else {2225    return false; // default if not specified2226  }2227}2228 2229bool ImplicitRules::isImplicitNoneExternal() const {2230  if (isImplicitNoneExternal_) {2231    return true;2232  } else if (inheritFromParent_) {2233    return parent_->isImplicitNoneExternal();2234  } else {2235    return false; // default if not specified2236  }2237}2238 2239const DeclTypeSpec *ImplicitRules::GetType(2240    SourceName name, bool respectImplicitNoneType) const {2241  char ch{name.front()};2242  if (isImplicitNoneType_ && respectImplicitNoneType) {2243    return nullptr;2244  } else if (auto it{map_.find(ch)}; it != map_.end()) {2245    return &*it->second;2246  } else if (inheritFromParent_) {2247    return parent_->GetType(name, respectImplicitNoneType);2248  } else if (ch >= 'i' && ch <= 'n') {2249    return &context_.MakeNumericType(TypeCategory::Integer);2250  } else if (ch >= 'a' && ch <= 'z') {2251    return &context_.MakeNumericType(TypeCategory::Real);2252  } else {2253    return nullptr;2254  }2255}2256 2257void ImplicitRules::SetTypeMapping(const DeclTypeSpec &type,2258    parser::Location fromLetter, parser::Location toLetter) {2259  for (char ch = *fromLetter; ch; ch = ImplicitRules::Incr(ch)) {2260    auto res{map_.emplace(ch, type)};2261    if (!res.second) {2262      context_.Say(parser::CharBlock{fromLetter},2263          "More than one implicit type specified for '%c'"_err_en_US, ch);2264    }2265    if (ch == *toLetter) {2266      break;2267    }2268  }2269}2270 2271// Return the next char after ch in a way that works for ASCII or EBCDIC.2272// Return '\0' for the char after 'z'.2273char ImplicitRules::Incr(char ch) {2274  switch (ch) {2275  case 'i':2276    return 'j';2277  case 'r':2278    return 's';2279  case 'z':2280    return '\0';2281  default:2282    return ch + 1;2283  }2284}2285 2286llvm::raw_ostream &operator<<(2287    llvm::raw_ostream &o, const ImplicitRules &implicitRules) {2288  o << "ImplicitRules:\n";2289  for (char ch = 'a'; ch; ch = ImplicitRules::Incr(ch)) {2290    ShowImplicitRule(o, implicitRules, ch);2291  }2292  ShowImplicitRule(o, implicitRules, '_');2293  ShowImplicitRule(o, implicitRules, '$');2294  ShowImplicitRule(o, implicitRules, '@');2295  return o;2296}2297void ShowImplicitRule(2298    llvm::raw_ostream &o, const ImplicitRules &implicitRules, char ch) {2299  auto it{implicitRules.map_.find(ch)};2300  if (it != implicitRules.map_.end()) {2301    o << "  " << ch << ": " << *it->second << '\n';2302  }2303}2304 2305template <typename T> void BaseVisitor::Walk(const T &x) {2306  parser::Walk(x, *this_);2307}2308 2309void BaseVisitor::MakePlaceholder(2310    const parser::Name &name, MiscDetails::Kind kind) {2311  if (!name.symbol) {2312    name.symbol = &context_->globalScope().MakeSymbol(2313        name.source, Attrs{}, MiscDetails{kind});2314  }2315}2316 2317// AttrsVisitor implementation2318 2319bool AttrsVisitor::BeginAttrs() {2320  CHECK(!attrs_ && !cudaDataAttr_);2321  attrs_ = Attrs{};2322  return true;2323}2324Attrs AttrsVisitor::GetAttrs() {2325  CHECK(attrs_);2326  return *attrs_;2327}2328Attrs AttrsVisitor::EndAttrs() {2329  Attrs result{GetAttrs()};2330  attrs_.reset();2331  cudaDataAttr_.reset();2332  passName_ = std::nullopt;2333  bindName_.reset();2334  isCDefined_ = false;2335  return result;2336}2337 2338bool AttrsVisitor::SetPassNameOn(Symbol &symbol) {2339  if (!passName_) {2340    return false;2341  }2342  common::visit(common::visitors{2343                    [&](ProcEntityDetails &x) { x.set_passName(*passName_); },2344                    [&](ProcBindingDetails &x) { x.set_passName(*passName_); },2345                    [](auto &) { common::die("unexpected pass name"); },2346                },2347      symbol.details());2348  return true;2349}2350 2351void AttrsVisitor::SetBindNameOn(Symbol &symbol) {2352  if ((!attrs_ || !attrs_->test(Attr::BIND_C)) &&2353      !symbol.attrs().test(Attr::BIND_C)) {2354    return;2355  }2356  symbol.SetIsCDefined(isCDefined_);2357  std::optional<std::string> label{2358      evaluate::GetScalarConstantValue<evaluate::Ascii>(bindName_)};2359  // 18.9.2(2): discard leading and trailing blanks2360  if (label) {2361    symbol.SetIsExplicitBindName(true);2362    auto first{label->find_first_not_of(" ")};2363    if (first == std::string::npos) {2364      // Empty NAME= means no binding at all (18.10.2p2)2365      return;2366    }2367    auto last{label->find_last_not_of(" ")};2368    label = label->substr(first, last - first + 1);2369  } else if (symbol.GetIsExplicitBindName()) {2370    // don't try to override explicit binding name with default2371    return;2372  } else if (ClassifyProcedure(symbol) == ProcedureDefinitionClass::Internal) {2373    // BIND(C) does not give an implicit binding label to internal procedures.2374    return;2375  } else {2376    label = symbol.name().ToString();2377  }2378  // Checks whether a symbol has two Bind names.2379  std::string oldBindName;2380  if (const auto *bindName{symbol.GetBindName()}) {2381    oldBindName = *bindName;2382  }2383  symbol.SetBindName(std::move(*label));2384  if (!oldBindName.empty()) {2385    if (const std::string * newBindName{symbol.GetBindName()}) {2386      if (oldBindName != *newBindName) {2387        Say(symbol.name(),2388            "The entity '%s' has multiple BIND names ('%s' and '%s')"_err_en_US,2389            symbol.name(), oldBindName, *newBindName);2390      }2391    }2392  }2393}2394 2395void AttrsVisitor::Post(const parser::LanguageBindingSpec &x) {2396  if (CheckAndSet(Attr::BIND_C)) {2397    if (const auto &name{2398            std::get<std::optional<parser::ScalarDefaultCharConstantExpr>>(2399                x.t)}) {2400      bindName_ = EvaluateExpr(*name);2401    }2402    isCDefined_ = std::get<bool>(x.t);2403  }2404}2405bool AttrsVisitor::Pre(const parser::IntentSpec &x) {2406  CheckAndSet(IntentSpecToAttr(x));2407  return false;2408}2409bool AttrsVisitor::Pre(const parser::Pass &x) {2410  if (CheckAndSet(Attr::PASS)) {2411    if (x.v) {2412      passName_ = x.v->source;2413      MakePlaceholder(*x.v, MiscDetails::Kind::PassName);2414    }2415  }2416  return false;2417}2418 2419// C730, C743, C755, C778, C1543 say no attribute or prefix repetitions2420bool AttrsVisitor::IsDuplicateAttr(Attr attrName) {2421  CHECK(attrs_);2422  if (attrs_->test(attrName)) {2423    context().Warn(common::LanguageFeature::RedundantAttribute,2424        currStmtSource().value(),2425        "Attribute '%s' cannot be used more than once"_warn_en_US,2426        AttrToString(attrName));2427    return true;2428  }2429  return false;2430}2431 2432// See if attrName violates a constraint cause by a conflict.  attr1 and attr22433// name attributes that cannot be used on the same declaration2434bool AttrsVisitor::HaveAttrConflict(Attr attrName, Attr attr1, Attr attr2) {2435  CHECK(attrs_);2436  if ((attrName == attr1 && attrs_->test(attr2)) ||2437      (attrName == attr2 && attrs_->test(attr1))) {2438    Say(currStmtSource().value(),2439        "Attributes '%s' and '%s' conflict with each other"_err_en_US,2440        AttrToString(attr1), AttrToString(attr2));2441    return true;2442  }2443  return false;2444}2445// C759, C15432446bool AttrsVisitor::IsConflictingAttr(Attr attrName) {2447  return HaveAttrConflict(attrName, Attr::INTENT_IN, Attr::INTENT_INOUT) ||2448      HaveAttrConflict(attrName, Attr::INTENT_IN, Attr::INTENT_OUT) ||2449      HaveAttrConflict(attrName, Attr::INTENT_INOUT, Attr::INTENT_OUT) ||2450      HaveAttrConflict(attrName, Attr::PASS, Attr::NOPASS) || // C7812451      HaveAttrConflict(attrName, Attr::PURE, Attr::IMPURE) ||2452      HaveAttrConflict(attrName, Attr::PUBLIC, Attr::PRIVATE) ||2453      HaveAttrConflict(attrName, Attr::RECURSIVE, Attr::NON_RECURSIVE) ||2454      HaveAttrConflict(attrName, Attr::INTRINSIC, Attr::EXTERNAL);2455}2456bool AttrsVisitor::CheckAndSet(Attr attrName) {2457  if (IsConflictingAttr(attrName) || IsDuplicateAttr(attrName)) {2458    return false;2459  }2460  attrs_->set(attrName);2461  return true;2462}2463bool AttrsVisitor::Pre(const common::CUDADataAttr x) {2464  if (cudaDataAttr_.value_or(x) != x) {2465    Say(currStmtSource().value(),2466        "CUDA data attributes '%s' and '%s' may not both be specified"_err_en_US,2467        common::EnumToString(*cudaDataAttr_), common::EnumToString(x));2468  }2469  cudaDataAttr_ = x;2470  return false;2471}2472 2473// DeclTypeSpecVisitor implementation2474 2475const DeclTypeSpec *DeclTypeSpecVisitor::GetDeclTypeSpec() const {2476  return state_.declTypeSpec;2477}2478const parser::Expr *DeclTypeSpecVisitor::GetOriginalKindParameter() const {2479  return state_.originalKindParameter;2480}2481 2482void DeclTypeSpecVisitor::BeginDeclTypeSpec() {2483  CHECK(!state_.expectDeclTypeSpec);2484  CHECK(!state_.declTypeSpec);2485  state_.expectDeclTypeSpec = true;2486}2487void DeclTypeSpecVisitor::EndDeclTypeSpec() {2488  CHECK(state_.expectDeclTypeSpec);2489  state_ = {};2490}2491 2492void DeclTypeSpecVisitor::SetDeclTypeSpecCategory(2493    DeclTypeSpec::Category category) {2494  CHECK(state_.expectDeclTypeSpec);2495  state_.derived.category = category;2496}2497 2498bool DeclTypeSpecVisitor::Pre(const parser::TypeGuardStmt &) {2499  BeginDeclTypeSpec();2500  return true;2501}2502void DeclTypeSpecVisitor::Post(const parser::TypeGuardStmt &) {2503  EndDeclTypeSpec();2504}2505 2506void DeclTypeSpecVisitor::Post(const parser::TypeSpec &typeSpec) {2507  // Record the resolved DeclTypeSpec in the parse tree for use by2508  // expression semantics if the DeclTypeSpec is a valid TypeSpec.2509  // The grammar ensures that it's an intrinsic or derived type spec,2510  // not TYPE(*) or CLASS(*) or CLASS(T).2511  if (const DeclTypeSpec * spec{state_.declTypeSpec}) {2512    switch (spec->category()) {2513    case DeclTypeSpec::Numeric:2514    case DeclTypeSpec::Logical:2515    case DeclTypeSpec::Character:2516      typeSpec.declTypeSpec = spec;2517      break;2518    case DeclTypeSpec::TypeDerived:2519      if (const DerivedTypeSpec * derived{spec->AsDerived()}) {2520        CheckForAbstractType(derived->typeSymbol()); // C7032521        typeSpec.declTypeSpec = spec;2522      }2523      break;2524    default:2525      CRASH_NO_CASE;2526    }2527  }2528}2529 2530void DeclTypeSpecVisitor::Post(2531    const parser::IntrinsicTypeSpec::DoublePrecision &) {2532  MakeNumericType(TypeCategory::Real, context().doublePrecisionKind());2533}2534void DeclTypeSpecVisitor::Post(2535    const parser::IntrinsicTypeSpec::DoubleComplex &) {2536  MakeNumericType(TypeCategory::Complex, context().doublePrecisionKind());2537}2538void DeclTypeSpecVisitor::MakeNumericType(TypeCategory category, int kind) {2539  SetDeclTypeSpec(context().MakeNumericType(category, kind));2540}2541 2542void DeclTypeSpecVisitor::CheckForAbstractType(const Symbol &typeSymbol) {2543  if (typeSymbol.attrs().test(Attr::ABSTRACT)) {2544    Say("ABSTRACT derived type may not be used here"_err_en_US);2545  }2546}2547 2548void DeclTypeSpecVisitor::Post(const parser::DeclarationTypeSpec::ClassStar &) {2549  SetDeclTypeSpec(context().globalScope().MakeClassStarType());2550}2551void DeclTypeSpecVisitor::Post(const parser::DeclarationTypeSpec::TypeStar &) {2552  SetDeclTypeSpec(context().globalScope().MakeTypeStarType());2553}2554 2555// Check that we're expecting to see a DeclTypeSpec (and haven't seen one yet)2556// and save it in state_.declTypeSpec.2557void DeclTypeSpecVisitor::SetDeclTypeSpec(const DeclTypeSpec &declTypeSpec) {2558  CHECK(state_.expectDeclTypeSpec);2559  CHECK(!state_.declTypeSpec);2560  state_.declTypeSpec = &declTypeSpec;2561}2562 2563KindExpr DeclTypeSpecVisitor::GetKindParamExpr(2564    TypeCategory category, const std::optional<parser::KindSelector> &kind) {2565  if (inPDTDefinition_) {2566    if (category != TypeCategory::Derived && kind) {2567      if (const auto *expr{2568              std::get_if<parser::ScalarIntConstantExpr>(&kind->u)}) {2569        CHECK(!state_.originalKindParameter);2570        // Save a pointer to the KIND= expression in the parse tree2571        // in case we need to reanalyze it during PDT instantiation.2572        state_.originalKindParameter = parser::Unwrap<parser::Expr>(expr);2573      }2574    }2575    // Inhibit some errors now that will be caught later during instantiations.2576    auto restorer{2577        context().foldingContext().AnalyzingPDTComponentKindSelector()};2578    return AnalyzeKindSelector(context(), category, kind);2579  }2580  return AnalyzeKindSelector(context(), category, kind);2581}2582 2583// MessageHandler implementation2584 2585Message &MessageHandler::Say(MessageFixedText &&msg) {2586  return context_->Say(currStmtSource().value(), std::move(msg));2587}2588Message &MessageHandler::Say(MessageFormattedText &&msg) {2589  return context_->Say(currStmtSource().value(), std::move(msg));2590}2591Message &MessageHandler::Say(const SourceName &name, MessageFixedText &&msg) {2592  return Say(name, std::move(msg), name);2593}2594 2595// ImplicitRulesVisitor implementation2596 2597void ImplicitRulesVisitor::Post(const parser::ParameterStmt &) {2598  prevParameterStmt_ = currStmtSource();2599}2600 2601bool ImplicitRulesVisitor::Pre(const parser::ImplicitStmt &x) {2602  bool result{2603      common::visit(common::visitors{2604                        [&](const std::list<ImplicitNoneNameSpec> &y) {2605                          return HandleImplicitNone(y);2606                        },2607                        [&](const std::list<parser::ImplicitSpec> &) {2608                          if (prevImplicitNoneType_) {2609                            Say("IMPLICIT statement after IMPLICIT NONE or "2610                                "IMPLICIT NONE(TYPE) statement"_err_en_US);2611                            return false;2612                          }2613                          implicitRules_->set_isImplicitNoneType(false);2614                          return true;2615                        },2616                    },2617          x.u)};2618  prevImplicit_ = currStmtSource();2619  return result;2620}2621 2622bool ImplicitRulesVisitor::Pre(const parser::LetterSpec &x) {2623  auto loLoc{std::get<parser::Location>(x.t)};2624  auto hiLoc{loLoc};2625  if (auto hiLocOpt{std::get<std::optional<parser::Location>>(x.t)}) {2626    hiLoc = *hiLocOpt;2627    if (*hiLoc < *loLoc) {2628      Say(hiLoc, "'%s' does not follow '%s' alphabetically"_err_en_US,2629          std::string(hiLoc, 1), std::string(loLoc, 1));2630      return false;2631    }2632  }2633  implicitRules_->SetTypeMapping(*GetDeclTypeSpec(), loLoc, hiLoc);2634  return false;2635}2636 2637bool ImplicitRulesVisitor::Pre(const parser::ImplicitSpec &) {2638  BeginDeclTypeSpec();2639  set_allowForwardReferenceToDerivedType(true);2640  return true;2641}2642 2643void ImplicitRulesVisitor::Post(const parser::ImplicitSpec &) {2644  set_allowForwardReferenceToDerivedType(false);2645  EndDeclTypeSpec();2646}2647 2648void ImplicitRulesVisitor::SetScope(const Scope &scope) {2649  implicitRules_ = &DEREF(implicitRulesMap_).at(&scope);2650  prevImplicit_ = std::nullopt;2651  prevImplicitNone_ = std::nullopt;2652  prevImplicitNoneType_ = std::nullopt;2653  prevParameterStmt_ = std::nullopt;2654}2655void ImplicitRulesVisitor::BeginScope(const Scope &scope) {2656  // find or create implicit rules for this scope2657  DEREF(implicitRulesMap_).try_emplace(&scope, context(), implicitRules_);2658  SetScope(scope);2659}2660 2661// TODO: for all of these errors, reference previous statement too2662bool ImplicitRulesVisitor::HandleImplicitNone(2663    const std::list<ImplicitNoneNameSpec> &nameSpecs) {2664  if (prevImplicitNone_) {2665    Say("More than one IMPLICIT NONE statement"_err_en_US);2666    Say(*prevImplicitNone_, "Previous IMPLICIT NONE statement"_en_US);2667    return false;2668  }2669  if (prevParameterStmt_) {2670    Say("IMPLICIT NONE statement after PARAMETER statement"_err_en_US);2671    return false;2672  }2673  prevImplicitNone_ = currStmtSource();2674  bool implicitNoneTypeNever{2675      context().IsEnabled(common::LanguageFeature::ImplicitNoneTypeNever)};2676  if (nameSpecs.empty()) {2677    if (!implicitNoneTypeNever) {2678      prevImplicitNoneType_ = currStmtSource();2679      implicitRules_->set_isImplicitNoneType(true);2680      if (prevImplicit_) {2681        Say("IMPLICIT NONE statement after IMPLICIT statement"_err_en_US);2682        return false;2683      }2684    }2685  } else {2686    int sawType{0};2687    int sawExternal{0};2688    for (const auto noneSpec : nameSpecs) {2689      switch (noneSpec) {2690      case ImplicitNoneNameSpec::External:2691        implicitRules_->set_isImplicitNoneExternal(true);2692        ++sawExternal;2693        break;2694      case ImplicitNoneNameSpec::Type:2695        if (!implicitNoneTypeNever) {2696          prevImplicitNoneType_ = currStmtSource();2697          implicitRules_->set_isImplicitNoneType(true);2698          if (prevImplicit_) {2699            Say("IMPLICIT NONE(TYPE) after IMPLICIT statement"_err_en_US);2700            return false;2701          }2702          ++sawType;2703        }2704        break;2705      }2706    }2707    if (sawType > 1) {2708      Say("TYPE specified more than once in IMPLICIT NONE statement"_err_en_US);2709      return false;2710    }2711    if (sawExternal > 1) {2712      Say("EXTERNAL specified more than once in IMPLICIT NONE statement"_err_en_US);2713      return false;2714    }2715  }2716  return true;2717}2718 2719// ArraySpecVisitor implementation2720 2721void ArraySpecVisitor::Post(const parser::ArraySpec &x) {2722  CHECK(arraySpec_.empty());2723  arraySpec_ = AnalyzeArraySpec(context(), x);2724}2725void ArraySpecVisitor::Post(const parser::ComponentArraySpec &x) {2726  CHECK(arraySpec_.empty());2727  arraySpec_ = AnalyzeArraySpec(context(), x);2728}2729void ArraySpecVisitor::Post(const parser::CoarraySpec &x) {2730  CHECK(coarraySpec_.empty());2731  coarraySpec_ = AnalyzeCoarraySpec(context(), x);2732}2733 2734const ArraySpec &ArraySpecVisitor::arraySpec() {2735  return !arraySpec_.empty() ? arraySpec_ : attrArraySpec_;2736}2737const ArraySpec &ArraySpecVisitor::coarraySpec() {2738  return !coarraySpec_.empty() ? coarraySpec_ : attrCoarraySpec_;2739}2740void ArraySpecVisitor::BeginArraySpec() {2741  CHECK(arraySpec_.empty());2742  CHECK(coarraySpec_.empty());2743  CHECK(attrArraySpec_.empty());2744  CHECK(attrCoarraySpec_.empty());2745}2746void ArraySpecVisitor::EndArraySpec() {2747  CHECK(arraySpec_.empty());2748  CHECK(coarraySpec_.empty());2749  attrArraySpec_.clear();2750  attrCoarraySpec_.clear();2751}2752void ArraySpecVisitor::PostAttrSpec() {2753  // Save dimension/codimension from attrs so we can process array/coarray-spec2754  // on the entity-decl2755  if (!arraySpec_.empty()) {2756    if (attrArraySpec_.empty()) {2757      attrArraySpec_ = arraySpec_;2758      arraySpec_.clear();2759    } else {2760      Say(currStmtSource().value(),2761          "Attribute 'DIMENSION' cannot be used more than once"_err_en_US);2762    }2763  }2764  if (!coarraySpec_.empty()) {2765    if (attrCoarraySpec_.empty()) {2766      attrCoarraySpec_ = coarraySpec_;2767      coarraySpec_.clear();2768    } else {2769      Say(currStmtSource().value(),2770          "Attribute 'CODIMENSION' cannot be used more than once"_err_en_US);2771    }2772  }2773}2774 2775// FuncResultStack implementation2776 2777FuncResultStack::~FuncResultStack() { CHECK(stack_.empty()); }2778 2779// True when either type is absent, or if they are both present and are2780// equivalent for interface compatibility purposes.2781static bool TypesMismatchIfNonNull(2782    const DeclTypeSpec *type1, const DeclTypeSpec *type2) {2783  if (auto t1{evaluate::DynamicType::From(type1)}) {2784    if (auto t2{evaluate::DynamicType::From(type2)}) {2785      return !t1->IsEquivalentTo(*t2);2786    }2787  }2788  return false;2789}2790 2791void FuncResultStack::CompleteFunctionResultType() {2792  // If the function has a type in the prefix, process it now.2793  FuncInfo *info{Top()};2794  if (info && &info->scope == &scopeHandler_.currScope() &&2795      info->resultSymbol) {2796    if (info->parsedType) {2797      scopeHandler_.messageHandler().set_currStmtSource(info->source);2798      if (const auto *type{2799              scopeHandler_.ProcessTypeSpec(*info->parsedType, true)}) {2800        Symbol &symbol{*info->resultSymbol};2801        if (!scopeHandler_.context().HasError(symbol)) {2802          if (symbol.GetType()) {2803            scopeHandler_.Say(symbol.name(),2804                "Function cannot have both an explicit type prefix and a RESULT suffix"_err_en_US);2805            scopeHandler_.context().SetError(symbol);2806          } else {2807            symbol.SetType(*type);2808          }2809        }2810      }2811      info->parsedType = nullptr;2812    }2813    if (TypesMismatchIfNonNull(2814            info->resultSymbol->GetType(), info->previousImplicitType)) {2815      scopeHandler_2816          .Say(info->resultSymbol->name(),2817              "Function '%s' has a result type that differs from the implicit type it obtained in a previous reference"_err_en_US,2818              info->previousName)2819          .Attach(info->previousName,2820              "Previous reference implicitly typed as %s\n"_en_US,2821              info->previousImplicitType->AsFortran());2822    }2823  }2824}2825 2826// Called from ConvertTo{Object/Proc}Entity to cope with any appearance2827// of the function result in a specification expression.2828void FuncResultStack::CompleteTypeIfFunctionResult(Symbol &symbol) {2829  if (FuncInfo * info{Top()}) {2830    if (info->resultSymbol == &symbol) {2831      CompleteFunctionResultType();2832    }2833  }2834}2835 2836void FuncResultStack::Pop() {2837  if (!stack_.empty() && &stack_.back().scope == &scopeHandler_.currScope()) {2838    stack_.pop_back();2839  }2840}2841 2842// ScopeHandler implementation2843 2844void ScopeHandler::SayAlreadyDeclared(const parser::Name &name, Symbol &prev) {2845  SayAlreadyDeclared(name.source, prev);2846}2847void ScopeHandler::SayAlreadyDeclared(const SourceName &name, Symbol &prev) {2848  if (context().HasError(prev)) {2849    // don't report another error about prev2850  } else {2851    if (const auto *details{prev.detailsIf<UseDetails>()}) {2852      Say(name, "'%s' is already declared in this scoping unit"_err_en_US)2853          .Attach(details->location(),2854              "It is use-associated with '%s' in module '%s'"_en_US,2855              details->symbol().name(), GetUsedModule(*details).name());2856    } else {2857      SayAlreadyDeclared(name, prev.name());2858    }2859    context().SetError(prev);2860  }2861}2862void ScopeHandler::SayAlreadyDeclared(2863    const SourceName &name1, const SourceName &name2) {2864  if (name1.begin() < name2.begin()) {2865    SayAlreadyDeclared(name2, name1);2866  } else {2867    Say(name1, "'%s' is already declared in this scoping unit"_err_en_US)2868        .Attach(name2, "Previous declaration of '%s'"_en_US, name2);2869  }2870}2871 2872void ScopeHandler::SayWithReason(const parser::Name &name, Symbol &symbol,2873    MessageFixedText &&msg1, Message &&msg2) {2874  bool isFatal{msg1.IsFatal()};2875  Say(name, std::move(msg1), symbol.name()).Attach(std::move(msg2));2876  context().SetError(symbol, isFatal);2877}2878 2879template <typename... A>2880Message &ScopeHandler::SayWithDecl(const parser::Name &name, Symbol &symbol,2881    MessageFixedText &&msg, A &&...args) {2882  auto &message{2883      Say(name.source, std::move(msg), symbol.name(), std::forward<A>(args)...)2884          .Attach(symbol.name(),2885              symbol.test(Symbol::Flag::Implicit)2886                  ? "Implicit declaration of '%s'"_en_US2887                  : "Declaration of '%s'"_en_US,2888              name.source)};2889  if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {2890    if (auto usedAsProc{proc->usedAsProcedureHere()}) {2891      if (usedAsProc->begin() != symbol.name().begin()) {2892        message.Attach(*usedAsProc, "Referenced as a procedure"_en_US);2893      }2894    }2895  }2896  return message;2897}2898 2899void ScopeHandler::SayLocalMustBeVariable(2900    const parser::Name &name, Symbol &symbol) {2901  SayWithDecl(name, symbol,2902      "The name '%s' must be a variable to appear"2903      " in a locality-spec"_err_en_US);2904}2905 2906Message &ScopeHandler::SayDerivedType(2907    const SourceName &name, MessageFixedText &&msg, const Scope &type) {2908  const Symbol &typeSymbol{DEREF(type.GetSymbol())};2909  return Say(name, std::move(msg), name, typeSymbol.name())2910      .Attach(typeSymbol.name(), "Declaration of derived type '%s'"_en_US,2911          typeSymbol.name());2912}2913Message &ScopeHandler::Say2(const SourceName &name1, MessageFixedText &&msg1,2914    const SourceName &name2, MessageFixedText &&msg2) {2915  return Say(name1, std::move(msg1)).Attach(name2, std::move(msg2), name2);2916}2917Message &ScopeHandler::Say2(const SourceName &name, MessageFixedText &&msg1,2918    Symbol &symbol, MessageFixedText &&msg2) {2919  bool isFatal{msg1.IsFatal()};2920  Message &result{Say2(name, std::move(msg1), symbol.name(), std::move(msg2))};2921  context().SetError(symbol, isFatal);2922  return result;2923}2924Message &ScopeHandler::Say2(const parser::Name &name, MessageFixedText &&msg1,2925    Symbol &symbol, MessageFixedText &&msg2) {2926  bool isFatal{msg1.IsFatal()};2927  Message &result{2928      Say2(name.source, std::move(msg1), symbol.name(), std::move(msg2))};2929  context().SetError(symbol, isFatal);2930  return result;2931}2932 2933// This is essentially GetProgramUnitContaining(), but it can return2934// a mutable Scope &, it ignores statement functions, and it fails2935// gracefully for error recovery (returning the original Scope).2936template <typename T> static T &GetInclusiveScope(T &scope) {2937  for (T *s{&scope}; !s->IsGlobal(); s = &s->parent()) {2938    switch (s->kind()) {2939    case Scope::Kind::Module:2940    case Scope::Kind::MainProgram:2941    case Scope::Kind::Subprogram:2942    case Scope::Kind::BlockData:2943      if (!s->IsStmtFunction()) {2944        return *s;2945      }2946      break;2947    default:;2948    }2949  }2950  return scope;2951}2952 2953Scope &ScopeHandler::InclusiveScope() { return GetInclusiveScope(currScope()); }2954 2955Scope *ScopeHandler::GetHostProcedure() {2956  Scope &parent{InclusiveScope().parent()};2957  switch (parent.kind()) {2958  case Scope::Kind::Subprogram:2959    return &parent;2960  case Scope::Kind::MainProgram:2961    return &parent;2962  default:2963    return nullptr;2964  }2965}2966 2967Scope &ScopeHandler::NonDerivedTypeScope() {2968  return currScope_->IsDerivedType() ? currScope_->parent() : *currScope_;2969}2970 2971static void SetImplicitCUDADevice(Symbol &symbol) {2972  if (auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {2973    if (!object->cudaDataAttr() && !IsValue(symbol) &&2974        !IsFunctionResult(symbol)) {2975      // Implicitly set device attribute if none is set in device context.2976      object->set_cudaDataAttr(common::CUDADataAttr::Device);2977    }2978  }2979}2980 2981void ScopeHandler::PushScope(Scope::Kind kind, Symbol *symbol) {2982  PushScope(currScope().MakeScope(kind, symbol));2983}2984void ScopeHandler::PushScope(Scope &scope) {2985  currScope_ = &scope;2986  auto kind{currScope_->kind()};2987  if (kind != Scope::Kind::BlockConstruct &&2988      kind != Scope::Kind::OtherConstruct && kind != Scope::Kind::OtherClause) {2989    BeginScope(scope);2990  }2991  // The name of a module or submodule cannot be "used" in its scope,2992  // as we read 19.3.1(2), so we allow the name to be used as a local2993  // identifier in the module or submodule too.  Same with programs2994  // (14.1(3)) and BLOCK DATA.2995  if (!currScope_->IsDerivedType() && kind != Scope::Kind::Module &&2996      kind != Scope::Kind::MainProgram && kind != Scope::Kind::BlockData) {2997    if (auto *symbol{scope.symbol()}) {2998      // Create a dummy symbol so we can't create another one with the same2999      // name. It might already be there if we previously pushed the scope.3000      SourceName name{symbol->name()};3001      if (!FindInScope(scope, name)) {3002        auto &newSymbol{MakeSymbol(name)};3003        if (kind == Scope::Kind::Subprogram) {3004          // Allow for recursive references.  If this symbol is a function3005          // without an explicit RESULT(), this new symbol will be discarded3006          // and replaced with an object of the same name.3007          newSymbol.set_details(HostAssocDetails{*symbol});3008        } else {3009          newSymbol.set_details(MiscDetails{MiscDetails::Kind::ScopeName});3010        }3011      }3012    }3013  }3014}3015void ScopeHandler::PopScope() {3016  CHECK(currScope_ && !currScope_->IsGlobal());3017  // Entities that are not yet classified as objects or procedures are now3018  // assumed to be objects.3019  // TODO: Statement functions3020  bool inDeviceSubprogram{false};3021  const Symbol *scopeSym{currScope().GetSymbol()};3022  if (currScope().kind() == Scope::Kind::BlockConstruct) {3023    scopeSym = GetProgramUnitContaining(currScope()).GetSymbol();3024  }3025  if (scopeSym) {3026    if (auto *details{scopeSym->detailsIf<SubprogramDetails>()}) {3027      // Check the current procedure is a device procedure to apply implicit3028      // attribute at the end.3029      if (auto attrs{details->cudaSubprogramAttrs()}) {3030        if (*attrs == common::CUDASubprogramAttrs::Device ||3031            *attrs == common::CUDASubprogramAttrs::Global ||3032            *attrs == common::CUDASubprogramAttrs::Grid_Global) {3033          inDeviceSubprogram = true;3034        }3035      }3036    }3037  }3038  for (auto &pair : currScope()) {3039    ConvertToObjectEntity(*pair.second);3040  }3041 3042  // Apply CUDA device attributes if in a device subprogram3043  if (inDeviceSubprogram && currScope().kind() == Scope::Kind::BlockConstruct) {3044    for (auto &pair : currScope()) {3045      SetImplicitCUDADevice(*pair.second);3046    }3047  }3048 3049  funcResultStack_.Pop();3050  // If popping back into a global scope, pop back to the top scope.3051  Scope *hermetic{context().currentHermeticModuleFileScope()};3052  SetScope(currScope_->parent().IsGlobal()3053          ? (hermetic ? *hermetic : context().globalScope())3054          : currScope_->parent());3055}3056void ScopeHandler::SetScope(Scope &scope) {3057  currScope_ = &scope;3058  ImplicitRulesVisitor::SetScope(InclusiveScope());3059}3060 3061Symbol *ScopeHandler::FindSymbol(const parser::Name &name) {3062  return FindSymbol(currScope(), name);3063}3064Symbol *ScopeHandler::FindSymbol(const Scope &scope, const parser::Name &name) {3065  if (scope.IsDerivedType()) {3066    if (Symbol * symbol{scope.FindComponent(name.source)}) {3067      if (symbol->has<TypeParamDetails>()) {3068        return Resolve(name, symbol);3069      }3070    }3071    return FindSymbol(scope.parent(), name);3072  } else if (scope.kind() == Scope::Kind::ImpliedDos) {3073    if (Symbol * symbol{FindInScope(scope, name)}) {3074      return Resolve(name, symbol);3075    } else {3076      // Don't use scope.FindSymbol() as below, since implied DO scopes3077      // can be parts of initializers in derived type components.3078      return FindSymbol(scope.parent(), name);3079    }3080  } else if (inEquivalenceStmt_) {3081    // In EQUIVALENCE statements only resolve names in the local scope, see3082    // 19.5.1.4, paragraph 2, item (10)3083    return Resolve(name, FindInScope(scope, name));3084  } else {3085    return Resolve(name, scope.FindSymbol(name.source));3086  }3087}3088 3089Symbol &ScopeHandler::MakeSymbol(3090    Scope &scope, const SourceName &name, Attrs attrs) {3091  if (Symbol * symbol{FindInScope(scope, name)}) {3092    CheckDuplicatedAttrs(name, *symbol, attrs);3093    SetExplicitAttrs(*symbol, attrs);3094    return *symbol;3095  } else {3096    const auto pair{scope.try_emplace(name, attrs, UnknownDetails{})};3097    CHECK(pair.second); // name was not found, so must be able to add3098    return *pair.first->second;3099  }3100}3101Symbol &ScopeHandler::MakeSymbol(const SourceName &name, Attrs attrs) {3102  return MakeSymbol(currScope(), name, attrs);3103}3104Symbol &ScopeHandler::MakeSymbol(const parser::Name &name, Attrs attrs) {3105  return Resolve(name, MakeSymbol(name.source, attrs));3106}3107Symbol &ScopeHandler::MakeHostAssocSymbol(3108    const parser::Name &name, const Symbol &hostSymbol) {3109  Symbol &symbol{*NonDerivedTypeScope()3110                      .try_emplace(name.source, HostAssocDetails{hostSymbol})3111                      .first->second};3112  name.symbol = &symbol;3113  symbol.attrs() = hostSymbol.attrs(); // TODO: except PRIVATE, PUBLIC?3114  // These attributes can be redundantly reapplied without error3115  // on the host-associated name, at most once (C815).3116  symbol.implicitAttrs() =3117      symbol.attrs() & Attrs{Attr::ASYNCHRONOUS, Attr::VOLATILE};3118  // SAVE statement in the inner scope will create a new symbol.3119  // If the host variable is used via host association,3120  // we have to propagate whether SAVE is implicit in the host scope.3121  // Otherwise, verifications that do not allow explicit SAVE3122  // attribute would fail.3123  symbol.implicitAttrs() |= hostSymbol.implicitAttrs() & Attrs{Attr::SAVE};3124  symbol.flags() = hostSymbol.flags();3125  return symbol;3126}3127Symbol &ScopeHandler::CopySymbol(const SourceName &name, const Symbol &symbol) {3128  CHECK(!FindInScope(name));3129  return MakeSymbol(currScope(), name, symbol.attrs());3130}3131 3132// Look for name only in scope, not in enclosing scopes.3133 3134Symbol *ScopeHandler::FindInScope(3135    const Scope &scope, const parser::Name &name) {3136  return Resolve(name, FindInScope(scope, name.source));3137}3138Symbol *ScopeHandler::FindInScope(const Scope &scope, const SourceName &name) {3139  // all variants of names, e.g. "operator(.ne.)" for "operator(/=)"3140  for (const std::string &n : GetAllNames(context(), name)) {3141    auto it{scope.find(SourceName{n})};3142    if (it != scope.end()) {3143      return &*it->second;3144    }3145  }3146  return nullptr;3147}3148 3149// Find a component or type parameter by name in a derived type or its parents.3150Symbol *ScopeHandler::FindInTypeOrParents(3151    const Scope &scope, const parser::Name &name) {3152  return Resolve(name, scope.FindComponent(name.source));3153}3154Symbol *ScopeHandler::FindInTypeOrParents(const parser::Name &name) {3155  return FindInTypeOrParents(currScope(), name);3156}3157Symbol *ScopeHandler::FindInScopeOrBlockConstructs(3158    const Scope &scope, SourceName name) {3159  if (Symbol * symbol{FindInScope(scope, name)}) {3160    return symbol;3161  }3162  for (const Scope &child : scope.children()) {3163    if (child.kind() == Scope::Kind::BlockConstruct) {3164      if (Symbol * symbol{FindInScopeOrBlockConstructs(child, name)}) {3165        return symbol;3166      }3167    }3168  }3169  return nullptr;3170}3171 3172void ScopeHandler::EraseSymbol(const parser::Name &name) {3173  currScope().erase(name.source);3174  name.symbol = nullptr;3175}3176 3177static bool NeedsType(const Symbol &symbol) {3178  return !symbol.GetType() &&3179      common::visit(common::visitors{3180                        [](const EntityDetails &) { return true; },3181                        [](const ObjectEntityDetails &) { return true; },3182                        [](const AssocEntityDetails &) { return true; },3183                        [&](const ProcEntityDetails &p) {3184                          return symbol.test(Symbol::Flag::Function) &&3185                              !symbol.attrs().test(Attr::INTRINSIC) &&3186                              !p.type() && !p.procInterface();3187                        },3188                        [](const auto &) { return false; },3189                    },3190          symbol.details());3191}3192 3193void ScopeHandler::ApplyImplicitRules(3194    Symbol &symbol, bool allowForwardReference) {3195  funcResultStack_.CompleteTypeIfFunctionResult(symbol);3196  if (context().HasError(symbol) || !NeedsType(symbol)) {3197    return;3198  }3199  if (const DeclTypeSpec * type{GetImplicitType(symbol)}) {3200    if (!skipImplicitTyping_) {3201      symbol.set(Symbol::Flag::Implicit);3202      symbol.SetType(*type);3203    }3204    return;3205  }3206  if (symbol.has<ProcEntityDetails>() && !symbol.attrs().test(Attr::EXTERNAL)) {3207    std::optional<Symbol::Flag> functionOrSubroutineFlag;3208    if (symbol.test(Symbol::Flag::Function)) {3209      functionOrSubroutineFlag = Symbol::Flag::Function;3210    } else if (symbol.test(Symbol::Flag::Subroutine)) {3211      functionOrSubroutineFlag = Symbol::Flag::Subroutine;3212    }3213    if (IsIntrinsic(symbol.name(), functionOrSubroutineFlag)) {3214      // type will be determined in expression semantics3215      AcquireIntrinsicProcedureFlags(symbol);3216      return;3217    }3218  }3219  if (allowForwardReference && ImplicitlyTypeForwardRef(symbol)) {3220    return;3221  }3222  if (const auto *entity{symbol.detailsIf<EntityDetails>()};3223      entity && entity->isDummy()) {3224    // Dummy argument, no declaration or reference; if it turns3225    // out to be a subroutine, it's fine, and if it is a function3226    // or object, it'll be caught later.3227    return;3228  }3229  if (deferImplicitTyping_) {3230    return;3231  }3232  if (!context().HasError(symbol)) {3233    Say(symbol.name(), "No explicit type declared for '%s'"_err_en_US);3234    context().SetError(symbol);3235  }3236}3237 3238// Extension: Allow forward references to scalar integer dummy arguments3239// or variables in COMMON to appear in specification expressions under3240// IMPLICIT NONE(TYPE) when what would otherwise have been their implicit3241// type is default INTEGER.3242bool ScopeHandler::ImplicitlyTypeForwardRef(Symbol &symbol) {3243  if (!inSpecificationPart_ || context().HasError(symbol) ||3244      !(IsDummy(symbol) || FindCommonBlockContaining(symbol)) ||3245      symbol.Rank() != 0 ||3246      !context().languageFeatures().IsEnabled(3247          common::LanguageFeature::ForwardRefImplicitNone)) {3248    return false;3249  }3250  const DeclTypeSpec *type{3251      GetImplicitType(symbol, false /*ignore IMPLICIT NONE*/)};3252  if (!type || !type->IsNumeric(TypeCategory::Integer)) {3253    return false;3254  }3255  auto kind{evaluate::ToInt64(type->numericTypeSpec().kind())};3256  if (!kind || *kind != context().GetDefaultKind(TypeCategory::Integer)) {3257    return false;3258  }3259  if (!ConvertToObjectEntity(symbol)) {3260    return false;3261  }3262  // TODO: check no INTENT(OUT) if dummy?3263  context().Warn(common::LanguageFeature::ForwardRefImplicitNone, symbol.name(),3264      "'%s' was used without (or before) being explicitly typed"_warn_en_US,3265      symbol.name());3266  symbol.set(Symbol::Flag::Implicit);3267  symbol.SetType(*type);3268  return true;3269}3270 3271// Ensure that the symbol for an intrinsic procedure is marked with3272// the INTRINSIC attribute.  Also set PURE &/or ELEMENTAL as3273// appropriate.3274void ScopeHandler::AcquireIntrinsicProcedureFlags(Symbol &symbol) {3275  SetImplicitAttr(symbol, Attr::INTRINSIC);3276  switch (context().intrinsics().GetIntrinsicClass(symbol.name().ToString())) {3277  case evaluate::IntrinsicClass::elementalFunction:3278  case evaluate::IntrinsicClass::elementalSubroutine:3279    SetExplicitAttr(symbol, Attr::ELEMENTAL);3280    SetExplicitAttr(symbol, Attr::PURE);3281    break;3282  case evaluate::IntrinsicClass::impureSubroutine:3283    break;3284  default:3285    SetExplicitAttr(symbol, Attr::PURE);3286  }3287}3288 3289const DeclTypeSpec *ScopeHandler::GetImplicitType(3290    Symbol &symbol, bool respectImplicitNoneType) {3291  const Scope *scope{&symbol.owner()};3292  if (scope->IsGlobal()) {3293    scope = &currScope();3294  }3295  scope = &GetInclusiveScope(*scope);3296  const auto *type{implicitRulesMap_->at(scope).GetType(3297      symbol.name(), respectImplicitNoneType)};3298  if (type) {3299    if (const DerivedTypeSpec * derived{type->AsDerived()}) {3300      // Resolve any forward-referenced derived type; a quick no-op else.3301      auto &instantiatable{*const_cast<DerivedTypeSpec *>(derived)};3302      instantiatable.Instantiate(currScope());3303    }3304  }3305  return type;3306}3307 3308void ScopeHandler::CheckEntryDummyUse(SourceName source, Symbol *symbol) {3309  if (!inSpecificationPart_ && symbol &&3310      symbol->test(Symbol::Flag::EntryDummyArgument)) {3311    Say(source,3312        "Dummy argument '%s' may not be used before its ENTRY statement"_err_en_US,3313        symbol->name());3314    symbol->set(Symbol::Flag::EntryDummyArgument, false);3315  }3316}3317 3318// Convert symbol to be a ObjectEntity or return false if it can't be.3319bool ScopeHandler::ConvertToObjectEntity(Symbol &symbol) {3320  if (symbol.has<ObjectEntityDetails>()) {3321    // nothing to do3322  } else if (symbol.has<UnknownDetails>()) {3323    // These are attributes that a name could have picked up from3324    // an attribute statement or type declaration statement.3325    if (symbol.attrs().HasAny({Attr::EXTERNAL, Attr::INTRINSIC})) {3326      return false;3327    }3328    symbol.set_details(ObjectEntityDetails{});3329  } else if (auto *details{symbol.detailsIf<EntityDetails>()}) {3330    if (symbol.attrs().HasAny({Attr::EXTERNAL, Attr::INTRINSIC})) {3331      return false;3332    }3333    funcResultStack_.CompleteTypeIfFunctionResult(symbol);3334    symbol.set_details(ObjectEntityDetails{std::move(*details)});3335  } else if (auto *useDetails{symbol.detailsIf<UseDetails>()}) {3336    return useDetails->symbol().has<ObjectEntityDetails>();3337  } else if (auto *hostDetails{symbol.detailsIf<HostAssocDetails>()}) {3338    return hostDetails->symbol().has<ObjectEntityDetails>();3339  } else {3340    return false;3341  }3342  return true;3343}3344// Convert symbol to be a ProcEntity or return false if it can't be.3345bool ScopeHandler::ConvertToProcEntity(3346    Symbol &symbol, std::optional<SourceName> usedHere) {3347  if (symbol.has<ProcEntityDetails>()) {3348  } else if (symbol.has<UnknownDetails>()) {3349    symbol.set_details(ProcEntityDetails{});3350  } else if (auto *details{symbol.detailsIf<EntityDetails>()}) {3351    if (IsFunctionResult(symbol) &&3352        !(IsPointer(symbol) && symbol.attrs().test(Attr::EXTERNAL))) {3353      // Don't turn function result into a procedure pointer unless both3354      // POINTER and EXTERNAL3355      return false;3356    }3357    funcResultStack_.CompleteTypeIfFunctionResult(symbol);3358    symbol.set_details(ProcEntityDetails{std::move(*details)});3359    if (symbol.GetType() && !symbol.test(Symbol::Flag::Implicit)) {3360      CHECK(!symbol.test(Symbol::Flag::Subroutine));3361      symbol.set(Symbol::Flag::Function);3362    }3363  } else if (auto *useDetails{symbol.detailsIf<UseDetails>()}) {3364    return useDetails->symbol().has<ProcEntityDetails>();3365  } else if (auto *hostDetails{symbol.detailsIf<HostAssocDetails>()}) {3366    return hostDetails->symbol().has<ProcEntityDetails>();3367  } else {3368    return false;3369  }3370  auto &proc{symbol.get<ProcEntityDetails>()};3371  if (usedHere && !proc.usedAsProcedureHere()) {3372    proc.set_usedAsProcedureHere(*usedHere);3373  }3374  return true;3375}3376 3377const DeclTypeSpec &ScopeHandler::MakeNumericType(3378    TypeCategory category, const std::optional<parser::KindSelector> &kind) {3379  KindExpr value{GetKindParamExpr(category, kind)};3380  if (auto known{evaluate::ToInt64(value)}) {3381    return MakeNumericType(category, static_cast<int>(*known));3382  } else {3383    return currScope_->MakeNumericType(category, std::move(value));3384  }3385}3386 3387const DeclTypeSpec &ScopeHandler::MakeNumericType(3388    TypeCategory category, int kind) {3389  return context().MakeNumericType(category, kind);3390}3391 3392const DeclTypeSpec &ScopeHandler::MakeLogicalType(3393    const std::optional<parser::KindSelector> &kind) {3394  KindExpr value{GetKindParamExpr(TypeCategory::Logical, kind)};3395  if (auto known{evaluate::ToInt64(value)}) {3396    return MakeLogicalType(static_cast<int>(*known));3397  } else {3398    return currScope_->MakeLogicalType(std::move(value));3399  }3400}3401 3402const DeclTypeSpec &ScopeHandler::MakeLogicalType(int kind) {3403  return context().MakeLogicalType(kind);3404}3405 3406void ScopeHandler::NotePossibleBadForwardRef(const parser::Name &name) {3407  if (inSpecificationPart_ && !deferImplicitTyping_ && name.symbol) {3408    auto kind{currScope().kind()};3409    if ((kind == Scope::Kind::Subprogram && !currScope().IsStmtFunction()) ||3410        kind == Scope::Kind::BlockConstruct) {3411      bool isHostAssociated{&name.symbol->owner() == &currScope()3412              ? name.symbol->has<HostAssocDetails>()3413              : name.symbol->owner().Contains(currScope())};3414      if (isHostAssociated) {3415        specPartState_.forwardRefs.insert(name.source);3416      }3417    }3418  }3419}3420 3421std::optional<SourceName> ScopeHandler::HadForwardRef(3422    const Symbol &symbol) const {3423  auto iter{specPartState_.forwardRefs.find(symbol.name())};3424  if (iter != specPartState_.forwardRefs.end()) {3425    return *iter;3426  }3427  return std::nullopt;3428}3429 3430bool ScopeHandler::CheckPossibleBadForwardRef(const Symbol &symbol) {3431  if (!context().HasError(symbol)) {3432    if (auto fwdRef{HadForwardRef(symbol)}) {3433      const Symbol *outer{symbol.owner().FindSymbol(symbol.name())};3434      if (outer && symbol.has<UseDetails>() &&3435          &symbol.GetUltimate() == &outer->GetUltimate()) {3436        // e.g. IMPORT of host's USE association3437        return false;3438      }3439      Say(*fwdRef,3440          "Forward reference to '%s' is not allowed in the same specification part"_err_en_US,3441          *fwdRef)3442          .Attach(symbol.name(), "Later declaration of '%s'"_en_US, *fwdRef);3443      context().SetError(symbol);3444      return true;3445    }3446    if ((IsDummy(symbol) ||3447            (!symbol.has<UseDetails>() && FindCommonBlockContaining(symbol))) &&3448        isImplicitNoneType() && symbol.test(Symbol::Flag::Implicit) &&3449        !context().HasError(symbol)) {3450      // Dummy or COMMON was implicitly typed despite IMPLICIT NONE(TYPE) in3451      // ApplyImplicitRules() due to use in a specification expression,3452      // and no explicit type declaration appeared later.3453      Say(symbol.name(), "No explicit type declared for '%s'"_err_en_US);3454      context().SetError(symbol);3455      return true;3456    }3457  }3458  return false;3459}3460 3461void ScopeHandler::MakeExternal(Symbol &symbol) {3462  if (!symbol.attrs().test(Attr::EXTERNAL)) {3463    SetImplicitAttr(symbol, Attr::EXTERNAL);3464    if (symbol.attrs().test(Attr::INTRINSIC)) { // C8403465      Say(symbol.name(),3466          "Symbol '%s' cannot have both EXTERNAL and INTRINSIC attributes"_err_en_US,3467          symbol.name());3468    }3469  }3470}3471 3472bool ScopeHandler::CheckDuplicatedAttr(3473    SourceName name, Symbol &symbol, Attr attr) {3474  if (attr == Attr::SAVE) {3475    // checked elsewhere3476  } else if (symbol.attrs().test(attr)) { // C8153477    if (symbol.implicitAttrs().test(attr)) {3478      // Implied attribute is now confirmed explicitly3479      symbol.implicitAttrs().reset(attr);3480    } else {3481      Say(name, "%s attribute was already specified on '%s'"_err_en_US,3482          EnumToString(attr), name);3483      return false;3484    }3485  }3486  return true;3487}3488 3489bool ScopeHandler::CheckDuplicatedAttrs(3490    SourceName name, Symbol &symbol, Attrs attrs) {3491  bool ok{true};3492  attrs.IterateOverMembers(3493      [&](Attr x) { ok &= CheckDuplicatedAttr(name, symbol, x); });3494  return ok;3495}3496 3497void ScopeHandler::SetCUDADataAttr(SourceName source, Symbol &symbol,3498    std::optional<common::CUDADataAttr> attr) {3499  if (attr) {3500    ConvertToObjectEntity(symbol);3501    if (auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {3502      if (*attr != object->cudaDataAttr().value_or(*attr)) {3503        Say(source,3504            "'%s' already has another CUDA data attribute ('%s')"_err_en_US,3505            symbol.name(),3506            std::string{common::EnumToString(*object->cudaDataAttr())}.c_str());3507      } else {3508        object->set_cudaDataAttr(attr);3509      }3510    } else {3511      Say(source,3512          "'%s' is not an object and may not have a CUDA data attribute"_err_en_US,3513          symbol.name());3514    }3515  }3516}3517 3518// ModuleVisitor implementation3519 3520bool ModuleVisitor::Pre(const parser::Only &x) {3521  common::visit(common::visitors{3522                    [&](const Indirection<parser::GenericSpec> &generic) {3523                      GenericSpecInfo genericSpecInfo{generic.value()};3524                      AddUseOnly(genericSpecInfo.symbolName());3525                      AddUse(genericSpecInfo);3526                    },3527                    [&](const parser::Name &name) {3528                      AddUseOnly(name.source);3529                      Resolve(name, AddUse(name.source, name.source).use);3530                    },3531                    [&](const parser::Rename &rename) { Walk(rename); },3532                },3533      x.u);3534  return false;3535}3536 3537void ModuleVisitor::CollectUseRenames(const parser::UseStmt &useStmt) {3538  auto doRename{[&](const parser::Rename &rename) {3539    if (const auto *names{std::get_if<parser::Rename::Names>(&rename.u)}) {3540      AddUseRename(std::get<1>(names->t).source, useStmt.moduleName.source);3541    }3542  }};3543  common::visit(3544      common::visitors{3545          [&](const std::list<parser::Rename> &renames) {3546            for (const auto &rename : renames) {3547              doRename(rename);3548            }3549          },3550          [&](const std::list<parser::Only> &onlys) {3551            for (const auto &only : onlys) {3552              if (const auto *rename{std::get_if<parser::Rename>(&only.u)}) {3553                doRename(*rename);3554              }3555            }3556          },3557      },3558      useStmt.u);3559}3560 3561bool ModuleVisitor::Pre(const parser::Rename::Names &x) {3562  const auto &localName{std::get<0>(x.t)};3563  const auto &useName{std::get<1>(x.t)};3564  SymbolRename rename{AddUse(localName.source, useName.source)};3565  Resolve(useName, rename.use);3566  Resolve(localName, rename.local);3567  return false;3568}3569bool ModuleVisitor::Pre(const parser::Rename::Operators &x) {3570  const parser::DefinedOpName &local{std::get<0>(x.t)};3571  const parser::DefinedOpName &use{std::get<1>(x.t)};3572  GenericSpecInfo localInfo{local};3573  GenericSpecInfo useInfo{use};3574  if (IsIntrinsicOperator(context(), local.v.source)) {3575    Say(local.v,3576        "Intrinsic operator '%s' may not be used as a defined operator"_err_en_US);3577  } else if (IsLogicalConstant(context(), local.v.source)) {3578    Say(local.v,3579        "Logical constant '%s' may not be used as a defined operator"_err_en_US);3580  } else {3581    SymbolRename rename{AddUse(localInfo.symbolName(), useInfo.symbolName())};3582    useInfo.Resolve(rename.use);3583    localInfo.Resolve(rename.local);3584  }3585  return false;3586}3587 3588// Set useModuleScope_ to the Scope of the module being used.3589bool ModuleVisitor::Pre(const parser::UseStmt &x) {3590  std::optional<bool> isIntrinsic;3591  if (x.nature) {3592    isIntrinsic = *x.nature == parser::UseStmt::ModuleNature::Intrinsic;3593  } else if (currScope().IsModule() && currScope().symbol() &&3594      currScope().symbol()->attrs().test(Attr::INTRINSIC)) {3595    // Intrinsic modules USE only other intrinsic modules3596    isIntrinsic = true;3597  }3598  useModuleScope_ = FindModule(x.moduleName, isIntrinsic);3599  if (!useModuleScope_) {3600    return false;3601  }3602  AddAndCheckModuleUse(x.moduleName.source,3603      useModuleScope_->parent().kind() == Scope::Kind::IntrinsicModules);3604  // use the name from this source file3605  useModuleScope_->symbol()->ReplaceName(x.moduleName.source);3606  return true;3607}3608 3609void ModuleVisitor::Post(const parser::UseStmt &x) {3610  if (const auto *list{std::get_if<std::list<parser::Rename>>(&x.u)}) {3611    // Not a use-only: collect the names that were used in renames,3612    // then add a use for each public name that was not renamed.3613    std::set<SourceName> useNames;3614    for (const auto &rename : *list) {3615      common::visit(common::visitors{3616                        [&](const parser::Rename::Names &names) {3617                          useNames.insert(std::get<1>(names.t).source);3618                        },3619                        [&](const parser::Rename::Operators &ops) {3620                          useNames.insert(std::get<1>(ops.t).v.source);3621                        },3622                    },3623          rename.u);3624    }3625    for (const auto &[name, symbol] : *useModuleScope_) {3626      // Default USE imports public names, excluding intrinsic-only and most3627      // miscellaneous details. Allow OpenMP mapper identifiers represented3628      // as MapperDetails, and also legacy MiscDetails::ConstructName.3629      bool isMapper{symbol->has<MapperDetails>()};3630      if (!isMapper) {3631        if (const auto *misc{symbol->detailsIf<MiscDetails>()}) {3632          isMapper = misc->kind() == MiscDetails::Kind::ConstructName;3633        }3634      }3635      if (symbol->attrs().test(Attr::PUBLIC) && !IsUseRenamed(symbol->name()) &&3636          (!symbol->implicitAttrs().test(Attr::INTRINSIC) ||3637              symbol->has<UseDetails>()) &&3638          (!symbol->has<MiscDetails>() || isMapper) &&3639          useNames.count(name) == 0) {3640        SourceName location{x.moduleName.source};3641        if (auto *localSymbol{FindInScope(name)}) {3642          DoAddUse(location, localSymbol->name(), *localSymbol, *symbol);3643        } else {3644          DoAddUse(location, location, CopySymbol(name, *symbol), *symbol);3645        }3646      }3647    }3648  }3649  // Go through the list of COMMON block symbols in the module scope and add3650  // their USE association to the current scope's USE-associated COMMON blocks.3651  for (const auto &[name, symbol] : useModuleScope_->commonBlocks()) {3652    if (!currScope().FindCommonBlockInVisibleScopes(name)) {3653      currScope().AddCommonBlockUse(3654          name, symbol->attrs(), symbol->GetUltimate());3655    }3656  }3657  // Go through the list of USE-associated COMMON block symbols in the module3658  // scope and add USE associations to their ultimate symbols to the current3659  // scope's USE-associated COMMON blocks.3660  for (const auto &[name, symbol] : useModuleScope_->commonBlockUses()) {3661    currScope().AddCommonBlockUse(name, symbol->attrs(), symbol->GetUltimate());3662  }3663  useModuleScope_ = nullptr;3664}3665 3666ModuleVisitor::SymbolRename ModuleVisitor::AddUse(3667    const SourceName &localName, const SourceName &useName) {3668  return AddUse(localName, useName, FindInScope(*useModuleScope_, useName));3669}3670 3671ModuleVisitor::SymbolRename ModuleVisitor::AddUse(3672    const SourceName &localName, const SourceName &useName, Symbol *useSymbol) {3673  if (!useModuleScope_) {3674    return {}; // error occurred finding module3675  }3676  if (!useSymbol) {3677    Say(useName, "'%s' not found in module '%s'"_err_en_US, MakeOpName(useName),3678        useModuleScope_->GetName().value());3679    return {};3680  }3681  if (useSymbol->attrs().test(Attr::PRIVATE) &&3682      !FindModuleFileContaining(currScope())) {3683    // Privacy is not enforced in module files so that generic interfaces3684    // can be resolved to private specific procedures in specification3685    // expressions.3686    // Local names that contain currency symbols ('$') are created by the3687    // module file writer when a private name in another module is needed to3688    // process a local declaration.  These can show up in the output of3689    // -fdebug-unparse-with-modules, too, so go easy on them.3690    if (currScope().IsModule() &&3691        localName.ToString().find("$") != std::string::npos) {3692      Say(useName, "'%s' is PRIVATE in '%s'"_warn_en_US, MakeOpName(useName),3693          useModuleScope_->GetName().value());3694    } else {3695      Say(useName, "'%s' is PRIVATE in '%s'"_err_en_US, MakeOpName(useName),3696          useModuleScope_->GetName().value());3697      return {};3698    }3699  }3700  auto &localSymbol{MakeSymbol(localName)};3701  DoAddUse(useName, localName, localSymbol, *useSymbol);3702  return {&localSymbol, useSymbol};3703}3704 3705// symbol must be either a Use or a Generic formed by merging two uses.3706// Convert it to a UseError with this additional location.3707bool ScopeHandler::ConvertToUseError(3708    Symbol &symbol, const SourceName &location, const Symbol &used) {3709  if (auto *ued{symbol.detailsIf<UseErrorDetails>()}) {3710    ued->add_occurrence(location, used);3711    return true;3712  }3713  const auto *useDetails{symbol.detailsIf<UseDetails>()};3714  if (!useDetails) {3715    if (auto *genericDetails{symbol.detailsIf<GenericDetails>()}) {3716      if (!genericDetails->uses().empty()) {3717        useDetails = &genericDetails->uses().at(0)->get<UseDetails>();3718      }3719    }3720  }3721  if (useDetails) {3722    symbol.set_details(3723        UseErrorDetails{*useDetails}.add_occurrence(location, used));3724    return true;3725  }3726  if (const auto *hostAssocDetails{symbol.detailsIf<HostAssocDetails>()};3727      hostAssocDetails && hostAssocDetails->symbol().has<SubprogramDetails>() &&3728      &symbol.owner() == &currScope() &&3729      &hostAssocDetails->symbol() == currScope().symbol()) {3730    // Handle USE-association of procedure FOO into function/subroutine FOO,3731    // replacing its place-holding HostAssocDetails symbol.3732    context().Warn(common::UsageWarning::UseAssociationIntoSameNameSubprogram,3733        location,3734        "'%s' is use-associated into a subprogram of the same name"_port_en_US,3735        used.name());3736    SourceName created{context().GetTempName(currScope())};3737    Symbol &tmpUse{MakeSymbol(created, Attrs(), UseDetails{location, used})};3738    UseErrorDetails useError{tmpUse.get<UseDetails>()};3739    useError.add_occurrence(location, hostAssocDetails->symbol());3740    symbol.set_details(std::move(useError));3741    return true;3742  }3743  return false;3744}3745 3746// Two ultimate symbols are distinct, but they have the same name and come3747// from modules with the same name.  At link time, their mangled names3748// would conflict, so they had better resolve to the same definition.3749// Check whether the two ultimate symbols have compatible definitions.3750// Returns true if no further processing is required in DoAddUse().3751static bool CheckCompatibleDistinctUltimates(SemanticsContext &context,3752    SourceName location, SourceName localName, const Symbol &localSymbol,3753    const Symbol &localUltimate, const Symbol &useUltimate, bool &isError) {3754  isError = false;3755  if (localUltimate.has<GenericDetails>()) {3756    if (useUltimate.has<GenericDetails>() ||3757        useUltimate.has<SubprogramDetails>() ||3758        useUltimate.has<DerivedTypeDetails>()) {3759      return false; // can try to merge them3760    } else {3761      isError = true;3762    }3763  } else if (useUltimate.has<GenericDetails>()) {3764    if (localUltimate.has<SubprogramDetails>() ||3765        localUltimate.has<DerivedTypeDetails>()) {3766      return false; // can try to merge them3767    } else {3768      isError = true;3769    }3770  } else if (localUltimate.has<SubprogramDetails>()) {3771    if (useUltimate.has<SubprogramDetails>()) {3772      auto localCharacteristics{3773          evaluate::characteristics::Procedure::Characterize(3774              localUltimate, context.foldingContext())};3775      auto useCharacteristics{3776          evaluate::characteristics::Procedure::Characterize(3777              useUltimate, context.foldingContext())};3778      if ((localCharacteristics &&3779              (!useCharacteristics ||3780                  *localCharacteristics != *useCharacteristics)) ||3781          (!localCharacteristics && useCharacteristics)) {3782        isError = true;3783      }3784    } else {3785      isError = true;3786    }3787  } else if (useUltimate.has<SubprogramDetails>()) {3788    isError = true;3789  } else if (const auto *localObject{3790                 localUltimate.detailsIf<ObjectEntityDetails>()}) {3791    if (const auto *useObject{useUltimate.detailsIf<ObjectEntityDetails>()}) {3792      auto localType{evaluate::DynamicType::From(localUltimate)};3793      auto useType{evaluate::DynamicType::From(useUltimate)};3794      if (localUltimate.size() != useUltimate.size() ||3795          (localType &&3796              (!useType || !localType->IsTkLenCompatibleWith(*useType) ||3797                  !useType->IsTkLenCompatibleWith(*localType))) ||3798          (!localType && useType)) {3799        isError = true;3800      } else if (IsNamedConstant(localUltimate)) {3801        isError = !IsNamedConstant(useUltimate) ||3802            !(*localObject->init() == *useObject->init());3803      } else {3804        isError = IsNamedConstant(useUltimate);3805      }3806    } else {3807      isError = true;3808    }3809  } else if (useUltimate.has<ObjectEntityDetails>()) {3810    isError = true;3811  } else if (IsProcedurePointer(localUltimate)) {3812    isError = !IsProcedurePointer(useUltimate);3813  } else if (IsProcedurePointer(useUltimate)) {3814    isError = true;3815  } else if (localUltimate.has<DerivedTypeDetails>()) {3816    isError = !(useUltimate.has<DerivedTypeDetails>() &&3817        evaluate::AreSameDerivedTypeIgnoringSequence(3818            DerivedTypeSpec{localUltimate.name(), localUltimate},3819            DerivedTypeSpec{useUltimate.name(), useUltimate}));3820  } else if (useUltimate.has<DerivedTypeDetails>()) {3821    isError = true;3822  } else if (localUltimate.has<NamelistDetails>() &&3823      useUltimate.has<NamelistDetails>()) {3824  } else if (localUltimate.has<CommonBlockDetails>() &&3825      useUltimate.has<CommonBlockDetails>()) {3826  } else {3827    isError = true;3828  }3829  return true; // don't try to merge generics (or whatever)3830}3831 3832void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,3833    Symbol &originalLocal, const Symbol &useSymbol) {3834  Symbol *localSymbol{&originalLocal};3835  if (auto *details{localSymbol->detailsIf<UseErrorDetails>()}) {3836    details->add_occurrence(location, useSymbol);3837    return;3838  }3839  const Symbol &useUltimate{useSymbol.GetUltimate()};3840  const auto *useGeneric{useUltimate.detailsIf<GenericDetails>()};3841  if (localSymbol->has<UnknownDetails>()) {3842    if (useGeneric &&3843        ((useGeneric->specific() &&3844             IsProcedurePointer(*useGeneric->specific())) ||3845            (useGeneric->derivedType() &&3846                useUltimate.name() != localSymbol->name()))) {3847      // We are use-associating a generic that either shadows a procedure3848      // pointer or shadows a derived type with a distinct name.3849      // Local references that might be made to the procedure pointer should3850      // use a UseDetails symbol for proper data addressing, and a derived3851      // type needs to be in scope with its local name.  So create an3852      // empty local generic now into which the use-associated generic may3853      // be copied.3854      localSymbol->set_details(GenericDetails{});3855      localSymbol->get<GenericDetails>().set_kind(useGeneric->kind());3856    } else { // just create UseDetails3857      localSymbol->set_details(UseDetails{localName, useSymbol});3858      localSymbol->attrs() =3859          useSymbol.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE, Attr::SAVE};3860      localSymbol->implicitAttrs() =3861          localSymbol->attrs() & Attrs{Attr::ASYNCHRONOUS, Attr::VOLATILE};3862      localSymbol->flags() = useSymbol.flags();3863      return;3864    }3865  }3866 3867  Symbol &localUltimate{localSymbol->GetUltimate()};3868  if (&localUltimate == &useUltimate) {3869    // use-associating the same symbol again -- ok3870    return;3871  }3872  if (useUltimate.owner().IsModule() && localUltimate.owner().IsSubmodule() &&3873      DoesScopeContain(&useUltimate.owner(), localUltimate)) {3874    // Within a submodule, USE'ing a symbol that comes indirectly3875    // from the ancestor module, e.g. foo in:3876    //  MODULE m1; INTERFACE; MODULE SUBROUTINE foo; END INTERFACE; END3877    //  MODULE m2; USE m1; END3878    //  SUBMODULE m1(sm); USE m2; CONTAINS; MODULE PROCEDURE foo; END; END3879    return; // ok, ignore it3880  }3881 3882  if (localUltimate.name() == useUltimate.name() &&3883      localUltimate.owner().IsModule() && useUltimate.owner().IsModule() &&3884      localUltimate.owner().GetName() &&3885      localUltimate.owner().GetName() == useUltimate.owner().GetName()) {3886    bool isError{false};3887    if (CheckCompatibleDistinctUltimates(context(), location, localName,3888            *localSymbol, localUltimate, useUltimate, isError)) {3889      if (isError) {3890        // Convert the local symbol to a UseErrorDetails, if possible;3891        // otherwise emit a fatal error.3892        if (!ConvertToUseError(*localSymbol, location, useSymbol)) {3893          context()3894              .Say(location,3895                  "'%s' use-associated from '%s' in module '%s' is incompatible with '%s' from another module"_err_en_US,3896                  localName, useUltimate.name(),3897                  useUltimate.owner().GetName().value(), localUltimate.name())3898              .Attach(useUltimate.name(), "First declaration"_en_US)3899              .Attach(localUltimate.name(), "Other declaration"_en_US);3900          return;3901        }3902      }3903      if (auto *msg{context().Warn(3904              common::UsageWarning::CompatibleDeclarationsFromDistinctModules,3905              location,3906              "'%s' is use-associated from '%s' in two distinct instances of module '%s'"_warn_en_US,3907              localName, localUltimate.name(),3908              localUltimate.owner().GetName().value())}) {3909        msg->Attach(localUltimate.name(), "Previous declaration"_en_US)3910            .Attach(useUltimate.name(), "Later declaration"_en_US);3911      }3912      return;3913    }3914  }3915 3916  // There are many possible combinations of symbol types that could arrive3917  // with the same (local) name vie USE association from distinct modules.3918  // Fortran allows a generic interface to share its name with a derived type,3919  // or with the name of a non-generic procedure (which should be one of the3920  // generic's specific procedures).  Implementing all these possibilities is3921  // complicated.3922  // Error cases are converted into UseErrorDetails symbols to trigger error3923  // messages when/if bad combinations are actually used later in the program.3924  // The error cases are:3925  //   - two distinct derived types3926  //   - two distinct non-generic procedures3927  //   - a generic and a non-generic that is not already one of its specifics3928  //   - anything other than a derived type, non-generic procedure, or3929  //     generic procedure being combined with something other than an3930  //     prior USE association of itself3931  auto *localGeneric{localUltimate.detailsIf<GenericDetails>()};3932  Symbol *localDerivedType{nullptr};3933  if (localUltimate.has<DerivedTypeDetails>()) {3934    localDerivedType = &localUltimate;3935  } else if (localGeneric) {3936    if (auto *dt{localGeneric->derivedType()};3937        dt && !dt->attrs().test(Attr::PRIVATE)) {3938      localDerivedType = dt;3939    }3940  }3941  const Symbol *useDerivedType{nullptr};3942  if (useUltimate.has<DerivedTypeDetails>()) {3943    useDerivedType = &useUltimate;3944  } else if (useGeneric) {3945    if (const auto *dt{useGeneric->derivedType()};3946        dt && !dt->attrs().test(Attr::PRIVATE)) {3947      useDerivedType = dt;3948    }3949  }3950 3951  Symbol *localProcedure{nullptr};3952  if (localGeneric) {3953    if (localGeneric->specific() &&3954        !localGeneric->specific()->attrs().test(Attr::PRIVATE)) {3955      localProcedure = localGeneric->specific();3956    }3957  } else if (IsProcedure(localUltimate)) {3958    localProcedure = &localUltimate;3959  }3960  const Symbol *useProcedure{nullptr};3961  if (useGeneric) {3962    if (useGeneric->specific() &&3963        !useGeneric->specific()->attrs().test(Attr::PRIVATE)) {3964      useProcedure = useGeneric->specific();3965    }3966  } else if (IsProcedure(useUltimate)) {3967    useProcedure = &useUltimate;3968  }3969 3970  // When two derived types arrived, try to combine them.3971  const Symbol *combinedDerivedType{nullptr};3972  if (!useDerivedType) {3973    combinedDerivedType = localDerivedType;3974  } else if (!localDerivedType) {3975    if (useDerivedType->name() == localName) {3976      combinedDerivedType = useDerivedType;3977    } else {3978      combinedDerivedType =3979          &currScope().MakeSymbol(localSymbol->name(), useDerivedType->attrs(),3980              UseDetails{localSymbol->name(), *useDerivedType});3981    }3982  } else if (&localDerivedType->GetUltimate() ==3983      &useDerivedType->GetUltimate()) {3984    combinedDerivedType = localDerivedType;3985  } else {3986    const Scope *localScope{localDerivedType->GetUltimate().scope()};3987    const Scope *useScope{useDerivedType->GetUltimate().scope()};3988    if (localScope && useScope && localScope->derivedTypeSpec() &&3989        useScope->derivedTypeSpec() &&3990        evaluate::AreSameDerivedType(3991            *localScope->derivedTypeSpec(), *useScope->derivedTypeSpec())) {3992      combinedDerivedType = localDerivedType;3993    } else {3994      // Create a local UseErrorDetails for the ambiguous derived type3995      if (localSymbol->has<UseDetails>() && localGeneric) {3996        // Creates a UseErrorDetails symbol in the current scope for a3997        // current UseDetails symbol, but leaves the UseDetails in the3998        // scope's name map.3999        UseErrorDetails details{localSymbol->get<UseDetails>()};4000        EraseSymbol(*localSymbol);4001        details.add_occurrence(location, useSymbol);4002        Symbol *newSymbol{&MakeSymbol(localName, Attrs{}, std::move(details))};4003        // Restore *localSymbol in currScope4004        auto iter{currScope().find(localName)};4005        CHECK(iter != currScope().end() && &*iter->second == newSymbol);4006        iter->second = MutableSymbolRef{*localSymbol};4007        combinedDerivedType = newSymbol;4008      } else {4009        ConvertToUseError(*localSymbol, location, useSymbol);4010        localDerivedType = nullptr;4011        localGeneric = nullptr;4012        combinedDerivedType = localSymbol;4013      }4014    }4015    if (!localGeneric && !useGeneric) {4016      return; // both symbols are derived types; done4017    }4018  }4019 4020  auto AreSameModuleProcOrBothInterfaces{[](const Symbol &p1,4021                                             const Symbol &p2) {4022    if (IsProcedure(p1) && !IsPointer(p1) && IsProcedure(p2) &&4023        !IsPointer(p2)) {4024      auto classification{ClassifyProcedure(p1)};4025      if (classification == ClassifyProcedure(p2)) {4026        if (classification == ProcedureDefinitionClass::External) {4027          const auto *subp1{p1.detailsIf<SubprogramDetails>()};4028          const auto *subp2{p2.detailsIf<SubprogramDetails>()};4029          return subp1 && subp1->isInterface() && subp2 && subp2->isInterface();4030        } else if (classification == ProcedureDefinitionClass::Module) {4031          return AreSameModuleSymbol(p1, p2);4032        }4033      }4034    }4035    return false;4036  }};4037 4038  auto AreSameProcedure{[&](const Symbol &p1, const Symbol &p2) {4039    if (&p1.GetUltimate() == &p2.GetUltimate()) {4040      return true;4041    } else if (p1.name() != p2.name()) {4042      return false;4043    } else if (p1.attrs().test(Attr::INTRINSIC) ||4044        p2.attrs().test(Attr::INTRINSIC)) {4045      return p1.attrs().test(Attr::INTRINSIC) &&4046          p2.attrs().test(Attr::INTRINSIC);4047    } else if (AreSameModuleProcOrBothInterfaces(p1, p2)) {4048      // Both are external interfaces, perhaps to the same procedure,4049      // or both are module procedures from modules with the same name.4050      auto p1Chars{evaluate::characteristics::Procedure::Characterize(4051          p1, GetFoldingContext())};4052      auto p2Chars{evaluate::characteristics::Procedure::Characterize(4053          p2, GetFoldingContext())};4054      return p1Chars && p2Chars && *p1Chars == *p2Chars;4055    } else {4056      return false;4057    }4058  }};4059 4060  // When two non-generic procedures arrived, try to combine them.4061  const Symbol *combinedProcedure{nullptr};4062  if (!localProcedure) {4063    combinedProcedure = useProcedure;4064  } else if (!useProcedure) {4065    combinedProcedure = localProcedure;4066  } else {4067    if (AreSameProcedure(4068            localProcedure->GetUltimate(), useProcedure->GetUltimate())) {4069      if (!localGeneric && !useGeneric) {4070        return; // both symbols are non-generic procedures4071      }4072      combinedProcedure = localProcedure;4073    }4074  }4075 4076  // Prepare to merge generics4077  bool cantCombine{false};4078  if (localGeneric) {4079    if (useGeneric || useDerivedType) {4080    } else if (&useUltimate == &BypassGeneric(localUltimate).GetUltimate()) {4081      return; // nothing to do; used subprogram is local's specific4082    } else if (useUltimate.attrs().test(Attr::INTRINSIC) &&4083        useUltimate.name() == localSymbol->name()) {4084      return; // local generic can extend intrinsic4085    } else {4086      for (const auto &ref : localGeneric->specificProcs()) {4087        if (&ref->GetUltimate() == &useUltimate) {4088          return; // used non-generic is already a specific of local generic4089        }4090      }4091      cantCombine = true;4092    }4093  } else if (useGeneric) {4094    if (localDerivedType) {4095    } else if (&localUltimate == &BypassGeneric(useUltimate).GetUltimate() ||4096        (localSymbol->attrs().test(Attr::INTRINSIC) &&4097            localUltimate.name() == useUltimate.name())) {4098      // Local is the specific of the used generic or an intrinsic with the4099      // same name; replace it.4100      EraseSymbol(*localSymbol);4101      Symbol &newSymbol{MakeSymbol(localName,4102          useUltimate.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE},4103          UseDetails{localName, useUltimate})};4104      newSymbol.flags() = useSymbol.flags();4105      return;4106    } else {4107      for (const auto &ref : useGeneric->specificProcs()) {4108        if (&ref->GetUltimate() == &localUltimate) {4109          return; // local non-generic is already a specific of used generic4110        }4111      }4112      cantCombine = true;4113    }4114  } else {4115    cantCombine = true;4116  }4117 4118  // If symbols are not combinable, create a use error.4119  if (cantCombine) {4120    if (!ConvertToUseError(*localSymbol, location, useSymbol)) {4121      Say(location,4122          "Cannot use-associate '%s'; it is already declared in this scope"_err_en_US,4123          localName)4124          .Attach(localSymbol->name(), "Previous declaration of '%s'"_en_US,4125              localName);4126    }4127    return;4128  }4129 4130  // At this point, there must be at least one generic interface.4131  CHECK(localGeneric || (useGeneric && (localDerivedType || localProcedure)));4132 4133  // Ensure that a use-associated specific procedure that is a procedure4134  // pointer is properly represented as a USE association of an entity.4135  if (IsProcedurePointer(useProcedure)) {4136    Symbol &combined{currScope().MakeSymbol(localSymbol->name(),4137        useProcedure->attrs(), UseDetails{localName, *useProcedure})};4138    combined.flags() |= useProcedure->flags();4139    combinedProcedure = &combined;4140  }4141 4142  if (localGeneric) {4143    // Create a local copy of a previously use-associated generic so that4144    // it can be locally extended without corrupting the original.4145    if (localSymbol->has<UseDetails>()) {4146      GenericDetails generic;4147      generic.CopyFrom(DEREF(localGeneric));4148      EraseSymbol(*localSymbol);4149      Symbol &newSymbol{MakeSymbol(4150          localSymbol->name(), localSymbol->attrs(), std::move(generic))};4151      newSymbol.flags() = localSymbol->flags();4152      localGeneric = &newSymbol.get<GenericDetails>();4153      localGeneric->AddUse(*localSymbol);4154      localSymbol = &newSymbol;4155    }4156    if (useGeneric) {4157      // Combine two use-associated generics.4158      localSymbol->attrs() =4159          useSymbol.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE};4160      localSymbol->flags() = useSymbol.flags();4161      AddGenericUse(*localGeneric, localName, useUltimate);4162      // Don't duplicate specific procedures.4163      std::size_t originalLocalSpecifics{localGeneric->specificProcs().size()};4164      std::size_t useSpecifics{useGeneric->specificProcs().size()};4165      CHECK(originalLocalSpecifics == localGeneric->bindingNames().size());4166      CHECK(useSpecifics == useGeneric->bindingNames().size());4167      std::size_t j{0};4168      for (const Symbol &useSpecific : useGeneric->specificProcs()) {4169        SourceName useBindingName{useGeneric->bindingNames()[j++]};4170        bool isDuplicate{false};4171        std::size_t k{0};4172        for (const Symbol &localSpecific : localGeneric->specificProcs()) {4173          if (localGeneric->bindingNames()[k++] == useBindingName &&4174              AreSameProcedure(localSpecific, useSpecific)) {4175            isDuplicate = true;4176            break;4177          }4178        }4179        if (!isDuplicate) {4180          localGeneric->AddSpecificProc(useSpecific, useBindingName);4181        }4182      }4183    }4184    localGeneric->clear_derivedType();4185    if (combinedDerivedType) {4186      localGeneric->set_derivedType(*const_cast<Symbol *>(combinedDerivedType));4187    }4188    localGeneric->clear_specific();4189    if (combinedProcedure) {4190      localGeneric->set_specific(*const_cast<Symbol *>(combinedProcedure));4191    }4192  } else {4193    CHECK(localSymbol->has<UseDetails>());4194    // Create a local copy of the use-associated generic, then extend it4195    // with the combined derived type &/or non-generic procedure.4196    GenericDetails generic;4197    generic.CopyFrom(*useGeneric);4198    EraseSymbol(*localSymbol);4199    Symbol &newSymbol{MakeSymbol(localName,4200        useUltimate.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE},4201        std::move(generic))};4202    newSymbol.flags() = useUltimate.flags();4203    auto &newUseGeneric{newSymbol.get<GenericDetails>()};4204    AddGenericUse(newUseGeneric, localName, useUltimate);4205    newUseGeneric.AddUse(*localSymbol);4206    if (combinedDerivedType) {4207      if (const auto *oldDT{newUseGeneric.derivedType()}) {4208        CHECK(&oldDT->GetUltimate() == &combinedDerivedType->GetUltimate());4209      } else {4210        newUseGeneric.set_derivedType(4211            *const_cast<Symbol *>(combinedDerivedType));4212      }4213    }4214    if (combinedProcedure) {4215      newUseGeneric.set_specific(*const_cast<Symbol *>(combinedProcedure));4216    }4217  }4218}4219 4220void ModuleVisitor::AddUse(const GenericSpecInfo &info) {4221  if (useModuleScope_) {4222    const auto &name{info.symbolName()};4223    auto rename{AddUse(name, name, FindInScope(*useModuleScope_, name))};4224    info.Resolve(rename.use);4225  }4226}4227 4228// Create a UseDetails symbol for this USE and add it to generic4229Symbol &ModuleVisitor::AddGenericUse(4230    GenericDetails &generic, const SourceName &name, const Symbol &useSymbol) {4231  Symbol &newSymbol{4232      currScope().MakeSymbol(name, {}, UseDetails{name, useSymbol})};4233  generic.AddUse(newSymbol);4234  return newSymbol;4235}4236 4237// Enforce F'2023 C1406 as a warning4238void ModuleVisitor::AddAndCheckModuleUse(SourceName name, bool isIntrinsic) {4239  if (isIntrinsic) {4240    if (auto iter{nonIntrinsicUses_.find(name)};4241        iter != nonIntrinsicUses_.end()) {4242      if (auto *msg{context().Warn(common::LanguageFeature::MiscUseExtensions,4243              name,4244              "Should not USE the intrinsic module '%s' in the same scope as a USE of the non-intrinsic module"_port_en_US,4245              name)}) {4246        msg->Attach(*iter, "Previous USE of '%s'"_en_US, *iter);4247      }4248    }4249    intrinsicUses_.insert(name);4250  } else {4251    if (auto iter{intrinsicUses_.find(name)}; iter != intrinsicUses_.end()) {4252      if (auto *msg{context().Warn(common::LanguageFeature::MiscUseExtensions,4253              name,4254              "Should not USE the non-intrinsic module '%s' in the same scope as a USE of the intrinsic module"_port_en_US,4255              name)}) {4256        msg->Attach(*iter, "Previous USE of '%s'"_en_US, *iter);4257      }4258    }4259    nonIntrinsicUses_.insert(name);4260  }4261}4262 4263bool ModuleVisitor::BeginSubmodule(4264    const parser::Name &name, const parser::ParentIdentifier &parentId) {4265  const auto &ancestorName{std::get<parser::Name>(parentId.t)};4266  Scope *parentScope{nullptr};4267  Scope *ancestor{FindModule(ancestorName, false /*not intrinsic*/)};4268  if (ancestor) {4269    if (const auto &parentName{4270            std::get<std::optional<parser::Name>>(parentId.t)}) {4271      parentScope = FindModule(*parentName, false /*not intrinsic*/, ancestor);4272    } else {4273      parentScope = ancestor;4274    }4275  }4276  if (parentScope) {4277    PushScope(*parentScope);4278  } else {4279    // Error recovery: there's no ancestor scope, so create a dummy one to4280    // hold the submodule's scope.4281    SourceName dummyName{context().GetTempName(currScope())};4282    Symbol &dummySymbol{MakeSymbol(dummyName, Attrs{}, ModuleDetails{false})};4283    PushScope(Scope::Kind::Module, &dummySymbol);4284    parentScope = &currScope();4285  }4286  BeginModule(name, true);4287  set_inheritFromParent(false); // submodules don't inherit parents' implicits4288  if (ancestor && !ancestor->AddSubmodule(name.source, currScope())) {4289    Say(name, "Module '%s' already has a submodule named '%s'"_err_en_US,4290        ancestorName.source, name.source);4291  }4292  return true;4293}4294 4295void ModuleVisitor::BeginModule(const parser::Name &name, bool isSubmodule) {4296  // Submodule symbols are not visible in their parents' scopes.4297  Symbol &symbol{isSubmodule ? Resolve(name,4298                                   currScope().MakeSymbol(name.source, Attrs{},4299                                       ModuleDetails{true}))4300                             : MakeSymbol(name, ModuleDetails{false})};4301  auto &details{symbol.get<ModuleDetails>()};4302  PushScope(Scope::Kind::Module, &symbol);4303  details.set_scope(&currScope());4304  prevAccessStmt_ = std::nullopt;4305}4306 4307// Find a module or submodule by name and return its scope.4308// If ancestor is present, look for a submodule of that ancestor module.4309// May have to read a .mod file to find it.4310// If an error occurs, report it and return nullptr.4311Scope *ModuleVisitor::FindModule(const parser::Name &name,4312    std::optional<bool> isIntrinsic, Scope *ancestor) {4313  ModFileReader reader{context()};4314  Scope *scope{4315      reader.Read(name.source, isIntrinsic, ancestor, /*silent=*/false)};4316  if (scope) {4317    if (DoesScopeContain(scope, currScope())) { // 14.2.2(1)4318      std::optional<SourceName> submoduleName;4319      if (const Scope * container{FindModuleOrSubmoduleContaining(currScope())};4320          container && container->IsSubmodule()) {4321        submoduleName = container->GetName();4322      }4323      if (submoduleName) {4324        Say(name.source,4325            "Module '%s' cannot USE itself from its own submodule '%s'"_err_en_US,4326            name.source, *submoduleName);4327      } else {4328        Say(name, "Module '%s' cannot USE itself"_err_en_US);4329      }4330    }4331    Resolve(name, scope->symbol());4332  }4333  return scope;4334}4335 4336void ModuleVisitor::ApplyDefaultAccess() {4337  const auto *moduleDetails{4338      DEREF(currScope().symbol()).detailsIf<ModuleDetails>()};4339  CHECK(moduleDetails);4340  Attr defaultAttr{4341      DEREF(moduleDetails).isDefaultPrivate() ? Attr::PRIVATE : Attr::PUBLIC};4342  for (auto &pair : currScope()) {4343    Symbol &symbol{*pair.second};4344    if (!symbol.attrs().HasAny({Attr::PUBLIC, Attr::PRIVATE})) {4345      Attr attr{defaultAttr};4346      if (auto *generic{symbol.detailsIf<GenericDetails>()}) {4347        if (generic->derivedType()) {4348          // If a generic interface has a derived type of the same4349          // name that has an explicit accessibility attribute, then4350          // the generic must have the same accessibility.4351          if (generic->derivedType()->attrs().test(Attr::PUBLIC)) {4352            attr = Attr::PUBLIC;4353          } else if (generic->derivedType()->attrs().test(Attr::PRIVATE)) {4354            attr = Attr::PRIVATE;4355          }4356        }4357      }4358      SetImplicitAttr(symbol, attr);4359    }4360  }4361}4362 4363// InterfaceVistor implementation4364 4365bool InterfaceVisitor::Pre(const parser::InterfaceStmt &x) {4366  bool isAbstract{std::holds_alternative<parser::Abstract>(x.u)};4367  genericInfo_.emplace(/*isInterface*/ true, isAbstract);4368  return BeginAttrs();4369}4370 4371void InterfaceVisitor::Post(const parser::InterfaceStmt &) { EndAttrs(); }4372 4373void InterfaceVisitor::Post(const parser::EndInterfaceStmt &) {4374  ResolveNewSpecifics();4375  genericInfo_.pop();4376}4377 4378// Create a symbol in genericSymbol_ for this GenericSpec.4379bool InterfaceVisitor::Pre(const parser::GenericSpec &x) {4380  if (auto *symbol{FindInScope(GenericSpecInfo{x}.symbolName())}) {4381    SetGenericSymbol(*symbol);4382  }4383  return false;4384}4385 4386bool InterfaceVisitor::Pre(const parser::ProcedureStmt &x) {4387  if (!isGeneric()) {4388    Say("A PROCEDURE statement is only allowed in a generic interface block"_err_en_US);4389  } else {4390    auto kind{std::get<parser::ProcedureStmt::Kind>(x.t)};4391    const auto &names{std::get<std::list<parser::Name>>(x.t)};4392    AddSpecificProcs(names, kind);4393  }4394  return false;4395}4396 4397bool InterfaceVisitor::Pre(const parser::GenericStmt &) {4398  genericInfo_.emplace(/*isInterface*/ false);4399  return BeginAttrs();4400}4401void InterfaceVisitor::Post(const parser::GenericStmt &x) {4402  auto attrs{EndAttrs()};4403  if (Symbol * symbol{GetGenericInfo().symbol}) {4404    SetExplicitAttrs(*symbol, attrs);4405  }4406  const auto &names{std::get<std::list<parser::Name>>(x.t)};4407  AddSpecificProcs(names, ProcedureKind::Procedure);4408  ResolveNewSpecifics();4409  genericInfo_.pop();4410}4411 4412bool InterfaceVisitor::inInterfaceBlock() const {4413  return !genericInfo_.empty() && GetGenericInfo().isInterface;4414}4415bool InterfaceVisitor::isGeneric() const {4416  return !genericInfo_.empty() && GetGenericInfo().symbol;4417}4418bool InterfaceVisitor::isAbstract() const {4419  return !genericInfo_.empty() && GetGenericInfo().isAbstract;4420}4421 4422void InterfaceVisitor::AddSpecificProcs(4423    const std::list<parser::Name> &names, ProcedureKind kind) {4424  if (Symbol * symbol{GetGenericInfo().symbol};4425      symbol && symbol->has<GenericDetails>()) {4426    for (const auto &name : names) {4427      specificsForGenericProcs_.emplace(symbol, std::make_pair(&name, kind));4428      genericsForSpecificProcs_.emplace(name.source, symbol);4429    }4430  }4431}4432 4433// By now we should have seen all specific procedures referenced by name in4434// this generic interface. Resolve those names to symbols.4435void GenericHandler::ResolveSpecificsInGeneric(4436    Symbol &generic, bool isEndOfSpecificationPart) {4437  auto &details{generic.get<GenericDetails>()};4438  UnorderedSymbolSet symbolsSeen;4439  for (const Symbol &symbol : details.specificProcs()) {4440    symbolsSeen.insert(symbol.GetUltimate());4441  }4442  auto range{specificsForGenericProcs_.equal_range(&generic)};4443  SpecificProcMapType retain;4444  for (auto it{range.first}; it != range.second; ++it) {4445    const parser::Name *name{it->second.first};4446    auto kind{it->second.second};4447    const Symbol *symbol{isEndOfSpecificationPart4448            ? FindSymbol(*name)4449            : FindInScope(generic.owner(), *name)};4450    ProcedureDefinitionClass defClass{ProcedureDefinitionClass::None};4451    const Symbol *specific{symbol};4452    const Symbol *ultimate{nullptr};4453    if (symbol) {4454      // Subtlety: when *symbol is a use- or host-association, the specific4455      // procedure that is recorded in the GenericDetails below must be *symbol,4456      // not the specific procedure shadowed by a generic, because that specific4457      // procedure may be a symbol from another module and its name unavailable4458      // to emit to a module file.4459      const Symbol &bypassed{BypassGeneric(*symbol)};4460      if (symbol == &symbol->GetUltimate()) {4461        specific = &bypassed;4462      }4463      ultimate = &bypassed.GetUltimate();4464      defClass = ClassifyProcedure(*ultimate);4465    }4466    std::optional<MessageFixedText> error;4467    if (defClass == ProcedureDefinitionClass::Module) {4468      // ok4469    } else if (kind == ProcedureKind::ModuleProcedure) {4470      error = "'%s' is not a module procedure"_err_en_US;4471    } else {4472      switch (defClass) {4473      case ProcedureDefinitionClass::Intrinsic:4474      case ProcedureDefinitionClass::External:4475      case ProcedureDefinitionClass::Internal:4476      case ProcedureDefinitionClass::Dummy:4477      case ProcedureDefinitionClass::Pointer:4478        break;4479      case ProcedureDefinitionClass::None:4480        error = "'%s' is not a procedure"_err_en_US;4481        break;4482      default:4483        error =4484            "'%s' is not a procedure that can appear in a generic interface"_err_en_US;4485        break;4486      }4487    }4488    if (error) {4489      if (isEndOfSpecificationPart) {4490        Say(*name, std::move(*error));4491      } else {4492        // possible forward reference, catch it later4493        retain.emplace(&generic, std::make_pair(name, kind));4494      }4495    } else if (!ultimate) {4496    } else if (symbolsSeen.insert(*ultimate).second /*true if added*/) {4497      // When a specific procedure is a USE association, that association4498      // is saved in the generic's specifics, not its ultimate symbol,4499      // so that module file output of interfaces can distinguish them.4500      details.AddSpecificProc(*specific, name->source);4501    } else if (specific == ultimate) {4502      Say(name->source,4503          "Procedure '%s' is already specified in generic '%s'"_err_en_US,4504          name->source, MakeOpName(generic.name()));4505    } else {4506      Say(name->source,4507          "Procedure '%s' from module '%s' is already specified in generic '%s'"_err_en_US,4508          ultimate->name(), ultimate->owner().GetName().value(),4509          MakeOpName(generic.name()));4510    }4511  }4512  specificsForGenericProcs_.erase(range.first, range.second);4513  specificsForGenericProcs_.merge(std::move(retain));4514}4515 4516void GenericHandler::DeclaredPossibleSpecificProc(Symbol &proc) {4517  auto range{genericsForSpecificProcs_.equal_range(proc.name())};4518  for (auto iter{range.first}; iter != range.second; ++iter) {4519    ResolveSpecificsInGeneric(*iter->second, false);4520  }4521}4522 4523void InterfaceVisitor::ResolveNewSpecifics() {4524  if (Symbol * generic{genericInfo_.top().symbol};4525      generic && generic->has<GenericDetails>()) {4526    ResolveSpecificsInGeneric(*generic, false);4527  }4528}4529 4530// Mixed interfaces are allowed by the standard.4531// If there is a derived type with the same name, they must all be functions.4532void InterfaceVisitor::CheckGenericProcedures(Symbol &generic) {4533  ResolveSpecificsInGeneric(generic, true);4534  auto &details{generic.get<GenericDetails>()};4535  if (auto *proc{details.CheckSpecific()}) {4536    context().Warn(common::UsageWarning::HomonymousSpecific,4537        proc->name().begin() > generic.name().begin() ? proc->name()4538                                                      : generic.name(),4539        "'%s' should not be the name of both a generic interface and a procedure unless it is a specific procedure of the generic"_warn_en_US,4540        generic.name());4541  }4542  auto &specifics{details.specificProcs()};4543  if (specifics.empty()) {4544    if (details.derivedType()) {4545      generic.set(Symbol::Flag::Function);4546    }4547    return;4548  }4549  const Symbol *function{nullptr};4550  const Symbol *subroutine{nullptr};4551  for (const Symbol &specific : specifics) {4552    if (!function && specific.test(Symbol::Flag::Function)) {4553      function = &specific;4554    } else if (!subroutine && specific.test(Symbol::Flag::Subroutine)) {4555      subroutine = &specific;4556      if (details.derivedType() &&4557          context().ShouldWarn(4558              common::LanguageFeature::SubroutineAndFunctionSpecifics) &&4559          !InModuleFile()) {4560        SayDerivedType(generic.name(),4561            "Generic interface '%s' should only contain functions due to derived type with same name"_warn_en_US,4562            *details.derivedType()->GetUltimate().scope())4563            .set_languageFeature(4564                common::LanguageFeature::SubroutineAndFunctionSpecifics);4565      }4566    }4567    if (function && subroutine) { // F'2023 C15144568      if (auto *msg{context().Warn(4569              common::LanguageFeature::SubroutineAndFunctionSpecifics,4570              generic.name(),4571              "Generic interface '%s' has both a function and a subroutine"_warn_en_US,4572              generic.name())}) {4573        msg->Attach(function->name(), "Function declaration"_en_US)4574            .Attach(subroutine->name(), "Subroutine declaration"_en_US);4575      }4576      break;4577    }4578  }4579  if (function && !subroutine) {4580    generic.set(Symbol::Flag::Function);4581  } else if (subroutine && !function) {4582    generic.set(Symbol::Flag::Subroutine);4583  }4584}4585 4586// SubprogramVisitor implementation4587 4588// Return false if it is actually an assignment statement.4589bool SubprogramVisitor::HandleStmtFunction(const parser::StmtFunctionStmt &x) {4590  const auto &name{std::get<parser::Name>(x.t)};4591  const DeclTypeSpec *resultType{nullptr};4592  // Look up name: provides return type or tells us if it's an array4593  if (auto *symbol{FindSymbol(name)}) {4594    Symbol &ultimate{symbol->GetUltimate()};4595    if (ultimate.has<ObjectEntityDetails>() ||4596        ultimate.has<AssocEntityDetails>() ||4597        CouldBeDataPointerValuedFunction(&ultimate) ||4598        (&symbol->owner() == &currScope() && IsFunctionResult(*symbol))) {4599      misparsedStmtFuncFound_ = true;4600      return false;4601    }4602    if (IsHostAssociated(*symbol, currScope())) {4603      context().Warn(common::LanguageFeature::StatementFunctionExtensions,4604          name.source,4605          "Name '%s' from host scope should have a type declaration before its local statement function definition"_port_en_US,4606          name.source);4607      MakeSymbol(name, Attrs{}, UnknownDetails{});4608    } else if (auto *entity{ultimate.detailsIf<EntityDetails>()};4609               entity && !ultimate.has<ProcEntityDetails>()) {4610      resultType = entity->type();4611      ultimate.details() = UnknownDetails{}; // will be replaced below4612    } else {4613      misparsedStmtFuncFound_ = true;4614    }4615  }4616  if (misparsedStmtFuncFound_) {4617    Say(name,4618        "'%s' has not been declared as an array or pointer-valued function"_err_en_US);4619    return false;4620  }4621  Symbol *symbol{PushSubprogramScope(name, Symbol::Flag::Function)};4622  if (!symbol) {4623    return false;4624  }4625  symbol->set(Symbol::Flag::StmtFunction);4626  EraseSymbol(*symbol); // removes symbol added by PushSubprogramScope4627  auto &details{symbol->get<SubprogramDetails>()};4628  for (const auto &dummyName : std::get<std::list<parser::Name>>(x.t)) {4629    ObjectEntityDetails dummyDetails{true};4630    if (auto *dummySymbol{FindInScope(currScope().parent(), dummyName)}) {4631      if (auto *d{dummySymbol->GetType()}) {4632        dummyDetails.set_type(*d);4633      }4634    }4635    Symbol &dummy{MakeSymbol(dummyName, std::move(dummyDetails))};4636    ApplyImplicitRules(dummy);4637    details.add_dummyArg(dummy);4638  }4639  ObjectEntityDetails resultDetails;4640  if (resultType) {4641    resultDetails.set_type(*resultType);4642  }4643  resultDetails.set_funcResult(true);4644  Symbol &result{MakeSymbol(name, std::move(resultDetails))};4645  result.flags().set(Symbol::Flag::StmtFunction);4646  ApplyImplicitRules(result);4647  details.set_result(result);4648  // The analysis of the expression that constitutes the body of the4649  // statement function is deferred to FinishSpecificationPart() so that4650  // all declarations and implicit typing are complete.4651  PopScope();4652  return true;4653}4654 4655bool SubprogramVisitor::Pre(const parser::Suffix &suffix) {4656  if (suffix.resultName) {4657    if (IsFunction(currScope())) {4658      if (FuncResultStack::FuncInfo * info{funcResultStack().Top()}) {4659        if (info->inFunctionStmt) {4660          info->resultName = &suffix.resultName.value();4661        } else {4662          // will check the result name in Post(EntryStmt)4663        }4664      }4665    } else {4666      Message &msg{Say(*suffix.resultName,4667          "RESULT(%s) may appear only in a function"_err_en_US)};4668      if (const Symbol * subprogram{InclusiveScope().symbol()}) {4669        msg.Attach(subprogram->name(), "Containing subprogram"_en_US);4670      }4671    }4672  }4673  // LanguageBindingSpec deferred to Post(EntryStmt) or, for FunctionStmt,4674  // all the way to EndSubprogram().4675  return false;4676}4677 4678bool SubprogramVisitor::Pre(const parser::PrefixSpec &x) {4679  // Save this to process after UseStmt and ImplicitPart4680  if (const auto *parsedType{std::get_if<parser::DeclarationTypeSpec>(&x.u)}) {4681    if (FuncResultStack::FuncInfo * info{funcResultStack().Top()}) {4682      if (info->parsedType) { // C15434683        Say(currStmtSource().value_or(info->source),4684            "FUNCTION prefix cannot specify the type more than once"_err_en_US);4685      } else {4686        info->parsedType = parsedType;4687        if (auto at{currStmtSource()}) {4688          info->source = *at;4689        }4690      }4691    } else {4692      Say(currStmtSource().value(),4693          "SUBROUTINE prefix cannot specify a type"_err_en_US);4694    }4695    return false;4696  } else {4697    return true;4698  }4699}4700 4701bool SubprogramVisitor::Pre(const parser::PrefixSpec::Attributes &attrs) {4702  if (auto *subp{currScope().symbol()4703              ? currScope().symbol()->detailsIf<SubprogramDetails>()4704              : nullptr}) {4705    for (auto attr : attrs.v) {4706      if (auto current{subp->cudaSubprogramAttrs()}) {4707        if (attr == *current ||4708            (*current == common::CUDASubprogramAttrs::HostDevice &&4709                (attr == common::CUDASubprogramAttrs::Host ||4710                    attr == common::CUDASubprogramAttrs::Device))) {4711          context().Warn(common::LanguageFeature::RedundantAttribute,4712              currStmtSource().value(),4713              "ATTRIBUTES(%s) appears more than once"_warn_en_US,4714              common::EnumToString(attr));4715        } else if ((attr == common::CUDASubprogramAttrs::Host ||4716                       attr == common::CUDASubprogramAttrs::Device) &&4717            (*current == common::CUDASubprogramAttrs::Host ||4718                *current == common::CUDASubprogramAttrs::Device ||4719                *current == common::CUDASubprogramAttrs::HostDevice)) {4720          // HOST,DEVICE or DEVICE,HOST -> HostDevice4721          subp->set_cudaSubprogramAttrs(4722              common::CUDASubprogramAttrs::HostDevice);4723        } else {4724          Say(currStmtSource().value(),4725              "ATTRIBUTES(%s) conflicts with earlier ATTRIBUTES(%s)"_err_en_US,4726              common::EnumToString(attr), common::EnumToString(*current));4727        }4728      } else {4729        subp->set_cudaSubprogramAttrs(attr);4730      }4731    }4732    if (auto attrs{subp->cudaSubprogramAttrs()}) {4733      if (*attrs == common::CUDASubprogramAttrs::Global ||4734          *attrs == common::CUDASubprogramAttrs::Grid_Global ||4735          *attrs == common::CUDASubprogramAttrs::Device ||4736          *attrs == common::CUDASubprogramAttrs::HostDevice) {4737        const Scope &scope{currScope()};4738        const Scope *mod{FindModuleContaining(scope)};4739        if (mod &&4740            (mod->GetName().value() == "cudadevice" ||4741                mod->GetName().value() == "__cuda_device")) {4742          return false;4743        }4744        // Implicitly USE the cudadevice module by copying its symbols in the4745        // current scope.4746        const Scope &cudaDeviceScope{context().GetCUDADeviceScope()};4747        for (auto sym : cudaDeviceScope.GetSymbols()) {4748          if (!currScope().FindSymbol(sym->name())) {4749            auto &localSymbol{MakeSymbol(4750                sym->name(), Attrs{}, UseDetails{sym->name(), *sym})};4751            localSymbol.flags() = sym->flags();4752          }4753        }4754      }4755    }4756  }4757  return false;4758}4759 4760void SubprogramVisitor::Post(const parser::PrefixSpec::Launch_Bounds &x) {4761  std::vector<std::int64_t> bounds;4762  bool ok{true};4763  for (const auto &sicx : x.v) {4764    if (auto value{evaluate::ToInt64(EvaluateExpr(sicx))}) {4765      bounds.push_back(*value);4766    } else {4767      ok = false;4768    }4769  }4770  if (!ok || bounds.size() < 2 || bounds.size() > 3) {4771    Say(currStmtSource().value(),4772        "Operands of LAUNCH_BOUNDS() must be 2 or 3 integer constants"_err_en_US);4773  } else if (auto *subp{currScope().symbol()4774                     ? currScope().symbol()->detailsIf<SubprogramDetails>()4775                     : nullptr}) {4776    if (subp->cudaLaunchBounds().empty()) {4777      subp->set_cudaLaunchBounds(std::move(bounds));4778    } else {4779      Say(currStmtSource().value(),4780          "LAUNCH_BOUNDS() may only appear once"_err_en_US);4781    }4782  }4783}4784 4785void SubprogramVisitor::Post(const parser::PrefixSpec::Cluster_Dims &x) {4786  std::vector<std::int64_t> dims;4787  bool ok{true};4788  for (const auto &sicx : x.v) {4789    if (auto value{evaluate::ToInt64(EvaluateExpr(sicx))}) {4790      dims.push_back(*value);4791    } else {4792      ok = false;4793    }4794  }4795  if (!ok || dims.size() != 3) {4796    Say(currStmtSource().value(),4797        "Operands of CLUSTER_DIMS() must be three integer constants"_err_en_US);4798  } else if (auto *subp{currScope().symbol()4799                     ? currScope().symbol()->detailsIf<SubprogramDetails>()4800                     : nullptr}) {4801    if (subp->cudaClusterDims().empty()) {4802      subp->set_cudaClusterDims(std::move(dims));4803    } else {4804      Say(currStmtSource().value(),4805          "CLUSTER_DIMS() may only appear once"_err_en_US);4806    }4807  }4808}4809 4810static bool HasModulePrefix(const std::list<parser::PrefixSpec> &prefixes) {4811  for (const auto &prefix : prefixes) {4812    if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) {4813      return true;4814    }4815  }4816  return false;4817}4818 4819bool SubprogramVisitor::Pre(const parser::InterfaceBody::Subroutine &x) {4820  const auto &stmtTuple{4821      std::get<parser::Statement<parser::SubroutineStmt>>(x.t).statement.t};4822  return BeginSubprogram(std::get<parser::Name>(stmtTuple),4823      Symbol::Flag::Subroutine,4824      HasModulePrefix(std::get<std::list<parser::PrefixSpec>>(stmtTuple)));4825}4826void SubprogramVisitor::Post(const parser::InterfaceBody::Subroutine &x) {4827  const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(x.t)};4828  EndSubprogram(stmt.source,4829      &std::get<std::optional<parser::LanguageBindingSpec>>(stmt.statement.t));4830}4831bool SubprogramVisitor::Pre(const parser::InterfaceBody::Function &x) {4832  const auto &stmtTuple{4833      std::get<parser::Statement<parser::FunctionStmt>>(x.t).statement.t};4834  return BeginSubprogram(std::get<parser::Name>(stmtTuple),4835      Symbol::Flag::Function,4836      HasModulePrefix(std::get<std::list<parser::PrefixSpec>>(stmtTuple)));4837}4838void SubprogramVisitor::Post(const parser::InterfaceBody::Function &x) {4839  const auto &stmt{std::get<parser::Statement<parser::FunctionStmt>>(x.t)};4840  const auto &maybeSuffix{4841      std::get<std::optional<parser::Suffix>>(stmt.statement.t)};4842  EndSubprogram(stmt.source, maybeSuffix ? &maybeSuffix->binding : nullptr);4843}4844 4845bool SubprogramVisitor::Pre(const parser::SubroutineStmt &stmt) {4846  BeginAttrs();4847  Walk(std::get<std::list<parser::PrefixSpec>>(stmt.t));4848  Walk(std::get<parser::Name>(stmt.t));4849  Walk(std::get<std::list<parser::DummyArg>>(stmt.t));4850  // Don't traverse the LanguageBindingSpec now; it's deferred to EndSubprogram.4851  Symbol &symbol{PostSubprogramStmt()};4852  SubprogramDetails &details{symbol.get<SubprogramDetails>()};4853  for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {4854    if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {4855      CreateDummyArgument(details, *dummyName);4856    } else {4857      details.add_alternateReturn();4858    }4859  }4860  return false;4861}4862bool SubprogramVisitor::Pre(const parser::FunctionStmt &) {4863  FuncResultStack::FuncInfo &info{DEREF(funcResultStack().Top())};4864  CHECK(!info.inFunctionStmt);4865  info.inFunctionStmt = true;4866  if (auto at{currStmtSource()}) {4867    info.source = *at;4868  }4869  return BeginAttrs();4870}4871bool SubprogramVisitor::Pre(const parser::EntryStmt &) { return BeginAttrs(); }4872 4873void SubprogramVisitor::Post(const parser::FunctionStmt &stmt) {4874  const auto &name{std::get<parser::Name>(stmt.t)};4875  Symbol &symbol{PostSubprogramStmt()};4876  SubprogramDetails &details{symbol.get<SubprogramDetails>()};4877  for (const auto &dummyName : std::get<std::list<parser::Name>>(stmt.t)) {4878    CreateDummyArgument(details, dummyName);4879  }4880  const parser::Name *funcResultName;4881  FuncResultStack::FuncInfo &info{DEREF(funcResultStack().Top())};4882  CHECK(info.inFunctionStmt);4883  info.inFunctionStmt = false;4884  bool distinctResultName{4885      info.resultName && info.resultName->source != name.source};4886  if (distinctResultName) {4887    // Note that RESULT is ignored if it has the same name as the function.4888    // The symbol created by PushScope() is retained as a place-holder4889    // for error detection.4890    funcResultName = info.resultName;4891  } else {4892    EraseSymbol(name); // was added by PushScope()4893    funcResultName = &name;4894  }4895  if (details.isFunction()) {4896    CHECK(context().HasError(currScope().symbol()));4897  } else {4898    // RESULT(x) can be the same explicitly-named RESULT(x) as an ENTRY4899    // statement.4900    Symbol *result{nullptr};4901    if (distinctResultName) {4902      if (auto iter{currScope().find(funcResultName->source)};4903          iter != currScope().end()) {4904        Symbol &entryResult{*iter->second};4905        if (IsFunctionResult(entryResult)) {4906          result = &entryResult;4907        }4908      }4909    }4910    if (result) {4911      Resolve(*funcResultName, *result);4912    } else {4913      // add function result to function scope4914      EntityDetails funcResultDetails;4915      funcResultDetails.set_funcResult(true);4916      result = &MakeSymbol(*funcResultName, std::move(funcResultDetails));4917    }4918    info.resultSymbol = result;4919    details.set_result(*result);4920  }4921  // C1560.4922  if (info.resultName && !distinctResultName) {4923    context().Warn(common::UsageWarning::HomonymousResult,4924        info.resultName->source,4925        "The function name should not appear in RESULT; references to '%s' inside the function will be considered as references to the result only"_warn_en_US,4926        name.source);4927    // RESULT name was ignored above, the only side effect from doing so will be4928    // the inability to make recursive calls. The related parser::Name is still4929    // resolved to the created function result symbol because every parser::Name4930    // should be resolved to avoid internal errors.4931    Resolve(*info.resultName, info.resultSymbol);4932  }4933  name.symbol = &symbol; // must not be function result symbol4934  // Clear the RESULT() name now in case an ENTRY statement in the implicit-part4935  // has a RESULT() suffix.4936  info.resultName = nullptr;4937}4938 4939Symbol &SubprogramVisitor::PostSubprogramStmt() {4940  Symbol &symbol{*currScope().symbol()};4941  SetExplicitAttrs(symbol, EndAttrs());4942  if (symbol.attrs().test(Attr::MODULE)) {4943    symbol.attrs().set(Attr::EXTERNAL, false);4944    symbol.implicitAttrs().set(Attr::EXTERNAL, false);4945  }4946  return symbol;4947}4948 4949void SubprogramVisitor::Post(const parser::EntryStmt &stmt) {4950  if (const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)}) {4951    Walk(suffix->binding);4952  }4953  PostEntryStmt(stmt);4954  EndAttrs();4955}4956 4957void SubprogramVisitor::CreateDummyArgument(4958    SubprogramDetails &details, const parser::Name &name) {4959  Symbol *dummy{FindInScope(name)};4960  if (dummy) {4961    if (IsDummy(*dummy)) {4962      if (dummy->test(Symbol::Flag::EntryDummyArgument)) {4963        dummy->set(Symbol::Flag::EntryDummyArgument, false);4964      } else {4965        Say(name,4966            "'%s' appears more than once as a dummy argument name in this subprogram"_err_en_US,4967            name.source);4968        return;4969      }4970    } else {4971      SayWithDecl(name, *dummy,4972          "'%s' may not appear as a dummy argument name in this subprogram"_err_en_US);4973      return;4974    }4975  } else {4976    dummy = &MakeSymbol(name, EntityDetails{true});4977  }4978  details.add_dummyArg(DEREF(dummy));4979}4980 4981void SubprogramVisitor::CreateEntry(4982    const parser::EntryStmt &stmt, Symbol &subprogram) {4983  const auto &entryName{std::get<parser::Name>(stmt.t)};4984  Scope &outer{currScope().parent()};4985  Symbol::Flag subpFlag{subprogram.test(Symbol::Flag::Function)4986          ? Symbol::Flag::Function4987          : Symbol::Flag::Subroutine};4988  Attrs attrs;4989  const auto &suffix{std::get<std::optional<parser::Suffix>>(stmt.t)};4990  bool hasGlobalBindingName{outer.IsGlobal() && suffix && suffix->binding &&4991      std::get<std::optional<parser::ScalarDefaultCharConstantExpr>>(4992          suffix->binding->t)4993          .has_value()};4994  if (!hasGlobalBindingName) {4995    if (Symbol * extant{FindSymbol(outer, entryName)}) {4996      if (!HandlePreviousCalls(entryName, *extant, subpFlag)) {4997        if (outer.IsTopLevel()) {4998          Say2(entryName,4999              "'%s' is already defined as a global identifier"_err_en_US,5000              *extant, "Previous definition of '%s'"_en_US);5001        } else {5002          SayAlreadyDeclared(entryName, *extant);5003        }5004        return;5005      }5006      attrs = extant->attrs();5007    }5008  }5009  std::optional<SourceName> distinctResultName;5010  if (suffix && suffix->resultName &&5011      suffix->resultName->source != entryName.source) {5012    distinctResultName = suffix->resultName->source;5013  }5014  if (outer.IsModule() && !attrs.test(Attr::PRIVATE)) {5015    attrs.set(Attr::PUBLIC);5016  }5017  Symbol *entrySymbol{nullptr};5018  if (hasGlobalBindingName) {5019    // Hide the entry's symbol in a new anonymous global scope so5020    // that its name doesn't clash with anything.5021    Symbol &symbol{MakeSymbol(outer, context().GetTempName(outer), Attrs{})};5022    symbol.set_details(MiscDetails{MiscDetails::Kind::ScopeName});5023    Scope &hidden{outer.MakeScope(Scope::Kind::Global, &symbol)};5024    entrySymbol = &MakeSymbol(hidden, entryName.source, attrs);5025  } else {5026    entrySymbol = FindInScope(outer, entryName.source);5027    if (entrySymbol) {5028      if (auto *generic{entrySymbol->detailsIf<GenericDetails>()}) {5029        if (auto *specific{generic->specific()}) {5030          // Forward reference to ENTRY from a generic interface5031          entrySymbol = specific;5032          CheckDuplicatedAttrs(entryName.source, *entrySymbol, attrs);5033          SetExplicitAttrs(*entrySymbol, attrs);5034        }5035      }5036    } else {5037      entrySymbol = &MakeSymbol(outer, entryName.source, attrs);5038    }5039  }5040  SubprogramDetails entryDetails;5041  entryDetails.set_entryScope(currScope());5042  entrySymbol->set(subpFlag);5043  if (subpFlag == Symbol::Flag::Function) {5044    Symbol *result{nullptr};5045    EntityDetails resultDetails;5046    resultDetails.set_funcResult(true);5047    if (distinctResultName) {5048      // An explicit RESULT() can also be an explicit RESULT()5049      // of the function or another ENTRY.5050      if (auto iter{currScope().find(suffix->resultName->source)};5051          iter != currScope().end()) {5052        result = &*iter->second;5053      }5054      if (!result) {5055        result =5056            &MakeSymbol(*distinctResultName, Attrs{}, std::move(resultDetails));5057      } else if (!result->has<EntityDetails>()) {5058        Say(*distinctResultName,5059            "ENTRY cannot have RESULT(%s) that is not a variable"_err_en_US,5060            *distinctResultName)5061            .Attach(result->name(), "Existing declaration of '%s'"_en_US,5062                result->name());5063        result = nullptr;5064      }5065      if (result) {5066        Resolve(*suffix->resultName, *result);5067      }5068    } else {5069      result = &MakeSymbol(entryName.source, Attrs{}, std::move(resultDetails));5070    }5071    if (result) {5072      entryDetails.set_result(*result);5073    }5074  }5075  if (subpFlag == Symbol::Flag::Subroutine || distinctResultName) {5076    Symbol &assoc{MakeSymbol(entryName.source)};5077    assoc.set_details(HostAssocDetails{*entrySymbol});5078    assoc.set(Symbol::Flag::Subroutine);5079  }5080  Resolve(entryName, *entrySymbol);5081  std::set<SourceName> dummies;5082  for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {5083    if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {5084      auto pair{dummies.insert(dummyName->source)};5085      if (!pair.second) {5086        Say(*dummyName,5087            "'%s' appears more than once as a dummy argument name in this ENTRY statement"_err_en_US,5088            dummyName->source);5089        continue;5090      }5091      Symbol *dummy{FindInScope(*dummyName)};5092      if (dummy) {5093        if (!IsDummy(*dummy)) {5094          evaluate::AttachDeclaration(5095              Say(*dummyName,5096                  "'%s' may not appear as a dummy argument name in this ENTRY statement"_err_en_US,5097                  dummyName->source),5098              *dummy);5099          continue;5100        }5101      } else {5102        dummy = &MakeSymbol(*dummyName, EntityDetails{true});5103        dummy->set(Symbol::Flag::EntryDummyArgument);5104      }5105      entryDetails.add_dummyArg(DEREF(dummy));5106    } else if (subpFlag == Symbol::Flag::Function) { // C15735107      Say(entryName,5108          "ENTRY in a function may not have an alternate return dummy argument"_err_en_US);5109      break;5110    } else {5111      entryDetails.add_alternateReturn();5112    }5113  }5114  entrySymbol->set_details(std::move(entryDetails));5115}5116 5117void SubprogramVisitor::PostEntryStmt(const parser::EntryStmt &stmt) {5118  // The entry symbol should have already been created and resolved5119  // in CreateEntry(), called by BeginSubprogram(), with one exception (below).5120  const auto &name{std::get<parser::Name>(stmt.t)};5121  Scope &inclusiveScope{InclusiveScope()};5122  if (!name.symbol) {5123    if (inclusiveScope.kind() != Scope::Kind::Subprogram) {5124      Say(name.source,5125          "ENTRY '%s' may appear only in a subroutine or function"_err_en_US,5126          name.source);5127    } else if (FindSeparateModuleSubprogramInterface(inclusiveScope.symbol())) {5128      Say(name.source,5129          "ENTRY '%s' may not appear in a separate module procedure"_err_en_US,5130          name.source);5131    } else {5132      // C1571 - entry is nested, so was not put into the program tree; error5133      // is emitted from MiscChecker in semantics.cpp.5134    }5135    return;5136  }5137  Symbol &entrySymbol{*name.symbol};5138  if (context().HasError(entrySymbol)) {5139    return;5140  }5141  if (!entrySymbol.has<SubprogramDetails>()) {5142    SayAlreadyDeclared(name, entrySymbol);5143    return;5144  }5145  SubprogramDetails &entryDetails{entrySymbol.get<SubprogramDetails>()};5146  CHECK(entryDetails.entryScope() == &inclusiveScope);5147  SetCUDADataAttr(name.source, entrySymbol, cudaDataAttr());5148  entrySymbol.attrs() |= GetAttrs();5149  SetBindNameOn(entrySymbol);5150  for (const auto &dummyArg : std::get<std::list<parser::DummyArg>>(stmt.t)) {5151    if (const auto *dummyName{std::get_if<parser::Name>(&dummyArg.u)}) {5152      if (Symbol * dummy{FindInScope(*dummyName)}) {5153        if (dummy->test(Symbol::Flag::EntryDummyArgument)) {5154          const auto *subp{dummy->detailsIf<SubprogramDetails>()};5155          if (subp && subp->isInterface()) { // ok5156          } else if (!dummy->has<EntityDetails>() &&5157              !dummy->has<ObjectEntityDetails>() &&5158              !dummy->has<ProcEntityDetails>()) {5159            SayWithDecl(*dummyName, *dummy,5160                "ENTRY dummy argument '%s' was previously declared as an item that may not be used as a dummy argument"_err_en_US);5161          }5162          dummy->set(Symbol::Flag::EntryDummyArgument, false);5163        }5164      }5165    }5166  }5167}5168 5169Symbol *ScopeHandler::FindSeparateModuleProcedureInterface(5170    const parser::Name &name) {5171  auto *symbol{FindSymbol(name)};5172  if (symbol && symbol->has<SubprogramNameDetails>()) {5173    const Scope *parent{nullptr};5174    if (currScope().IsSubmodule()) {5175      parent = currScope().symbol()->get<ModuleDetails>().parent();5176    }5177    symbol = parent ? FindSymbol(*parent, name) : nullptr;5178  }5179  if (symbol) {5180    if (auto *generic{symbol->detailsIf<GenericDetails>()}) {5181      symbol = generic->specific();5182    }5183  }5184  if (const Symbol * defnIface{FindSeparateModuleSubprogramInterface(symbol)}) {5185    // Error recovery in case of multiple definitions5186    symbol = const_cast<Symbol *>(defnIface);5187  }5188  if (!IsSeparateModuleProcedureInterface(symbol)) {5189    Say(name, "'%s' was not declared a separate module procedure"_err_en_US);5190    symbol = nullptr;5191  }5192  return symbol;5193}5194 5195// A subprogram declared with MODULE PROCEDURE5196bool SubprogramVisitor::BeginMpSubprogram(const parser::Name &name) {5197  Symbol *symbol{FindSeparateModuleProcedureInterface(name)};5198  if (!symbol) {5199    return false;5200  }5201  if (symbol->owner() == currScope() && symbol->scope()) {5202    // This is a MODULE PROCEDURE whose interface appears in its host.5203    // Convert the module procedure's interface into a subprogram.5204    SetScope(DEREF(symbol->scope()));5205    symbol->get<SubprogramDetails>().set_isInterface(false);5206    name.symbol = symbol;5207  } else {5208    // Copy the interface into a new subprogram scope.5209    EraseSymbol(name);5210    Symbol &newSymbol{MakeSymbol(name, SubprogramDetails{})};5211    PushScope(Scope::Kind::Subprogram, &newSymbol);5212    auto &newSubprogram{newSymbol.get<SubprogramDetails>()};5213    newSubprogram.set_moduleInterface(*symbol);5214    auto &subprogram{symbol->get<SubprogramDetails>()};5215    if (const auto *name{subprogram.bindName()}) {5216      newSubprogram.set_bindName(std::string{*name});5217    }5218    newSymbol.attrs() |= symbol->attrs();5219    newSymbol.set(symbol->test(Symbol::Flag::Subroutine)5220            ? Symbol::Flag::Subroutine5221            : Symbol::Flag::Function);5222    MapSubprogramToNewSymbols(*symbol, newSymbol, currScope());5223  }5224  return true;5225}5226 5227// A subprogram or interface declared with SUBROUTINE or FUNCTION5228bool SubprogramVisitor::BeginSubprogram(const parser::Name &name,5229    Symbol::Flag subpFlag, bool hasModulePrefix,5230    const parser::LanguageBindingSpec *bindingSpec,5231    const ProgramTree::EntryStmtList *entryStmts) {5232  bool isValid{true};5233  if (hasModulePrefix && !currScope().IsModule() &&5234      !currScope().IsSubmodule()) { // C15475235    Say(name,5236        "'%s' is a MODULE procedure which must be declared within a MODULE or SUBMODULE"_err_en_US);5237    // Don't return here because it can be useful to have the scope set for5238    // other semantic checks run before we print the errors5239    isValid = false;5240  }5241  Symbol *moduleInterface{nullptr};5242  if (isValid && hasModulePrefix && !inInterfaceBlock()) {5243    moduleInterface = FindSeparateModuleProcedureInterface(name);5244    if (moduleInterface && &moduleInterface->owner() == &currScope()) {5245      // Subprogram is MODULE FUNCTION or MODULE SUBROUTINE with an interface5246      // previously defined in the same scope.5247      if (GenericDetails *5248          generic{DEREF(FindSymbol(name)).detailsIf<GenericDetails>()}) {5249        generic->clear_specific();5250        name.symbol = nullptr;5251      } else {5252        EraseSymbol(name);5253      }5254    }5255  }5256  Symbol *newSymbol{5257      PushSubprogramScope(name, subpFlag, bindingSpec, hasModulePrefix)};5258  if (!newSymbol) {5259    return false;5260  }5261  if (moduleInterface) {5262    newSymbol->get<SubprogramDetails>().set_moduleInterface(*moduleInterface);5263    if (moduleInterface->attrs().test(Attr::PRIVATE)) {5264      SetImplicitAttr(*newSymbol, Attr::PRIVATE);5265    } else if (moduleInterface->attrs().test(Attr::PUBLIC)) {5266      SetImplicitAttr(*newSymbol, Attr::PUBLIC);5267    }5268  }5269  if (entryStmts) {5270    for (const auto &ref : *entryStmts) {5271      CreateEntry(*ref, *newSymbol);5272    }5273  }5274  return true;5275}5276 5277void SubprogramVisitor::HandleLanguageBinding(Symbol *symbol,5278    std::optional<parser::CharBlock> stmtSource,5279    const std::optional<parser::LanguageBindingSpec> *binding) {5280  if (binding && *binding && symbol) {5281    // Finally process the BIND(C,NAME=name) now that symbols in the name5282    // expression will resolve to local names if needed.5283    auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)};5284    auto originalStmtSource{messageHandler().currStmtSource()};5285    messageHandler().set_currStmtSource(stmtSource);5286    BeginAttrs();5287    Walk(**binding);5288    SetBindNameOn(*symbol);5289    symbol->attrs() |= EndAttrs();5290    messageHandler().set_currStmtSource(originalStmtSource);5291  }5292}5293 5294void SubprogramVisitor::EndSubprogram(5295    std::optional<parser::CharBlock> stmtSource,5296    const std::optional<parser::LanguageBindingSpec> *binding,5297    const ProgramTree::EntryStmtList *entryStmts) {5298  HandleLanguageBinding(currScope().symbol(), stmtSource, binding);5299  if (entryStmts) {5300    for (const auto &ref : *entryStmts) {5301      const parser::EntryStmt &entryStmt{*ref};5302      if (const auto &suffix{5303              std::get<std::optional<parser::Suffix>>(entryStmt.t)}) {5304        const auto &name{std::get<parser::Name>(entryStmt.t)};5305        HandleLanguageBinding(name.symbol, name.source, &suffix->binding);5306      }5307    }5308  }5309  if (inInterfaceBlock() && currScope().symbol()) {5310    DeclaredPossibleSpecificProc(*currScope().symbol());5311  }5312  PopScope();5313}5314 5315bool SubprogramVisitor::HandlePreviousCalls(5316    const parser::Name &name, Symbol &symbol, Symbol::Flag subpFlag) {5317  // If the extant symbol is a generic, check its homonymous specific5318  // procedure instead if it has one.5319  if (auto *generic{symbol.detailsIf<GenericDetails>()}) {5320    return generic->specific() &&5321        HandlePreviousCalls(name, *generic->specific(), subpFlag);5322  } else if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}; proc &&5323             !proc->isDummy() &&5324             !symbol.attrs().HasAny(Attrs{Attr::INTRINSIC, Attr::POINTER})) {5325    // There's a symbol created for previous calls to this subprogram or5326    // ENTRY's name.  We have to replace that symbol in situ to avoid the5327    // obligation to rewrite symbol pointers in the parse tree.5328    if (!symbol.test(subpFlag)) {5329      auto other{subpFlag == Symbol::Flag::Subroutine5330              ? Symbol::Flag::Function5331              : Symbol::Flag::Subroutine};5332      // External statements issue an explicit EXTERNAL attribute.5333      if (symbol.attrs().test(Attr::EXTERNAL) &&5334          !symbol.implicitAttrs().test(Attr::EXTERNAL)) {5335        // Warn if external statement previously declared.5336        context().Warn(common::LanguageFeature::RedundantAttribute, name.source,5337            "EXTERNAL attribute was already specified on '%s'"_warn_en_US,5338            name.source);5339      } else if (symbol.test(other)) {5340        Say2(name,5341            subpFlag == Symbol::Flag::Function5342                ? "'%s' was previously called as a subroutine"_err_en_US5343                : "'%s' was previously called as a function"_err_en_US,5344            symbol, "Previous call of '%s'"_en_US);5345      } else {5346        symbol.set(subpFlag);5347      }5348    }5349    EntityDetails entity;5350    if (proc->type()) {5351      entity.set_type(*proc->type());5352    }5353    symbol.details() = std::move(entity);5354    return true;5355  } else {5356    return symbol.has<UnknownDetails>() || symbol.has<SubprogramNameDetails>();5357  }5358}5359 5360const Symbol *SubprogramVisitor::CheckExtantProc(5361    const parser::Name &name, Symbol::Flag subpFlag) {5362  Symbol *prev{FindSymbol(name)};5363  if (prev) {5364    if (IsDummy(*prev)) {5365    } else if (auto *entity{prev->detailsIf<EntityDetails>()};5366               IsPointer(*prev) && entity && !entity->type()) {5367      // POINTER attribute set before interface5368    } else if (inInterfaceBlock() && currScope() != prev->owner()) {5369      // Procedures in an INTERFACE block do not resolve to symbols5370      // in scopes between the global scope and the current scope.5371    } else if (!HandlePreviousCalls(name, *prev, subpFlag)) {5372      SayAlreadyDeclared(name, *prev);5373    }5374  }5375  return prev;5376}5377 5378Symbol *SubprogramVisitor::PushSubprogramScope(const parser::Name &name,5379    Symbol::Flag subpFlag, const parser::LanguageBindingSpec *bindingSpec,5380    bool hasModulePrefix) {5381  Symbol *symbol{GetSpecificFromGeneric(name)};5382  const DeclTypeSpec *previousImplicitType{nullptr};5383  SourceName previousName;5384  if (symbol && inInterfaceBlock() && !symbol->has<SubprogramDetails>()) {5385    SayAlreadyDeclared(name, *symbol);5386    return nullptr;5387  }5388  if (!symbol) {5389    if (bindingSpec && currScope().IsGlobal() &&5390        std::get<std::optional<parser::ScalarDefaultCharConstantExpr>>(5391            bindingSpec->t)5392            .has_value()) {5393      // Create this new top-level subprogram with a binding label5394      // in a new global scope, so that its symbol's name won't clash5395      // with another symbol that has a distinct binding label.5396      PushScope(Scope::Kind::Global,5397          &MakeSymbol(context().GetTempName(currScope()), Attrs{},5398              MiscDetails{MiscDetails::Kind::ScopeName}));5399    }5400    if (const Symbol *previous{CheckExtantProc(name, subpFlag)}) {5401      if (previous->test(Symbol::Flag::Function) &&5402          previous->test(Symbol::Flag::Implicit)) {5403        // Function was implicitly typed in previous compilation unit.5404        previousImplicitType = previous->GetType();5405        previousName = previous->name();5406      }5407    }5408    symbol = &MakeSymbol(name, SubprogramDetails{});5409  }5410  symbol->ReplaceName(name.source);5411  symbol->set(subpFlag);5412  PushScope(Scope::Kind::Subprogram, symbol);5413  if (subpFlag == Symbol::Flag::Function) {5414    auto &funcResultTop{funcResultStack().Push(currScope(), name.source)};5415    funcResultTop.previousImplicitType = previousImplicitType;5416    funcResultTop.previousName = previousName;5417  }5418  if (inInterfaceBlock()) {5419    auto &details{symbol->get<SubprogramDetails>()};5420    details.set_isInterface();5421    if (isAbstract()) {5422      SetExplicitAttr(*symbol, Attr::ABSTRACT);5423    } else if (hasModulePrefix) {5424      SetExplicitAttr(*symbol, Attr::MODULE);5425    } else {5426      MakeExternal(*symbol);5427    }5428    if (isGeneric()) {5429      Symbol &genericSymbol{GetGenericSymbol()};5430      if (auto *details{genericSymbol.detailsIf<GenericDetails>()}) {5431        details->AddSpecificProc(*symbol, name.source);5432      } else {5433        CHECK(context().HasError(genericSymbol));5434      }5435    }5436    set_inheritFromParent(false); // interfaces don't inherit, even if MODULE5437  }5438  if (Symbol * found{FindSymbol(name)};5439      found && found->has<HostAssocDetails>()) {5440    found->set(subpFlag); // PushScope() created symbol5441  }5442  return symbol;5443}5444 5445void SubprogramVisitor::PushBlockDataScope(const parser::Name &name) {5446  if (auto *prev{FindSymbol(name)}) {5447    if (prev->attrs().test(Attr::EXTERNAL) && prev->has<ProcEntityDetails>()) {5448      if (prev->test(Symbol::Flag::Subroutine) ||5449          prev->test(Symbol::Flag::Function)) {5450        Say2(name, "BLOCK DATA '%s' has been called"_err_en_US, *prev,5451            "Previous call of '%s'"_en_US);5452      }5453      EraseSymbol(name);5454    }5455  }5456  if (name.source.empty()) {5457    // Don't let unnamed BLOCK DATA conflict with unnamed PROGRAM5458    PushScope(Scope::Kind::BlockData, nullptr);5459  } else {5460    PushScope(Scope::Kind::BlockData, &MakeSymbol(name, SubprogramDetails{}));5461  }5462}5463 5464// If name is a generic in the same scope, return its specific subprogram with5465// the same name, if any.5466Symbol *SubprogramVisitor::GetSpecificFromGeneric(const parser::Name &name) {5467  // Search for the name but don't resolve it5468  if (auto *symbol{currScope().FindSymbol(name.source)}) {5469    if (symbol->has<SubprogramNameDetails>()) {5470      if (inInterfaceBlock()) {5471        // Subtle: clear any MODULE flag so that the new interface5472        // symbol doesn't inherit it and ruin the ability to check it.5473        symbol->attrs().reset(Attr::MODULE);5474      }5475    } else if (&symbol->owner() != &currScope() && inInterfaceBlock() &&5476        !isGeneric()) {5477      // non-generic interface shadows outer definition5478    } else if (auto *details{symbol->detailsIf<GenericDetails>()}) {5479      // found generic, want specific procedure5480      auto *specific{details->specific()};5481      Attrs moduleAttr;5482      if (inInterfaceBlock()) {5483        if (specific) {5484          // Defining an interface in a generic of the same name which is5485          // already shadowing another procedure.  In some cases, the shadowed5486          // procedure is about to be replaced.5487          if (specific->has<SubprogramNameDetails>() &&5488              specific->attrs().test(Attr::MODULE)) {5489            // The shadowed procedure is a separate module procedure that is5490            // actually defined later in this (sub)module.5491            // Define its interface now as a new symbol.5492            moduleAttr.set(Attr::MODULE);5493            specific = nullptr;5494          } else if (&specific->owner() != &symbol->owner()) {5495            // The shadowed procedure was from an enclosing scope and will be5496            // overridden by this interface definition.5497            specific = nullptr;5498          }5499          if (!specific) {5500            details->clear_specific();5501          }5502        } else if (const auto *dType{details->derivedType()}) {5503          if (&dType->owner() != &symbol->owner()) {5504            // The shadowed derived type was from an enclosing scope and5505            // will be overridden by this interface definition.5506            details->clear_derivedType();5507          }5508        }5509      }5510      if (!specific) {5511        specific = &currScope().MakeSymbol(5512            name.source, std::move(moduleAttr), SubprogramDetails{});5513        if (details->derivedType()) {5514          // A specific procedure with the same name as a derived type5515          SayAlreadyDeclared(name, *details->derivedType());5516        } else {5517          details->set_specific(Resolve(name, *specific));5518        }5519      } else if (isGeneric()) {5520        SayAlreadyDeclared(name, *specific);5521      }5522      if (specific->has<SubprogramNameDetails>()) {5523        specific->set_details(Details{SubprogramDetails{}});5524      }5525      return specific;5526    }5527  }5528  return nullptr;5529}5530 5531// DeclarationVisitor implementation5532 5533bool DeclarationVisitor::BeginDecl() {5534  BeginDeclTypeSpec();5535  BeginArraySpec();5536  return BeginAttrs();5537}5538void DeclarationVisitor::EndDecl() {5539  EndDeclTypeSpec();5540  EndArraySpec();5541  EndAttrs();5542}5543 5544bool DeclarationVisitor::CheckUseError(const parser::Name &name) {5545  return HadUseError(context(), name.source, name.symbol);5546}5547 5548// Report error if accessibility of symbol doesn't match isPrivate.5549void DeclarationVisitor::CheckAccessibility(5550    const SourceName &name, bool isPrivate, Symbol &symbol) {5551  if (symbol.attrs().test(Attr::PRIVATE) != isPrivate) {5552    Say2(name,5553        "'%s' does not have the same accessibility as its previous declaration"_err_en_US,5554        symbol, "Previous declaration of '%s'"_en_US);5555  }5556}5557 5558bool DeclarationVisitor::Pre(const parser::TypeDeclarationStmt &x) {5559  BeginDecl();5560  // If INTRINSIC appears as an attr-spec, handle it now as if the5561  // names had appeared on an INTRINSIC attribute statement beforehand.5562  for (const auto &attr : std::get<std::list<parser::AttrSpec>>(x.t)) {5563    if (std::holds_alternative<parser::Intrinsic>(attr.u)) {5564      for (const auto &decl : std::get<std::list<parser::EntityDecl>>(x.t)) {5565        DeclareIntrinsic(parser::GetFirstName(decl));5566      }5567      break;5568    }5569  }5570  return true;5571}5572void DeclarationVisitor::Post(const parser::TypeDeclarationStmt &) {5573  EndDecl();5574}5575 5576void DeclarationVisitor::Post(const parser::DimensionStmt::Declaration &x) {5577  DeclareObjectEntity(std::get<parser::Name>(x.t));5578}5579void DeclarationVisitor::Post(const parser::CodimensionDecl &x) {5580  DeclareObjectEntity(std::get<parser::Name>(x.t));5581}5582 5583bool DeclarationVisitor::Pre(const parser::Initialization &) {5584  // Defer inspection of initializers to Initialization() so that the5585  // symbol being initialized will be available within the initialization5586  // expression.5587  return false;5588}5589 5590void DeclarationVisitor::Post(const parser::EntityDecl &x) {5591  const auto &name{std::get<parser::ObjectName>(x.t)};5592  Attrs attrs{attrs_ ? HandleSaveName(name.source, *attrs_) : Attrs{}};5593  attrs.set(Attr::INTRINSIC, false); // dealt with in Pre(TypeDeclarationStmt)5594  Symbol &symbol{DeclareUnknownEntity(name, attrs)};5595  symbol.ReplaceName(name.source);5596  SetCUDADataAttr(name.source, symbol, cudaDataAttr());5597  if (const auto &init{std::get<std::optional<parser::Initialization>>(x.t)}) {5598    ConvertToObjectEntity(symbol) || ConvertToProcEntity(symbol);5599    symbol.set(5600        Symbol::Flag::EntryDummyArgument, false); // forestall excessive errors5601    Initialization(name, *init, /*inComponentDecl=*/false);5602  } else if (attrs.test(Attr::PARAMETER)) { // C882, C8835603    Say(name, "Missing initialization for parameter '%s'"_err_en_US);5604  }5605  if (auto *scopeSymbol{currScope().symbol()}) {5606    if (auto *details{scopeSymbol->detailsIf<DerivedTypeDetails>()}) {5607      if (details->isDECStructure()) {5608        details->add_component(symbol);5609      }5610    }5611  }5612}5613 5614void DeclarationVisitor::Post(const parser::PointerDecl &x) {5615  const auto &name{std::get<parser::Name>(x.t)};5616  if (const auto &deferredShapeSpecs{5617          std::get<std::optional<parser::DeferredShapeSpecList>>(x.t)}) {5618    CHECK(arraySpec().empty());5619    BeginArraySpec();5620    set_arraySpec(AnalyzeDeferredShapeSpecList(context(), *deferredShapeSpecs));5621    Symbol &symbol{DeclareObjectEntity(name, Attrs{Attr::POINTER})};5622    symbol.ReplaceName(name.source);5623    EndArraySpec();5624  } else {5625    if (const auto *symbol{FindInScope(name)}) {5626      const auto *subp{symbol->detailsIf<SubprogramDetails>()};5627      if (!symbol->has<UseDetails>() && // error caught elsewhere5628          !symbol->has<ObjectEntityDetails>() &&5629          !symbol->has<ProcEntityDetails>() &&5630          !symbol->CanReplaceDetails(ObjectEntityDetails{}) &&5631          !symbol->CanReplaceDetails(ProcEntityDetails{}) &&5632          !(subp && subp->isInterface())) {5633        Say(name, "'%s' cannot have the POINTER attribute"_err_en_US);5634      }5635    }5636    HandleAttributeStmt(Attr::POINTER, std::get<parser::Name>(x.t));5637  }5638}5639 5640bool DeclarationVisitor::Pre(const parser::BindEntity &x) {5641  auto kind{std::get<parser::BindEntity::Kind>(x.t)};5642  auto &name{std::get<parser::Name>(x.t)};5643  Symbol *symbol;5644  if (kind == parser::BindEntity::Kind::Object) {5645    symbol = &HandleAttributeStmt(Attr::BIND_C, name);5646  } else {5647    symbol = &MakeCommonBlockSymbol(name, name.source);5648    SetExplicitAttr(*symbol, Attr::BIND_C);5649  }5650  // 8.6.4(1)5651  // Some entities such as named constant or module name need to checked5652  // elsewhere. This is to skip the ICE caused by setting Bind name for non-name5653  // things such as data type and also checks for procedures.5654  if (symbol->has<CommonBlockDetails>() || symbol->has<ObjectEntityDetails>() ||5655      symbol->has<EntityDetails>()) {5656    SetBindNameOn(*symbol);5657  } else {5658    Say(name,5659        "Only variable and named common block can be in BIND statement"_err_en_US);5660  }5661  return false;5662}5663bool DeclarationVisitor::Pre(const parser::OldParameterStmt &x) {5664  inOldStyleParameterStmt_ = true;5665  Walk(x.v);5666  inOldStyleParameterStmt_ = false;5667  return false;5668}5669bool DeclarationVisitor::Pre(const parser::NamedConstantDef &x) {5670  auto &name{std::get<parser::NamedConstant>(x.t).v};5671  auto &symbol{HandleAttributeStmt(Attr::PARAMETER, name)};5672  ConvertToObjectEntity(symbol);5673  auto *details{symbol.detailsIf<ObjectEntityDetails>()};5674  if (!details || symbol.test(Symbol::Flag::CrayPointer) ||5675      symbol.test(Symbol::Flag::CrayPointee)) {5676    SayWithDecl(5677        name, symbol, "PARAMETER attribute not allowed on '%s'"_err_en_US);5678    return false;5679  }5680  const auto &expr{std::get<parser::ConstantExpr>(x.t)};5681  if (details->init() || symbol.test(Symbol::Flag::InDataStmt)) {5682    Say(name, "Named constant '%s' already has a value"_err_en_US);5683  }5684  parser::CharBlock at{parser::UnwrapRef<parser::Expr>(expr).source};5685  if (inOldStyleParameterStmt_) {5686    // non-standard extension PARAMETER statement (no parentheses)5687    Walk(expr);5688    auto folded{EvaluateExpr(expr)};5689    if (details->type()) {5690      SayWithDecl(name, symbol,5691          "Alternative style PARAMETER '%s' must not already have an explicit type"_err_en_US);5692    } else if (folded) {5693      if (evaluate::IsActuallyConstant(*folded)) {5694        if (const auto *type{currScope().GetType(*folded)}) {5695          if (type->IsPolymorphic()) {5696            Say(at, "The expression must not be polymorphic"_err_en_US);5697          } else if (auto shape{ToArraySpec(5698                         GetFoldingContext(), evaluate::GetShape(*folded))}) {5699            // The type of the named constant is assumed from the expression.5700            details->set_type(*type);5701            details->set_init(std::move(*folded));5702            details->set_shape(std::move(*shape));5703          } else {5704            Say(at, "The expression must have constant shape"_err_en_US);5705          }5706        } else {5707          Say(at, "The expression must have a known type"_err_en_US);5708        }5709      } else {5710        Say(at, "The expression must be a constant of known type"_err_en_US);5711      }5712    }5713  } else {5714    // standard-conforming PARAMETER statement (with parentheses)5715    ApplyImplicitRules(symbol);5716    Walk(expr);5717    if (auto converted{EvaluateNonPointerInitializer(symbol, expr, at)}) {5718      details->set_init(std::move(*converted));5719    }5720  }5721  return false;5722}5723bool DeclarationVisitor::Pre(const parser::NamedConstant &x) {5724  const parser::Name &name{x.v};5725  if (!FindSymbol(name)) {5726    Say(name, "Named constant '%s' not found"_err_en_US);5727  } else {5728    CheckUseError(name);5729  }5730  return false;5731}5732 5733bool DeclarationVisitor::Pre(const parser::Enumerator &enumerator) {5734  const parser::Name &name{std::get<parser::NamedConstant>(enumerator.t).v};5735  Symbol *symbol{FindInScope(name)};5736  if (symbol && !symbol->has<UnknownDetails>()) {5737    // Contrary to named constants appearing in a PARAMETER statement,5738    // enumerator names should not have their type, dimension or any other5739    // attributes defined before they are declared in the enumerator statement,5740    // with the exception of accessibility.5741    // This is not explicitly forbidden by the standard, but they are scalars5742    // which type is left for the compiler to chose, so do not let users try to5743    // tamper with that.5744    SayAlreadyDeclared(name, *symbol);5745    symbol = nullptr;5746  } else {5747    // Enumerators are treated as PARAMETER (section 7.6 paragraph (4))5748    symbol = &MakeSymbol(name, Attrs{Attr::PARAMETER}, ObjectEntityDetails{});5749    symbol->SetType(context().MakeNumericType(5750        TypeCategory::Integer, evaluate::CInteger::kind));5751  }5752 5753  if (auto &init{std::get<std::optional<parser::ScalarIntConstantExpr>>(5754          enumerator.t)}) {5755    Walk(*init); // Resolve names in expression before evaluation.5756    if (auto value{EvaluateInt64(context(), *init)}) {5757      // Cast all init expressions to C_INT so that they can then be5758      // safely incremented (see 7.6 Note 2).5759      enumerationState_.value = static_cast<int>(*value);5760    } else {5761      Say(name,5762          "Enumerator value could not be computed "5763          "from the given expression"_err_en_US);5764      // Prevent resolution of next enumerators value5765      enumerationState_.value = std::nullopt;5766    }5767  }5768 5769  if (symbol) {5770    if (enumerationState_.value) {5771      symbol->get<ObjectEntityDetails>().set_init(SomeExpr{5772          evaluate::Expr<evaluate::CInteger>{*enumerationState_.value}});5773    } else {5774      context().SetError(*symbol);5775    }5776  }5777 5778  if (enumerationState_.value) {5779    (*enumerationState_.value)++;5780  }5781  return false;5782}5783 5784void DeclarationVisitor::Post(const parser::EnumDef &) {5785  enumerationState_ = EnumeratorState{};5786}5787 5788bool DeclarationVisitor::Pre(const parser::AccessSpec &x) {5789  Attr attr{AccessSpecToAttr(x)};5790  if (!NonDerivedTypeScope().IsModule()) { // C8175791    Say(currStmtSource().value(),5792        "%s attribute may only appear in the specification part of a module"_err_en_US,5793        EnumToString(attr));5794  }5795  CheckAndSet(attr);5796  return false;5797}5798 5799bool DeclarationVisitor::Pre(const parser::AsynchronousStmt &x) {5800  return HandleAttributeStmt(Attr::ASYNCHRONOUS, x.v);5801}5802bool DeclarationVisitor::Pre(const parser::ContiguousStmt &x) {5803  return HandleAttributeStmt(Attr::CONTIGUOUS, x.v);5804}5805bool DeclarationVisitor::Pre(const parser::ExternalStmt &x) {5806  HandleAttributeStmt(Attr::EXTERNAL, x.v);5807  for (const auto &name : x.v) {5808    auto *symbol{FindSymbol(name)};5809    if (!ConvertToProcEntity(DEREF(symbol), name.source)) {5810      // Check if previous symbol is an interface.5811      if (auto *details{symbol->detailsIf<SubprogramDetails>()}) {5812        if (details->isInterface()) {5813          // Warn if interface previously declared.5814          context().Warn(common::LanguageFeature::RedundantAttribute,5815              name.source,5816              "EXTERNAL attribute was already specified on '%s'"_warn_en_US,5817              name.source);5818        }5819      } else {5820        SayWithDecl(5821            name, *symbol, "EXTERNAL attribute not allowed on '%s'"_err_en_US);5822      }5823    } else if (symbol->attrs().test(Attr::INTRINSIC)) { // C8405824      Say(symbol->name(),5825          "Symbol '%s' cannot have both INTRINSIC and EXTERNAL attributes"_err_en_US,5826          symbol->name());5827    }5828  }5829  return false;5830}5831bool DeclarationVisitor::Pre(const parser::IntentStmt &x) {5832  auto &intentSpec{std::get<parser::IntentSpec>(x.t)};5833  auto &names{std::get<std::list<parser::Name>>(x.t)};5834  return CheckNotInBlock("INTENT") && // C11075835      HandleAttributeStmt(IntentSpecToAttr(intentSpec), names);5836}5837bool DeclarationVisitor::Pre(const parser::IntrinsicStmt &x) {5838  for (const auto &name : x.v) {5839    DeclareIntrinsic(name);5840  }5841  return false;5842}5843void DeclarationVisitor::DeclareIntrinsic(const parser::Name &name) {5844  HandleAttributeStmt(Attr::INTRINSIC, name);5845  if (!IsIntrinsic(name.source, std::nullopt)) {5846    Say(name.source, "'%s' is not a known intrinsic procedure"_err_en_US);5847  }5848  auto &symbol{DEREF(FindSymbol(name))};5849  if (symbol.has<GenericDetails>()) {5850    // Generic interface is extending intrinsic; ok5851  } else if (!ConvertToProcEntity(symbol, name.source)) {5852    SayWithDecl(5853        name, symbol, "INTRINSIC attribute not allowed on '%s'"_err_en_US);5854  } else if (symbol.attrs().test(Attr::EXTERNAL)) { // C8405855    Say(symbol.name(),5856        "Symbol '%s' cannot have both EXTERNAL and INTRINSIC attributes"_err_en_US,5857        symbol.name());5858  } else {5859    if (symbol.GetType()) {5860      // These warnings are worded so that they should make sense in either5861      // order.5862      if (auto *msg{context().Warn(5863              common::UsageWarning::IgnoredIntrinsicFunctionType, symbol.name(),5864              "Explicit type declaration ignored for intrinsic function '%s'"_warn_en_US,5865              symbol.name())}) {5866        msg->Attach(name.source,5867            "INTRINSIC statement for explicitly-typed '%s'"_en_US, name.source);5868      }5869    }5870    if (!symbol.test(Symbol::Flag::Function) &&5871        !symbol.test(Symbol::Flag::Subroutine) &&5872        !context().intrinsics().IsDualIntrinsic(name.source.ToString())) {5873      if (context().intrinsics().IsIntrinsicFunction(name.source.ToString())) {5874        symbol.set(Symbol::Flag::Function);5875      } else if (context().intrinsics().IsIntrinsicSubroutine(5876                     name.source.ToString())) {5877        symbol.set(Symbol::Flag::Subroutine);5878      }5879    }5880  }5881}5882bool DeclarationVisitor::Pre(const parser::OptionalStmt &x) {5883  return CheckNotInBlock("OPTIONAL") && // C11075884      HandleAttributeStmt(Attr::OPTIONAL, x.v);5885}5886bool DeclarationVisitor::Pre(const parser::ProtectedStmt &x) {5887  return HandleAttributeStmt(Attr::PROTECTED, x.v);5888}5889bool DeclarationVisitor::Pre(const parser::ValueStmt &x) {5890  return CheckNotInBlock("VALUE") && // C11075891      HandleAttributeStmt(Attr::VALUE, x.v);5892}5893bool DeclarationVisitor::Pre(const parser::VolatileStmt &x) {5894  return HandleAttributeStmt(Attr::VOLATILE, x.v);5895}5896bool DeclarationVisitor::Pre(const parser::CUDAAttributesStmt &x) {5897  auto attr{std::get<common::CUDADataAttr>(x.t)};5898  for (const auto &name : std::get<std::list<parser::Name>>(x.t)) {5899    auto *symbol{FindInScope(name)};5900    if (symbol && symbol->has<UseDetails>()) {5901      Say(currStmtSource().value(),5902          "Cannot apply CUDA data attribute to use-associated '%s'"_err_en_US,5903          name.source);5904    } else {5905      if (!symbol) {5906        symbol = &MakeSymbol(name, ObjectEntityDetails{});5907      }5908      SetCUDADataAttr(name.source, *symbol, attr);5909    }5910  }5911  return false;5912}5913// Handle a statement that sets an attribute on a list of names.5914bool DeclarationVisitor::HandleAttributeStmt(5915    Attr attr, const std::list<parser::Name> &names) {5916  for (const auto &name : names) {5917    HandleAttributeStmt(attr, name);5918  }5919  return false;5920}5921Symbol &DeclarationVisitor::HandleAttributeStmt(5922    Attr attr, const parser::Name &name) {5923  auto *symbol{FindInScope(name)};5924  if (attr == Attr::ASYNCHRONOUS || attr == Attr::VOLATILE) {5925    // these can be set on a symbol that is host-assoc or use-assoc5926    if (!symbol &&5927        (currScope().kind() == Scope::Kind::Subprogram ||5928            currScope().kind() == Scope::Kind::BlockConstruct)) {5929      if (auto *hostSymbol{FindSymbol(name)}) {5930        symbol = &MakeHostAssocSymbol(name, *hostSymbol);5931      }5932    }5933  } else if (symbol && symbol->has<UseDetails>()) {5934    if (symbol->GetUltimate().attrs().test(attr)) {5935      context().Warn(common::LanguageFeature::RedundantAttribute,5936          currStmtSource().value(),5937          "Use-associated '%s' already has '%s' attribute"_warn_en_US,5938          name.source, EnumToString(attr));5939    } else {5940      Say(currStmtSource().value(),5941          "Cannot change %s attribute on use-associated '%s'"_err_en_US,5942          EnumToString(attr), name.source);5943    }5944    return *symbol;5945  }5946  if (!symbol) {5947    symbol = &MakeSymbol(name, EntityDetails{});5948  }5949  if (CheckDuplicatedAttr(name.source, *symbol, attr)) {5950    HandleSaveName(name.source, Attrs{attr});5951    SetExplicitAttr(*symbol, attr);5952  }5953  return *symbol;5954}5955// C11075956bool DeclarationVisitor::CheckNotInBlock(const char *stmt) {5957  if (currScope().kind() == Scope::Kind::BlockConstruct) {5958    Say(MessageFormattedText{5959        "%s statement is not allowed in a BLOCK construct"_err_en_US, stmt});5960    return false;5961  } else {5962    return true;5963  }5964}5965 5966void DeclarationVisitor::Post(const parser::ObjectDecl &x) {5967  CHECK(objectDeclAttr_);5968  const auto &name{std::get<parser::ObjectName>(x.t)};5969  DeclareObjectEntity(name, Attrs{*objectDeclAttr_});5970}5971 5972// Declare an entity not yet known to be an object or proc.5973Symbol &DeclarationVisitor::DeclareUnknownEntity(5974    const parser::Name &name, Attrs attrs) {5975  if (!arraySpec().empty() || !coarraySpec().empty()) {5976    return DeclareObjectEntity(name, attrs);5977  } else {5978    Symbol &symbol{DeclareEntity<EntityDetails>(name, attrs)};5979    if (auto *type{GetDeclTypeSpec()}) {5980      ForgetEarlyDeclaredDummyArgument(symbol);5981      SetType(name, *type);5982    }5983    charInfo_.length.reset();5984    if (symbol.attrs().test(Attr::EXTERNAL)) {5985      ConvertToProcEntity(symbol);5986    } else if (symbol.attrs().HasAny(Attrs{Attr::ALLOCATABLE,5987                   Attr::ASYNCHRONOUS, Attr::CONTIGUOUS, Attr::PARAMETER,5988                   Attr::SAVE, Attr::TARGET, Attr::VALUE, Attr::VOLATILE})) {5989      ConvertToObjectEntity(symbol);5990    }5991    if (attrs.test(Attr::BIND_C)) {5992      SetBindNameOn(symbol);5993    }5994    return symbol;5995  }5996}5997 5998bool DeclarationVisitor::HasCycle(5999    const Symbol &procSymbol, const Symbol *interface) {6000  SourceOrderedSymbolSet procsInCycle;6001  procsInCycle.insert(procSymbol);6002  while (interface) {6003    if (procsInCycle.count(*interface) > 0) {6004      for (const auto &procInCycle : procsInCycle) {6005        Say(procInCycle->name(),6006            "The interface for procedure '%s' is recursively defined"_err_en_US,6007            procInCycle->name());6008        context().SetError(*procInCycle);6009      }6010      return true;6011    } else if (const auto *procDetails{6012                   interface->detailsIf<ProcEntityDetails>()}) {6013      procsInCycle.insert(*interface);6014      interface = procDetails->procInterface();6015    } else {6016      break;6017    }6018  }6019  return false;6020}6021 6022Symbol &DeclarationVisitor::DeclareProcEntity(6023    const parser::Name &name, Attrs attrs, const Symbol *interface) {6024  Symbol *proc{nullptr};6025  if (auto *extant{FindInScope(name)}) {6026    if (auto *d{extant->detailsIf<GenericDetails>()}; d && !d->derivedType()) {6027      // procedure pointer with same name as a generic6028      if (auto *specific{d->specific()}) {6029        SayAlreadyDeclared(name, *specific);6030      } else {6031        // Create the ProcEntityDetails symbol in the scope as the "specific()"6032        // symbol behind an existing GenericDetails symbol of the same name.6033        proc = &Resolve(name,6034            currScope().MakeSymbol(name.source, attrs, ProcEntityDetails{}));6035        d->set_specific(*proc);6036      }6037    }6038  }6039  Symbol &symbol{proc ? *proc : DeclareEntity<ProcEntityDetails>(name, attrs)};6040  if (auto *details{symbol.detailsIf<ProcEntityDetails>()}) {6041    if (context().HasError(symbol)) {6042    } else if (HasCycle(symbol, interface)) {6043      return symbol;6044    } else if (interface && (details->procInterface() || details->type())) {6045      SayWithDecl(name, symbol,6046          "The interface for procedure '%s' has already been declared"_err_en_US);6047      context().SetError(symbol);6048    } else if (interface) {6049      details->set_procInterfaces(6050          *interface, BypassGeneric(interface->GetUltimate()));6051      if (interface->test(Symbol::Flag::Function)) {6052        symbol.set(Symbol::Flag::Function);6053      } else if (interface->test(Symbol::Flag::Subroutine)) {6054        symbol.set(Symbol::Flag::Subroutine);6055      }6056    } else if (auto *type{GetDeclTypeSpec()}) {6057      ForgetEarlyDeclaredDummyArgument(symbol);6058      SetType(name, *type);6059      symbol.set(Symbol::Flag::Function);6060    }6061    SetBindNameOn(symbol);6062    SetPassNameOn(symbol);6063  }6064  return symbol;6065}6066 6067Symbol &DeclarationVisitor::DeclareObjectEntity(6068    const parser::Name &name, Attrs attrs) {6069  Symbol &symbol{DeclareEntity<ObjectEntityDetails>(name, attrs)};6070  if (auto *details{symbol.detailsIf<ObjectEntityDetails>()}) {6071    if (auto *type{GetDeclTypeSpec()}) {6072      ForgetEarlyDeclaredDummyArgument(symbol);6073      SetType(name, *type);6074    }6075    if (!arraySpec().empty()) {6076      if (details->IsArray()) {6077        if (!context().HasError(symbol)) {6078          Say(name,6079              "The dimensions of '%s' have already been declared"_err_en_US);6080          context().SetError(symbol);6081        }6082      } else if (MustBeScalar(symbol)) {6083        if (!context().HasError(symbol)) {6084          context().Warn(common::UsageWarning::PreviousScalarUse, name.source,6085              "'%s' appeared earlier as a scalar actual argument to a specification function"_warn_en_US,6086              name.source);6087        }6088      } else if (details->init() || symbol.test(Symbol::Flag::InDataStmt)) {6089        Say(name, "'%s' was initialized earlier as a scalar"_err_en_US);6090      } else {6091        details->set_shape(arraySpec());6092      }6093    }6094    if (!coarraySpec().empty()) {6095      if (details->IsCoarray()) {6096        if (!context().HasError(symbol)) {6097          Say(name,6098              "The codimensions of '%s' have already been declared"_err_en_US);6099          context().SetError(symbol);6100        }6101      } else {6102        details->set_coshape(coarraySpec());6103      }6104    }6105    SetBindNameOn(symbol);6106  }6107  ClearArraySpec();6108  ClearCoarraySpec();6109  charInfo_.length.reset();6110  return symbol;6111}6112 6113void DeclarationVisitor::Post(const parser::IntegerTypeSpec &x) {6114  if (!isVectorType_) {6115    SetDeclTypeSpec(MakeNumericType(TypeCategory::Integer, x.v));6116  }6117}6118void DeclarationVisitor::Post(const parser::UnsignedTypeSpec &x) {6119  if (!isVectorType_) {6120    if (!context().IsEnabled(common::LanguageFeature::Unsigned) &&6121        !context().AnyFatalError()) {6122      context().Say("-funsigned is required to enable UNSIGNED type"_err_en_US);6123    }6124    SetDeclTypeSpec(MakeNumericType(TypeCategory::Unsigned, x.v));6125  }6126}6127void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Real &x) {6128  if (!isVectorType_) {6129    SetDeclTypeSpec(MakeNumericType(TypeCategory::Real, x.kind));6130  }6131}6132void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Complex &x) {6133  SetDeclTypeSpec(MakeNumericType(TypeCategory::Complex, x.kind));6134}6135void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Logical &x) {6136  SetDeclTypeSpec(MakeLogicalType(x.kind));6137}6138void DeclarationVisitor::Post(const parser::IntrinsicTypeSpec::Character &) {6139  if (!charInfo_.length) {6140    charInfo_.length = ParamValue{1, common::TypeParamAttr::Len};6141  }6142  if (!charInfo_.kind) {6143    charInfo_.kind =6144        KindExpr{context().GetDefaultKind(TypeCategory::Character)};6145  }6146  SetDeclTypeSpec(currScope().MakeCharacterType(6147      std::move(*charInfo_.length), std::move(*charInfo_.kind)));6148  charInfo_ = {};6149}6150void DeclarationVisitor::Post(const parser::CharSelector::LengthAndKind &x) {6151  charInfo_.kind = EvaluateSubscriptIntExpr(x.kind);6152  std::optional<std::int64_t> intKind{ToInt64(charInfo_.kind)};6153  if (intKind &&6154      !context().targetCharacteristics().IsTypeEnabled(6155          TypeCategory::Character, *intKind)) { // C715, C7196156    Say(currStmtSource().value(),6157        "KIND value (%jd) not valid for CHARACTER"_err_en_US, *intKind);6158    charInfo_.kind = std::nullopt; // prevent further errors6159  }6160  if (x.length) {6161    charInfo_.length = GetParamValue(*x.length, common::TypeParamAttr::Len);6162  }6163}6164void DeclarationVisitor::Post(const parser::CharLength &x) {6165  if (const auto *length{std::get_if<std::uint64_t>(&x.u)}) {6166    charInfo_.length = ParamValue{6167        static_cast<ConstantSubscript>(*length), common::TypeParamAttr::Len};6168  } else {6169    charInfo_.length = GetParamValue(6170        std::get<parser::TypeParamValue>(x.u), common::TypeParamAttr::Len);6171  }6172}6173void DeclarationVisitor::Post(const parser::LengthSelector &x) {6174  if (const auto *param{std::get_if<parser::TypeParamValue>(&x.u)}) {6175    charInfo_.length = GetParamValue(*param, common::TypeParamAttr::Len);6176  }6177}6178 6179bool DeclarationVisitor::Pre(const parser::KindParam &x) {6180  if (const auto *kind{std::get_if<6181          parser::Scalar<parser::Integer<parser::Constant<parser::Name>>>>(6182          &x.u)}) {6183    const auto &name{parser::UnwrapRef<parser::Name>(kind)};6184    if (!FindSymbol(name)) {6185      Say(name, "Parameter '%s' not found"_err_en_US);6186    }6187  }6188  return false;6189}6190 6191int DeclarationVisitor::GetVectorElementKind(6192    TypeCategory category, const std::optional<parser::KindSelector> &kind) {6193  KindExpr value{GetKindParamExpr(category, kind)};6194  if (auto known{evaluate::ToInt64(value)}) {6195    return static_cast<int>(*known);6196  }6197  common::die("Vector element kind must be known at compile-time");6198}6199 6200bool DeclarationVisitor::Pre(const parser::VectorTypeSpec &) {6201  // PowerPC vector types are allowed only on Power architectures.6202  if (!currScope().context().targetCharacteristics().isPPC()) {6203    Say(currStmtSource().value(),6204        "Vector type is only supported for PowerPC"_err_en_US);6205    isVectorType_ = false;6206    return false;6207  }6208  isVectorType_ = true;6209  return true;6210}6211// Create semantic::DerivedTypeSpec for Vector types here.6212void DeclarationVisitor::Post(const parser::VectorTypeSpec &x) {6213  llvm::StringRef typeName;6214  llvm::SmallVector<ParamValue> typeParams;6215  DerivedTypeSpec::Category vectorCategory;6216 6217  isVectorType_ = false;6218  common::visit(6219      common::visitors{6220          [&](const parser::IntrinsicVectorTypeSpec &y) {6221            vectorCategory = DerivedTypeSpec::Category::IntrinsicVector;6222            int vecElemKind = 0;6223            typeName = "__builtin_ppc_intrinsic_vector";6224            common::visit(6225                common::visitors{6226                    [&](const parser::IntegerTypeSpec &z) {6227                      vecElemKind = GetVectorElementKind(6228                          TypeCategory::Integer, std::move(z.v));6229                      typeParams.push_back(ParamValue(6230                          static_cast<common::ConstantSubscript>(6231                              common::VectorElementCategory::Integer),6232                          common::TypeParamAttr::Kind));6233                    },6234                    [&](const parser::IntrinsicTypeSpec::Real &z) {6235                      vecElemKind = GetVectorElementKind(6236                          TypeCategory::Real, std::move(z.kind));6237                      typeParams.push_back(6238                          ParamValue(static_cast<common::ConstantSubscript>(6239                                         common::VectorElementCategory::Real),6240                              common::TypeParamAttr::Kind));6241                    },6242                    [&](const parser::UnsignedTypeSpec &z) {6243                      vecElemKind = GetVectorElementKind(6244                          TypeCategory::Integer, std::move(z.v));6245                      typeParams.push_back(ParamValue(6246                          static_cast<common::ConstantSubscript>(6247                              common::VectorElementCategory::Unsigned),6248                          common::TypeParamAttr::Kind));6249                    },6250                },6251                y.v.u);6252            typeParams.push_back(6253                ParamValue(static_cast<common::ConstantSubscript>(vecElemKind),6254                    common::TypeParamAttr::Kind));6255          },6256          [&](const parser::VectorTypeSpec::PairVectorTypeSpec &y) {6257            vectorCategory = DerivedTypeSpec::Category::PairVector;6258            typeName = "__builtin_ppc_pair_vector";6259          },6260          [&](const parser::VectorTypeSpec::QuadVectorTypeSpec &y) {6261            vectorCategory = DerivedTypeSpec::Category::QuadVector;6262            typeName = "__builtin_ppc_quad_vector";6263          },6264      },6265      x.u);6266 6267  auto ppcBuiltinTypesScope = currScope().context().GetPPCBuiltinTypesScope();6268  if (!ppcBuiltinTypesScope) {6269    common::die("INTERNAL: The __ppc_types module was not found ");6270  }6271 6272  auto iter{ppcBuiltinTypesScope->find(6273      semantics::SourceName{typeName.data(), typeName.size()})};6274  if (iter == ppcBuiltinTypesScope->cend()) {6275    common::die("INTERNAL: The __ppc_types module does not define "6276                "the type '%s'",6277        typeName.data());6278  }6279 6280  const semantics::Symbol &typeSymbol{*iter->second};6281  DerivedTypeSpec vectorDerivedType{typeName.data(), typeSymbol};6282  vectorDerivedType.set_category(vectorCategory);6283  if (typeParams.size()) {6284    vectorDerivedType.AddRawParamValue(nullptr, std::move(typeParams[0]));6285    vectorDerivedType.AddRawParamValue(nullptr, std::move(typeParams[1]));6286    vectorDerivedType.CookParameters(GetFoldingContext());6287  }6288 6289  if (const DeclTypeSpec *6290      extant{ppcBuiltinTypesScope->FindInstantiatedDerivedType(6291          vectorDerivedType, DeclTypeSpec::Category::TypeDerived)}) {6292    // This derived type and parameter expressions (if any) are already present6293    // in the __ppc_intrinsics scope.6294    SetDeclTypeSpec(*extant);6295  } else {6296    DeclTypeSpec &type{ppcBuiltinTypesScope->MakeDerivedType(6297        DeclTypeSpec::Category::TypeDerived, std::move(vectorDerivedType))};6298    DerivedTypeSpec &derived{type.derivedTypeSpec()};6299    auto restorer{6300        GetFoldingContext().messages().SetLocation(currStmtSource().value())};6301    derived.Instantiate(*ppcBuiltinTypesScope);6302    SetDeclTypeSpec(type);6303  }6304}6305 6306bool DeclarationVisitor::Pre(const parser::DeclarationTypeSpec::Type &) {6307  CHECK(GetDeclTypeSpecCategory() == DeclTypeSpec::Category::TypeDerived);6308  return true;6309}6310 6311void DeclarationVisitor::Post(const parser::DeclarationTypeSpec::Type &type) {6312  const parser::Name &derivedName{std::get<parser::Name>(type.derived.t)};6313  if (const Symbol * derivedSymbol{derivedName.symbol}) {6314    CheckForAbstractType(*derivedSymbol); // C7066315  }6316}6317 6318bool DeclarationVisitor::Pre(const parser::DeclarationTypeSpec::Class &) {6319  SetDeclTypeSpecCategory(DeclTypeSpec::Category::ClassDerived);6320  return true;6321}6322 6323void DeclarationVisitor::Post(6324    const parser::DeclarationTypeSpec::Class &parsedClass) {6325  const auto &typeName{std::get<parser::Name>(parsedClass.derived.t)};6326  if (auto spec{ResolveDerivedType(typeName)};6327      spec && !IsExtensibleType(&*spec)) { // C7056328    SayWithDecl(typeName, *typeName.symbol,6329        "Non-extensible derived type '%s' may not be used with CLASS"6330        " keyword"_err_en_US);6331  }6332}6333 6334void DeclarationVisitor::Post(const parser::DerivedTypeSpec &x) {6335  const auto &typeName{std::get<parser::Name>(x.t)};6336  auto spec{ResolveDerivedType(typeName)};6337  if (!spec) {6338    return;6339  }6340  bool seenAnyName{false};6341  for (const auto &typeParamSpec :6342      std::get<std::list<parser::TypeParamSpec>>(x.t)) {6343    const auto &optKeyword{6344        std::get<std::optional<parser::Keyword>>(typeParamSpec.t)};6345    std::optional<SourceName> name;6346    if (optKeyword) {6347      seenAnyName = true;6348      name = optKeyword->v.source;6349    } else if (seenAnyName) {6350      Say(typeName.source, "Type parameter value must have a name"_err_en_US);6351      continue;6352    }6353    const auto &value{std::get<parser::TypeParamValue>(typeParamSpec.t)};6354    // The expressions in a derived type specifier whose values define6355    // non-defaulted type parameters are evaluated (folded) in the enclosing6356    // scope.  The KIND/LEN distinction is resolved later in6357    // DerivedTypeSpec::CookParameters().6358    ParamValue param{GetParamValue(value, common::TypeParamAttr::Kind)};6359    if (!param.isExplicit() || param.GetExplicit()) {6360      spec->AddRawParamValue(6361          common::GetPtrFromOptional(optKeyword), std::move(param));6362    }6363  }6364  // The DerivedTypeSpec *spec is used initially as a search key.6365  // If it turns out to have the same name and actual parameter6366  // value expressions as another DerivedTypeSpec in the current6367  // scope does, then we'll use that extant spec; otherwise, when this6368  // spec is distinct from all derived types previously instantiated6369  // in the current scope, this spec will be moved into that collection.6370  const auto &dtDetails{spec->typeSymbol().get<DerivedTypeDetails>()};6371  auto category{GetDeclTypeSpecCategory()};6372  if (dtDetails.isForwardReferenced()) {6373    DeclTypeSpec &type{currScope().MakeDerivedType(category, std::move(*spec))};6374    SetDeclTypeSpec(type);6375    return;6376  }6377  // Normalize parameters to produce a better search key.6378  spec->CookParameters(GetFoldingContext());6379  if (!spec->MightBeParameterized()) {6380    spec->EvaluateParameters(context());6381  }6382  if (const DeclTypeSpec *6383      extant{currScope().FindInstantiatedDerivedType(*spec, category)}) {6384    // This derived type and parameter expressions (if any) are already present6385    // in this scope.6386    SetDeclTypeSpec(*extant);6387  } else {6388    DeclTypeSpec &type{currScope().MakeDerivedType(category, std::move(*spec))};6389    DerivedTypeSpec &derived{type.derivedTypeSpec()};6390    if (derived.MightBeParameterized() &&6391        currScope().IsParameterizedDerivedType()) {6392      // Defer instantiation; use the derived type's definition's scope.6393      derived.set_scope(DEREF(spec->typeSymbol().scope()));6394    } else if (&currScope() == spec->typeSymbol().scope()) {6395      // Direct recursive use of a type in the definition of one of its6396      // components: defer instantiation6397    } else {6398      auto restorer{6399          GetFoldingContext().messages().SetLocation(currStmtSource().value())};6400      derived.Instantiate(currScope());6401    }6402    SetDeclTypeSpec(type);6403  }6404  // Capture the DerivedTypeSpec in the parse tree for use in building6405  // structure constructor expressions.6406  x.derivedTypeSpec = &GetDeclTypeSpec()->derivedTypeSpec();6407}6408 6409void DeclarationVisitor::Post(const parser::DeclarationTypeSpec::Record &rec) {6410  const auto &typeName{rec.v};6411  if (auto spec{ResolveDerivedType(typeName)}) {6412    spec->CookParameters(GetFoldingContext());6413    spec->EvaluateParameters(context());6414    if (const DeclTypeSpec *6415        extant{currScope().FindInstantiatedDerivedType(6416            *spec, DeclTypeSpec::TypeDerived)}) {6417      SetDeclTypeSpec(*extant);6418    } else {6419      Say(typeName.source, "%s is not a known STRUCTURE"_err_en_US,6420          typeName.source);6421    }6422  }6423}6424 6425// The descendents of DerivedTypeDef in the parse tree are visited directly6426// in this Pre() routine so that recursive use of the derived type can be6427// supported in the components.6428bool DeclarationVisitor::Pre(const parser::DerivedTypeDef &x) {6429  auto &stmt{std::get<parser::Statement<parser::DerivedTypeStmt>>(x.t)};6430  Walk(stmt);6431  Walk(std::get<std::list<parser::Statement<parser::TypeParamDefStmt>>>(x.t));6432  auto &scope{currScope()};6433  CHECK(scope.symbol());6434  CHECK(scope.symbol()->scope() == &scope);6435  auto &details{scope.symbol()->get<DerivedTypeDetails>()};6436  for (auto &paramName : std::get<std::list<parser::Name>>(stmt.statement.t)) {6437    if (auto *symbol{FindInScope(scope, paramName)}) {6438      if (auto *details{symbol->detailsIf<TypeParamDetails>()}) {6439        if (!details->attr()) {6440          Say(paramName,6441              "No definition found for type parameter '%s'"_err_en_US); // C7426442        }6443      }6444    }6445  }6446  Walk(std::get<std::list<parser::Statement<parser::PrivateOrSequence>>>(x.t));6447  const auto &componentDefs{6448      std::get<std::list<parser::Statement<parser::ComponentDefStmt>>>(x.t)};6449  Walk(componentDefs);6450  if (derivedTypeInfo_.sequence) {6451    details.set_sequence(true);6452    if (componentDefs.empty()) {6453      // F'2023 C745 - not enforced by any compiler6454      context().Warn(common::LanguageFeature::EmptySequenceType, stmt.source,6455          "A sequence type should have at least one component"_warn_en_US);6456    }6457    if (!details.paramDeclOrder().empty()) { // C7406458      Say(stmt.source,6459          "A sequence type may not have type parameters"_err_en_US);6460    }6461    if (derivedTypeInfo_.extends) { // C7356462      Say(stmt.source,6463          "A sequence type may not have the EXTENDS attribute"_err_en_US);6464    }6465  }6466  Walk(std::get<std::optional<parser::TypeBoundProcedurePart>>(x.t));6467  Walk(std::get<parser::Statement<parser::EndTypeStmt>>(x.t));6468  details.set_isForwardReferenced(false);6469  derivedTypeInfo_ = {};6470  PopScope();6471  set_inPDTDefinition(false);6472  return false;6473}6474 6475bool DeclarationVisitor::Pre(const parser::DerivedTypeStmt &) {6476  return BeginAttrs();6477}6478void DeclarationVisitor::Post(const parser::DerivedTypeStmt &x) {6479  auto &name{std::get<parser::Name>(x.t)};6480  // Resolve the EXTENDS() clause before creating the derived6481  // type's symbol to foil attempts to recursively extend a type.6482  auto *extendsName{derivedTypeInfo_.extends};6483  std::optional<DerivedTypeSpec> extendsType{6484      ResolveExtendsType(name, extendsName)};6485  DerivedTypeDetails derivedTypeDetails;6486  // Catch any premature structure constructors within the definition6487  derivedTypeDetails.set_isForwardReferenced(true);6488  auto &symbol{MakeSymbol(name, GetAttrs(), std::move(derivedTypeDetails))};6489  symbol.ReplaceName(name.source);6490  derivedTypeInfo_.type = &symbol;6491  PushScope(Scope::Kind::DerivedType, &symbol);6492  if (extendsType) {6493    // Declare the "parent component"; private if the type is.6494    // Any symbol stored in the EXTENDS() clause is temporarily6495    // hidden so that a new symbol can be created for the parent6496    // component without producing spurious errors about already6497    // existing.6498    const Symbol &extendsSymbol{extendsType->typeSymbol()};6499    if (extendsSymbol.scope() &&6500        extendsSymbol.scope()->IsParameterizedDerivedType()) {6501      set_inPDTDefinition(true);6502    }6503    auto restorer{common::ScopedSet(extendsName->symbol, nullptr)};6504    if (OkToAddComponent(*extendsName, &extendsSymbol)) {6505      auto &comp{DeclareEntity<ObjectEntityDetails>(*extendsName, Attrs{})};6506      comp.attrs().set(6507          Attr::PRIVATE, extendsSymbol.attrs().test(Attr::PRIVATE));6508      comp.implicitAttrs().set(6509          Attr::PRIVATE, extendsSymbol.implicitAttrs().test(Attr::PRIVATE));6510      comp.set(Symbol::Flag::ParentComp);6511      DeclTypeSpec &type{currScope().MakeDerivedType(6512          DeclTypeSpec::TypeDerived, std::move(*extendsType))};6513      type.derivedTypeSpec().set_scope(DEREF(extendsSymbol.scope()));6514      comp.SetType(type);6515      DerivedTypeDetails &details{symbol.get<DerivedTypeDetails>()};6516      details.add_component(comp);6517    }6518  }6519  // Create symbols now for type parameters so that they shadow names6520  // from the enclosing specification part.6521  const auto &paramNames{std::get<std::list<parser::Name>>(x.t)};6522  if (!paramNames.empty()) {6523    set_inPDTDefinition(true);6524  }6525  if (auto *details{symbol.detailsIf<DerivedTypeDetails>()}) {6526    for (const auto &name : paramNames) {6527      if (Symbol * symbol{MakeTypeSymbol(name, TypeParamDetails{})}) {6528        details->add_paramNameOrder(*symbol);6529      }6530    }6531  }6532  EndAttrs();6533}6534 6535void DeclarationVisitor::Post(const parser::TypeParamDefStmt &x) {6536  auto *type{GetDeclTypeSpec()};6537  DerivedTypeDetails *derivedDetails{nullptr};6538  if (Symbol * dtSym{currScope().symbol()}) {6539    derivedDetails = dtSym->detailsIf<DerivedTypeDetails>();6540  }6541  auto attr{std::get<common::TypeParamAttr>(x.t)};6542  for (auto &decl : std::get<std::list<parser::TypeParamDecl>>(x.t)) {6543    auto &name{std::get<parser::Name>(decl.t)};6544    if (Symbol * symbol{FindInScope(currScope(), name)}) {6545      if (auto *paramDetails{symbol->detailsIf<TypeParamDetails>()}) {6546        if (!paramDetails->attr()) {6547          paramDetails->set_attr(attr);6548          SetType(name, *type);6549          if (auto &init{std::get<std::optional<parser::ScalarIntConstantExpr>>(6550                  decl.t)}) {6551            if (auto maybeExpr{AnalyzeExpr(context(), *init)}) {6552              if (auto *intExpr{std::get_if<SomeIntExpr>(&maybeExpr->u)}) {6553                paramDetails->set_init(std::move(*intExpr));6554              }6555            }6556          }6557          if (derivedDetails) {6558            derivedDetails->add_paramDeclOrder(*symbol);6559          }6560        } else {6561          Say(name,6562              "Type parameter '%s' was already declared in this derived type"_err_en_US);6563        }6564      }6565    } else {6566      Say(name, "'%s' is not a parameter of this derived type"_err_en_US);6567    }6568  }6569  EndDecl();6570}6571bool DeclarationVisitor::Pre(const parser::TypeAttrSpec::Extends &x) {6572  if (derivedTypeInfo_.extends) {6573    Say(currStmtSource().value(),6574        "Attribute 'EXTENDS' cannot be used more than once"_err_en_US);6575  } else {6576    derivedTypeInfo_.extends = &x.v;6577  }6578  return false;6579}6580 6581bool DeclarationVisitor::Pre(const parser::PrivateStmt &) {6582  if (!currScope().parent().IsModule()) {6583    Say("PRIVATE is only allowed in a derived type that is"6584        " in a module"_err_en_US); // C7666585  } else if (derivedTypeInfo_.sawContains) {6586    derivedTypeInfo_.privateBindings = true;6587  } else if (!derivedTypeInfo_.privateComps) {6588    derivedTypeInfo_.privateComps = true;6589  } else { // C7386590    context().Warn(common::LanguageFeature::RedundantAttribute,6591        "PRIVATE should not appear more than once in derived type components"_warn_en_US);6592  }6593  return false;6594}6595bool DeclarationVisitor::Pre(const parser::SequenceStmt &) {6596  if (derivedTypeInfo_.sequence) { // C7386597    context().Warn(common::LanguageFeature::RedundantAttribute,6598        "SEQUENCE should not appear more than once in derived type components"_warn_en_US);6599  }6600  derivedTypeInfo_.sequence = true;6601  return false;6602}6603void DeclarationVisitor::Post(const parser::ComponentDecl &x) {6604  const auto &name{std::get<parser::Name>(x.t)};6605  auto attrs{GetAttrs()};6606  if (derivedTypeInfo_.privateComps &&6607      !attrs.HasAny({Attr::PUBLIC, Attr::PRIVATE})) {6608    attrs.set(Attr::PRIVATE);6609  }6610  if (const auto *declType{GetDeclTypeSpec()}) {6611    if (const auto *derived{declType->AsDerived()}) {6612      if (!attrs.HasAny({Attr::POINTER, Attr::ALLOCATABLE})) {6613        if (derivedTypeInfo_.type == &derived->typeSymbol()) { // C7446614          Say("Recursive use of the derived type requires POINTER or ALLOCATABLE"_err_en_US);6615        }6616      }6617    }6618  }6619  if (OkToAddComponent(name)) {6620    auto &symbol{DeclareObjectEntity(name, attrs)};6621    SetCUDADataAttr(name.source, symbol, cudaDataAttr());6622    if (symbol.has<ObjectEntityDetails>()) {6623      if (auto &init{std::get<std::optional<parser::Initialization>>(x.t)}) {6624        Initialization(name, *init, /*inComponentDecl=*/true);6625      }6626    }6627    auto &details{currScope().symbol()->get<DerivedTypeDetails>()};6628    details.add_component(symbol);6629    if (const parser::Expr *kindExpr{GetOriginalKindParameter()}) {6630      details.add_originalKindParameter(name.source, kindExpr);6631    }6632  }6633  ClearArraySpec();6634  ClearCoarraySpec();6635}6636void DeclarationVisitor::Post(const parser::FillDecl &x) {6637  // Replace "%FILL" with a distinct generated name6638  const auto &name{std::get<parser::Name>(x.t)};6639  const_cast<SourceName &>(name.source) = context().GetTempName(currScope());6640  if (OkToAddComponent(name)) {6641    auto &symbol{DeclareObjectEntity(name, GetAttrs())};6642    currScope().symbol()->get<DerivedTypeDetails>().add_component(symbol);6643  }6644  ClearArraySpec();6645}6646bool DeclarationVisitor::Pre(const parser::ProcedureDeclarationStmt &x) {6647  CHECK(!interfaceName_);6648  const auto &procAttrSpec{std::get<std::list<parser::ProcAttrSpec>>(x.t)};6649  for (const parser::ProcAttrSpec &procAttr : procAttrSpec) {6650    if (auto *bindC{std::get_if<parser::LanguageBindingSpec>(&procAttr.u)}) {6651      if (std::get<std::optional<parser::ScalarDefaultCharConstantExpr>>(6652              bindC->t)6653              .has_value()) {6654        if (std::get<std::list<parser::ProcDecl>>(x.t).size() > 1) {6655          Say(context().location().value(),6656              "A procedure declaration statement with a binding name may not declare multiple procedures"_err_en_US);6657        }6658        break;6659      }6660    }6661  }6662  return BeginDecl();6663}6664void DeclarationVisitor::Post(const parser::ProcedureDeclarationStmt &) {6665  interfaceName_ = nullptr;6666  EndDecl();6667}6668bool DeclarationVisitor::Pre(const parser::DataComponentDefStmt &x) {6669  // Overrides parse tree traversal so as to handle attributes first,6670  // so POINTER & ALLOCATABLE enable forward references to derived types.6671  Walk(std::get<std::list<parser::ComponentAttrSpec>>(x.t));6672  set_allowForwardReferenceToDerivedType(6673      GetAttrs().HasAny({Attr::POINTER, Attr::ALLOCATABLE}));6674  Walk(std::get<parser::DeclarationTypeSpec>(x.t));6675  set_allowForwardReferenceToDerivedType(false);6676  if (derivedTypeInfo_.sequence) { // C7406677    if (const auto *declType{GetDeclTypeSpec()}) {6678      if (!declType->AsIntrinsic() && !declType->IsSequenceType() &&6679          !InModuleFile()) {6680        if (GetAttrs().test(Attr::POINTER) &&6681            context().IsEnabled(common::LanguageFeature::PointerInSeqType)) {6682          context().Warn(common::LanguageFeature::PointerInSeqType,6683              "A sequence type data component that is a pointer to a non-sequence type is not standard"_port_en_US);6684        } else {6685          Say("A sequence type data component must either be of an intrinsic type or a derived sequence type"_err_en_US);6686        }6687      }6688    }6689  }6690  Walk(std::get<std::list<parser::ComponentOrFill>>(x.t));6691  return false;6692}6693bool DeclarationVisitor::Pre(const parser::ProcComponentDefStmt &) {6694  CHECK(!interfaceName_);6695  return true;6696}6697void DeclarationVisitor::Post(const parser::ProcComponentDefStmt &) {6698  interfaceName_ = nullptr;6699}6700bool DeclarationVisitor::Pre(const parser::ProcPointerInit &x) {6701  if (auto *name{std::get_if<parser::Name>(&x.u)}) {6702    return !NameIsKnownOrIntrinsic(*name) && !CheckUseError(*name);6703  } else {6704    const auto &null{DEREF(std::get_if<parser::NullInit>(&x.u))};6705    Walk(null);6706    if (auto nullInit{EvaluateExpr(null)}) {6707      if (!evaluate::IsNullProcedurePointer(&*nullInit) &&6708          !evaluate::IsBareNullPointer(&*nullInit)) {6709        Say(null.v.value().source,6710            "Procedure pointer initializer must be a name or intrinsic NULL()"_err_en_US);6711      }6712    }6713    return false;6714  }6715}6716void DeclarationVisitor::Post(const parser::ProcInterface &x) {6717  if (auto *name{std::get_if<parser::Name>(&x.u)}) {6718    interfaceName_ = name;6719    NoteInterfaceName(*name);6720  }6721}6722void DeclarationVisitor::Post(const parser::ProcDecl &x) {6723  const auto &name{std::get<parser::Name>(x.t)};6724  // Don't use BypassGeneric or GetUltimate on this symbol, they can6725  // lead to unusable names in module files.6726  const Symbol *procInterface{6727      interfaceName_ ? interfaceName_->symbol : nullptr};6728  auto attrs{HandleSaveName(name.source, GetAttrs())};6729  DerivedTypeDetails *dtDetails{nullptr};6730  if (Symbol * symbol{currScope().symbol()}) {6731    dtDetails = symbol->detailsIf<DerivedTypeDetails>();6732  }6733  if (!dtDetails) {6734    attrs.set(Attr::EXTERNAL);6735  }6736  if (derivedTypeInfo_.privateComps &&6737      !attrs.HasAny({Attr::PUBLIC, Attr::PRIVATE})) {6738    attrs.set(Attr::PRIVATE);6739  }6740  Symbol &symbol{DeclareProcEntity(name, attrs, procInterface)};6741  SetCUDADataAttr(name.source, symbol, cudaDataAttr()); // for error6742  symbol.ReplaceName(name.source);6743  if (dtDetails) {6744    dtDetails->add_component(symbol);6745  }6746  DeclaredPossibleSpecificProc(symbol);6747}6748 6749bool DeclarationVisitor::Pre(const parser::TypeBoundProcedurePart &) {6750  derivedTypeInfo_.sawContains = true;6751  return true;6752}6753 6754// Resolve binding names from type-bound generics, saved in genericBindings_.6755void DeclarationVisitor::Post(const parser::TypeBoundProcedurePart &) {6756  // track specifics seen for the current generic to detect duplicates:6757  const Symbol *currGeneric{nullptr};6758  std::set<SourceName> specifics;6759  for (const auto &[generic, bindingName] : genericBindings_) {6760    if (generic != currGeneric) {6761      currGeneric = generic;6762      specifics.clear();6763    }6764    auto [it, inserted]{specifics.insert(bindingName->source)};6765    if (!inserted) {6766      Say(*bindingName, // C7736767          "Binding name '%s' was already specified for generic '%s'"_err_en_US,6768          bindingName->source, generic->name())6769          .Attach(*it, "Previous specification of '%s'"_en_US, *it);6770      continue;6771    }6772    auto *symbol{FindInTypeOrParents(*bindingName)};6773    if (!symbol) {6774      Say(*bindingName, // C7726775          "Binding name '%s' not found in this derived type"_err_en_US);6776    } else if (!symbol->has<ProcBindingDetails>()) {6777      SayWithDecl(*bindingName, *symbol, // C7726778          "'%s' is not the name of a specific binding of this type"_err_en_US);6779    } else {6780      generic->get<GenericDetails>().AddSpecificProc(6781          *symbol, bindingName->source);6782    }6783  }6784  genericBindings_.clear();6785}6786 6787void DeclarationVisitor::Post(const parser::ContainsStmt &) {6788  if (derivedTypeInfo_.sequence) {6789    Say("A sequence type may not have a CONTAINS statement"_err_en_US); // C7406790  }6791}6792 6793void DeclarationVisitor::Post(6794    const parser::TypeBoundProcedureStmt::WithoutInterface &x) {6795  if (GetAttrs().test(Attr::DEFERRED)) { // C7836796    Say("DEFERRED is only allowed when an interface-name is provided"_err_en_US);6797  }6798  for (auto &declaration : x.declarations) {6799    auto &bindingName{std::get<parser::Name>(declaration.t)};6800    auto &optName{std::get<std::optional<parser::Name>>(declaration.t)};6801    const parser::Name &procedureName{optName ? *optName : bindingName};6802    Symbol *procedure{FindSymbol(procedureName)};6803    if (!procedure) {6804      procedure = NoteInterfaceName(procedureName);6805    }6806    if (procedure) {6807      const Symbol &bindTo{BypassGeneric(*procedure)};6808      if (auto *s{MakeTypeSymbol(bindingName, ProcBindingDetails{bindTo})}) {6809        SetPassNameOn(*s);6810        if (GetAttrs().test(Attr::DEFERRED)) {6811          context().SetError(*s);6812        }6813      }6814    }6815  }6816}6817 6818void DeclarationVisitor::CheckBindings(6819    const parser::TypeBoundProcedureStmt::WithoutInterface &tbps) {6820  CHECK(currScope().IsDerivedType());6821  for (auto &declaration : tbps.declarations) {6822    auto &bindingName{std::get<parser::Name>(declaration.t)};6823    if (Symbol * binding{FindInScope(bindingName)}) {6824      if (auto *details{binding->detailsIf<ProcBindingDetails>()}) {6825        const Symbol &ultimate{details->symbol().GetUltimate()};6826        const Symbol &procedure{BypassGeneric(ultimate)};6827        if (&procedure != &ultimate) {6828          details->ReplaceSymbol(procedure);6829        }6830        if (!CanBeTypeBoundProc(procedure)) {6831          if (details->symbol().name() != binding->name()) {6832            Say(binding->name(),6833                "The binding of '%s' ('%s') must be either an accessible "6834                "module procedure or an external procedure with "6835                "an explicit interface"_err_en_US,6836                binding->name(), details->symbol().name());6837          } else {6838            Say(binding->name(),6839                "'%s' must be either an accessible module procedure "6840                "or an external procedure with an explicit interface"_err_en_US,6841                binding->name());6842          }6843          context().SetError(*binding);6844        }6845      }6846    }6847  }6848}6849 6850void DeclarationVisitor::Post(6851    const parser::TypeBoundProcedureStmt::WithInterface &x) {6852  if (!GetAttrs().test(Attr::DEFERRED)) { // C7836853    Say("DEFERRED is required when an interface-name is provided"_err_en_US);6854  }6855  if (Symbol * interface{NoteInterfaceName(x.interfaceName)}) {6856    for (auto &bindingName : x.bindingNames) {6857      if (auto *s{6858              MakeTypeSymbol(bindingName, ProcBindingDetails{*interface})}) {6859        SetPassNameOn(*s);6860        if (!GetAttrs().test(Attr::DEFERRED)) {6861          context().SetError(*s);6862        }6863      }6864    }6865  }6866}6867 6868bool DeclarationVisitor::Pre(const parser::FinalProcedureStmt &x) {6869  if (currScope().IsDerivedType() && currScope().symbol()) {6870    if (auto *details{currScope().symbol()->detailsIf<DerivedTypeDetails>()}) {6871      for (const auto &subrName : x.v) {6872        Symbol *symbol{FindSymbol(subrName)};6873        if (!symbol) {6874          // FINAL procedures must be module subroutines6875          symbol = &MakeSymbol(6876              currScope().parent(), subrName.source, Attrs{Attr::MODULE});6877          Resolve(subrName, symbol);6878          symbol->set_details(ProcEntityDetails{});6879          symbol->set(Symbol::Flag::Subroutine);6880        }6881        if (auto pair{details->finals().emplace(subrName.source, *symbol)};6882            !pair.second) { // C7876883          Say(subrName.source,6884              "FINAL subroutine '%s' already appeared in this derived type"_err_en_US,6885              subrName.source)6886              .Attach(pair.first->first,6887                  "earlier appearance of this FINAL subroutine"_en_US);6888        }6889      }6890    }6891  }6892  return false;6893}6894 6895bool DeclarationVisitor::Pre(const parser::TypeBoundGenericStmt &x) {6896  const auto &accessSpec{std::get<std::optional<parser::AccessSpec>>(x.t)};6897  const auto &genericSpec{std::get<Indirection<parser::GenericSpec>>(x.t)};6898  const auto &bindingNames{std::get<std::list<parser::Name>>(x.t)};6899  GenericSpecInfo info{genericSpec.value()};6900  SourceName symbolName{info.symbolName()};6901  bool isPrivate{accessSpec ? accessSpec->v == parser::AccessSpec::Kind::Private6902                            : derivedTypeInfo_.privateBindings};6903  auto *genericSymbol{FindInScope(symbolName)};6904  if (genericSymbol) {6905    if (!genericSymbol->has<GenericDetails>()) {6906      genericSymbol = nullptr; // MakeTypeSymbol will report the error below6907    }6908  } else {6909    // look in ancestor types for a generic of the same name6910    for (const auto &name : GetAllNames(context(), symbolName)) {6911      if (Symbol * inherited{currScope().FindComponent(SourceName{name})}) {6912        if (inherited->has<GenericDetails>()) {6913          CheckAccessibility(symbolName, isPrivate, *inherited); // C7716914        } else {6915          Say(symbolName,6916              "Type bound generic procedure '%s' may not have the same name as a non-generic symbol inherited from an ancestor type"_err_en_US)6917              .Attach(inherited->name(), "Inherited symbol"_en_US);6918        }6919        break;6920      }6921    }6922  }6923  if (genericSymbol) {6924    CheckAccessibility(symbolName, isPrivate, *genericSymbol); // C7716925  } else {6926    genericSymbol = MakeTypeSymbol(symbolName, GenericDetails{});6927    if (!genericSymbol) {6928      return false;6929    }6930    if (isPrivate) {6931      SetExplicitAttr(*genericSymbol, Attr::PRIVATE);6932    }6933  }6934  for (const parser::Name &bindingName : bindingNames) {6935    genericBindings_.emplace(genericSymbol, &bindingName);6936  }6937  info.Resolve(genericSymbol);6938  return false;6939}6940 6941// DEC STRUCTUREs are handled thus to allow for nested definitions.6942bool DeclarationVisitor::Pre(const parser::StructureDef &def) {6943  const auto &structureStatement{6944      std::get<parser::Statement<parser::StructureStmt>>(def.t)};6945  auto saveDerivedTypeInfo{derivedTypeInfo_};6946  derivedTypeInfo_ = {};6947  derivedTypeInfo_.isStructure = true;6948  derivedTypeInfo_.sequence = true;6949  Scope *previousStructure{nullptr};6950  if (saveDerivedTypeInfo.isStructure) {6951    previousStructure = &currScope();6952    PopScope();6953  }6954  const parser::StructureStmt &structStmt{structureStatement.statement};6955  const auto &name{std::get<std::optional<parser::Name>>(structStmt.t)};6956  if (!name) {6957    // Construct a distinct generated name for an anonymous structure6958    auto &mutableName{const_cast<std::optional<parser::Name> &>(name)};6959    mutableName.emplace(6960        parser::Name{context().GetTempName(currScope()), nullptr});6961  }6962  auto &symbol{MakeSymbol(*name, DerivedTypeDetails{})};6963  symbol.ReplaceName(name->source);6964  symbol.get<DerivedTypeDetails>().set_sequence(true);6965  symbol.get<DerivedTypeDetails>().set_isDECStructure(true);6966  derivedTypeInfo_.type = &symbol;6967  PushScope(Scope::Kind::DerivedType, &symbol);6968  const auto &fields{std::get<std::list<parser::StructureField>>(def.t)};6969  Walk(fields);6970  PopScope();6971  // Complete the definition6972  DerivedTypeSpec derivedTypeSpec{symbol.name(), symbol};6973  derivedTypeSpec.set_scope(DEREF(symbol.scope()));6974  derivedTypeSpec.CookParameters(GetFoldingContext());6975  derivedTypeSpec.EvaluateParameters(context());6976  DeclTypeSpec &type{currScope().MakeDerivedType(6977      DeclTypeSpec::TypeDerived, std::move(derivedTypeSpec))};6978  type.derivedTypeSpec().Instantiate(currScope());6979  // Restore previous structure definition context, if any6980  derivedTypeInfo_ = saveDerivedTypeInfo;6981  if (previousStructure) {6982    PushScope(*previousStructure);6983  }6984  // Handle any entity declarations on the STRUCTURE statement6985  const auto &decls{std::get<std::list<parser::EntityDecl>>(structStmt.t)};6986  if (!decls.empty()) {6987    BeginDecl();6988    SetDeclTypeSpec(type);6989    Walk(decls);6990    EndDecl();6991  }6992  return false;6993}6994 6995bool DeclarationVisitor::Pre(const parser::Union::UnionStmt &) {6996  Say("support for UNION"_todo_en_US); // TODO6997  return true;6998}6999 7000bool DeclarationVisitor::Pre(const parser::StructureField &x) {7001  if (std::holds_alternative<parser::Statement<parser::DataComponentDefStmt>>(7002          x.u)) {7003    BeginDecl();7004  }7005  return true;7006}7007 7008void DeclarationVisitor::Post(const parser::StructureField &x) {7009  if (std::holds_alternative<parser::Statement<parser::DataComponentDefStmt>>(7010          x.u)) {7011    EndDecl();7012  }7013}7014 7015bool DeclarationVisitor::Pre(const parser::AllocateStmt &) {7016  BeginDeclTypeSpec();7017  return true;7018}7019void DeclarationVisitor::Post(const parser::AllocateStmt &) {7020  EndDeclTypeSpec();7021}7022 7023bool DeclarationVisitor::Pre(const parser::StructureConstructor &x) {7024  auto &parsedType{std::get<parser::DerivedTypeSpec>(x.t)};7025  const DeclTypeSpec *type{ProcessTypeSpec(parsedType)};7026  if (!type) {7027    return false;7028  }7029  const DerivedTypeSpec *spec{type->AsDerived()};7030  const Scope *typeScope{spec ? spec->scope() : nullptr};7031  if (!typeScope) {7032    return false;7033  }7034 7035  // N.B C7102 is implicitly enforced by having inaccessible types not7036  // being found in resolution.7037  // More constraints are enforced in expression.cpp so that they7038  // can apply to structure constructors that have been converted7039  // from misparsed function references.7040  for (const auto &component :7041      std::get<std::list<parser::ComponentSpec>>(x.t)) {7042    // Visit the component spec expression, but not the keyword, since7043    // we need to resolve its symbol in the scope of the derived type.7044    Walk(std::get<parser::ComponentDataSource>(component.t));7045    if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) {7046      FindInTypeOrParents(*typeScope, kw->v);7047    }7048  }7049  return false;7050}7051 7052bool DeclarationVisitor::Pre(const parser::BasedPointer &) {7053  BeginArraySpec();7054  return true;7055}7056 7057void DeclarationVisitor::Post(const parser::BasedPointer &bp) {7058  const parser::ObjectName &pointerName{std::get<0>(bp.t)};7059  auto *pointer{FindInScope(pointerName)};7060  if (!pointer) {7061    pointer = &MakeSymbol(pointerName, ObjectEntityDetails{});7062  } else if (!ConvertToObjectEntity(*pointer)) {7063    SayWithDecl(pointerName, *pointer, "'%s' is not a variable"_err_en_US);7064  } else if (IsNamedConstant(*pointer)) {7065    SayWithDecl(pointerName, *pointer,7066        "'%s' is a named constant and may not be a Cray pointer"_err_en_US);7067  } else if (pointer->Rank() > 0) {7068    SayWithDecl(7069        pointerName, *pointer, "Cray pointer '%s' must be a scalar"_err_en_US);7070  } else if (pointer->test(Symbol::Flag::CrayPointee)) {7071    Say(pointerName,7072        "'%s' cannot be a Cray pointer as it is already a Cray pointee"_err_en_US);7073  }7074  pointer->set(Symbol::Flag::CrayPointer);7075  const DeclTypeSpec &pointerType{MakeNumericType(TypeCategory::Integer,7076      context().targetCharacteristics().integerKindForPointer())};7077  const auto *type{pointer->GetType()};7078  if (!type) {7079    pointer->SetType(pointerType);7080  } else if (*type != pointerType) {7081    Say(pointerName.source, "Cray pointer '%s' must have type %s"_err_en_US,7082        pointerName.source, pointerType.AsFortran());7083  }7084  const parser::ObjectName &pointeeName{std::get<1>(bp.t)};7085  DeclareObjectEntity(pointeeName);7086  if (Symbol * pointee{pointeeName.symbol}) {7087    if (!ConvertToObjectEntity(*pointee)) {7088      return;7089    }7090    if (IsNamedConstant(*pointee)) {7091      Say(pointeeName,7092          "'%s' is a named constant and may not be a Cray pointee"_err_en_US);7093      return;7094    }7095    if (pointee->test(Symbol::Flag::CrayPointer)) {7096      Say(pointeeName,7097          "'%s' cannot be a Cray pointee as it is already a Cray pointer"_err_en_US);7098    } else if (pointee->test(Symbol::Flag::CrayPointee)) {7099      Say(pointeeName, "'%s' was already declared as a Cray pointee"_err_en_US);7100    } else {7101      pointee->set(Symbol::Flag::CrayPointee);7102    }7103    if (const auto *pointeeType{pointee->GetType()}) {7104      if (const auto *derived{pointeeType->AsDerived()}) {7105        if (!IsSequenceOrBindCType(derived)) {7106          context().Warn(common::LanguageFeature::NonSequenceCrayPointee,7107              pointeeName.source,7108              "Type of Cray pointee '%s' is a derived type that is neither SEQUENCE nor BIND(C)"_warn_en_US,7109              pointeeName.source);7110        }7111      }7112    }7113    currScope().add_crayPointer(pointeeName.source, *pointer);7114  }7115}7116 7117bool DeclarationVisitor::Pre(const parser::NamelistStmt::Group &x) {7118  if (!CheckNotInBlock("NAMELIST")) { // C11077119    return false;7120  }7121  const auto &groupName{std::get<parser::Name>(x.t)};7122  auto *groupSymbol{FindInScope(groupName)};7123  if (!groupSymbol || !groupSymbol->has<NamelistDetails>()) {7124    groupSymbol = &MakeSymbol(groupName, NamelistDetails{});7125    groupSymbol->ReplaceName(groupName.source);7126  }7127  // Name resolution of group items is deferred to FinishNamelists()7128  // so that host association is handled correctly.7129  GetDeferredDeclarationState(true)->namelistGroups.emplace_back(&x);7130  return false;7131}7132 7133void DeclarationVisitor::FinishNamelists() {7134  if (auto *deferred{GetDeferredDeclarationState()}) {7135    for (const parser::NamelistStmt::Group *group : deferred->namelistGroups) {7136      if (auto *groupSymbol{FindInScope(std::get<parser::Name>(group->t))}) {7137        if (auto *details{groupSymbol->detailsIf<NamelistDetails>()}) {7138          for (const auto &name : std::get<std::list<parser::Name>>(group->t)) {7139            auto *symbol{FindSymbol(name)};7140            if (!symbol) {7141              symbol = &MakeSymbol(name, ObjectEntityDetails{});7142              ApplyImplicitRules(*symbol);7143            } else if (!ConvertToObjectEntity(symbol->GetUltimate())) {7144              SayWithDecl(name, *symbol, "'%s' is not a variable"_err_en_US);7145              context().SetError(*groupSymbol);7146            }7147            symbol->GetUltimate().set(Symbol::Flag::InNamelist);7148            details->add_object(*symbol);7149          }7150        }7151      }7152    }7153    deferred->namelistGroups.clear();7154  }7155}7156 7157bool DeclarationVisitor::Pre(const parser::IoControlSpec &x) {7158  if (const auto *name{std::get_if<parser::Name>(&x.u)}) {7159    auto *symbol{FindSymbol(*name)};7160    if (!symbol) {7161      Say(*name, "Namelist group '%s' not found"_err_en_US);7162    } else if (!symbol->GetUltimate().has<NamelistDetails>()) {7163      SayWithDecl(7164          *name, *symbol, "'%s' is not the name of a namelist group"_err_en_US);7165    }7166  }7167  return true;7168}7169 7170bool DeclarationVisitor::Pre(const parser::CommonStmt::Block &x) {7171  CheckNotInBlock("COMMON"); // C11077172  return true;7173}7174 7175bool DeclarationVisitor::Pre(const parser::CommonBlockObject &) {7176  BeginArraySpec();7177  return true;7178}7179 7180void DeclarationVisitor::Post(const parser::CommonBlockObject &x) {7181  const auto &name{std::get<parser::Name>(x.t)};7182  if (auto *symbol{FindSymbol(name)}) {7183    symbol->set(Symbol::Flag::InCommonBlock);7184  }7185  DeclareObjectEntity(name);7186  auto pair{specPartState_.commonBlockObjects.insert(name.source)};7187  if (!pair.second) {7188    const SourceName &prev{*pair.first};7189    Say2(name.source, "'%s' is already in a COMMON block"_err_en_US, prev,7190        "Previous occurrence of '%s' in a COMMON block"_en_US);7191  }7192}7193 7194bool DeclarationVisitor::Pre(const parser::EquivalenceStmt &x) {7195  // save equivalence sets to be processed after specification part7196  if (CheckNotInBlock("EQUIVALENCE")) { // C11077197    for (const std::list<parser::EquivalenceObject> &set : x.v) {7198      specPartState_.equivalenceSets.push_back(&set);7199    }7200  }7201  return false; // don't implicitly declare names yet7202}7203 7204void DeclarationVisitor::CheckEquivalenceSets() {7205  EquivalenceSets equivSets{context()};7206  inEquivalenceStmt_ = true;7207  for (const auto *set : specPartState_.equivalenceSets) {7208    const auto &source{set->front().v.value().source};7209    if (set->size() <= 1) { // R8717210      Say(source, "Equivalence set must have more than one object"_err_en_US);7211    }7212    for (const parser::EquivalenceObject &object : *set) {7213      const auto &designator{object.v.value()};7214      // The designator was not resolved when it was encountered, so do it now.7215      // AnalyzeExpr causes array sections to be changed to substrings as needed7216      Walk(designator);7217      if (AnalyzeExpr(context(), designator)) {7218        equivSets.AddToSet(designator);7219      }7220    }7221    equivSets.FinishSet(source);7222  }7223  inEquivalenceStmt_ = false;7224  for (auto &set : equivSets.sets()) {7225    if (!set.empty()) {7226      currScope().add_equivalenceSet(std::move(set));7227    }7228  }7229  specPartState_.equivalenceSets.clear();7230}7231 7232bool DeclarationVisitor::Pre(const parser::SaveStmt &x) {7233  if (x.v.empty()) {7234    specPartState_.saveInfo.saveAll = currStmtSource();7235    currScope().set_hasSAVE();7236  } else {7237    for (const parser::SavedEntity &y : x.v) {7238      auto kind{std::get<parser::SavedEntity::Kind>(y.t)};7239      const auto &name{std::get<parser::Name>(y.t)};7240      if (kind == parser::SavedEntity::Kind::Common) {7241        MakeCommonBlockSymbol(name, name.source);7242        AddSaveName(specPartState_.saveInfo.commons, name.source);7243      } else {7244        HandleAttributeStmt(Attr::SAVE, name);7245      }7246    }7247  }7248  return false;7249}7250 7251void DeclarationVisitor::CheckSaveStmts() {7252  for (const SourceName &name : specPartState_.saveInfo.entities) {7253    auto *symbol{FindInScope(name)};7254    if (!symbol) {7255      // error was reported7256    } else if (specPartState_.saveInfo.saveAll) {7257      // C889 - note that pgi, ifort, xlf do not enforce this constraint7258      if (context().ShouldWarn(common::LanguageFeature::RedundantAttribute)) {7259        Say2(name,7260            "Explicit SAVE of '%s' is redundant due to global SAVE statement"_warn_en_US,7261            *specPartState_.saveInfo.saveAll, "Global SAVE statement"_en_US)7262            .set_languageFeature(common::LanguageFeature::RedundantAttribute);7263      }7264    } else if (!IsSaved(*symbol)) {7265      SetExplicitAttr(*symbol, Attr::SAVE);7266    }7267  }7268  for (const SourceName &name : specPartState_.saveInfo.commons) {7269    if (auto *symbol{currScope().FindCommonBlock(name)}) {7270      auto &objects{symbol->get<CommonBlockDetails>().objects()};7271      if (objects.empty()) {7272        if (currScope().kind() != Scope::Kind::BlockConstruct) {7273          Say(name,7274              "'%s' appears as a COMMON block in a SAVE statement but not in"7275              " a COMMON statement"_err_en_US);7276        } else { // C11087277          Say(name,7278              "SAVE statement in BLOCK construct may not contain a"7279              " common block name '%s'"_err_en_US);7280        }7281      } else {7282        for (auto &object : symbol->get<CommonBlockDetails>().objects()) {7283          if (!IsSaved(*object)) {7284            SetImplicitAttr(*object, Attr::SAVE);7285          }7286        }7287      }7288    }7289  }7290  specPartState_.saveInfo = {};7291}7292 7293// Record SAVEd names in specPartState_.saveInfo.entities.7294Attrs DeclarationVisitor::HandleSaveName(const SourceName &name, Attrs attrs) {7295  if (attrs.test(Attr::SAVE)) {7296    AddSaveName(specPartState_.saveInfo.entities, name);7297  }7298  return attrs;7299}7300 7301// Record a name in a set of those to be saved.7302void DeclarationVisitor::AddSaveName(7303    std::set<SourceName> &set, const SourceName &name) {7304  auto pair{set.insert(name)};7305  if (!pair.second &&7306      context().ShouldWarn(common::LanguageFeature::RedundantAttribute)) {7307    Say2(name, "SAVE attribute was already specified on '%s'"_warn_en_US,7308        *pair.first, "Previous specification of SAVE attribute"_en_US)7309        .set_languageFeature(common::LanguageFeature::RedundantAttribute);7310  }7311}7312 7313// Check types of common block objects, now that they are known.7314void DeclarationVisitor::CheckCommonBlocks() {7315  // check for empty common blocks7316  for (const auto &pair : currScope().commonBlocks()) {7317    const auto &symbol{*pair.second};7318    if (symbol.get<CommonBlockDetails>().objects().empty() &&7319        symbol.attrs().test(Attr::BIND_C)) {7320      Say(symbol.name(),7321          "'%s' appears as a COMMON block in a BIND statement but not in a COMMON statement"_err_en_US);7322    }7323  }7324  specPartState_.commonBlockObjects = {};7325}7326 7327Symbol &DeclarationVisitor::MakeCommonBlockSymbol(7328    const parser::Name &name, SourceName location) {7329  return Resolve(name, currScope().MakeCommonBlock(name.source, location));7330}7331Symbol &DeclarationVisitor::MakeCommonBlockSymbol(7332    const std::optional<parser::Name> &name, SourceName location) {7333  if (name) {7334    return MakeCommonBlockSymbol(*name, location);7335  } else {7336    return MakeCommonBlockSymbol(parser::Name{}, location);7337  }7338}7339 7340bool DeclarationVisitor::NameIsKnownOrIntrinsic(const parser::Name &name) {7341  return FindSymbol(name) || HandleUnrestrictedSpecificIntrinsicFunction(name);7342}7343 7344bool DeclarationVisitor::HandleUnrestrictedSpecificIntrinsicFunction(7345    const parser::Name &name) {7346  if (auto interface{context().intrinsics().IsSpecificIntrinsicFunction(7347          name.source.ToString())}) {7348    // Unrestricted specific intrinsic function names (e.g., "cos")7349    // are acceptable as procedure interfaces.  The presence of the7350    // INTRINSIC flag will cause this symbol to have a complete interface7351    // recreated for it later on demand, but capturing its result type here7352    // will make GetType() return a correct result without having to7353    // probe the intrinsics table again.7354    Symbol &symbol{MakeSymbol(InclusiveScope(), name.source, Attrs{})};7355    SetImplicitAttr(symbol, Attr::INTRINSIC);7356    CHECK(interface->functionResult.has_value());7357    evaluate::DynamicType dyType{7358        DEREF(interface->functionResult->GetTypeAndShape()).type()};7359    CHECK(common::IsNumericTypeCategory(dyType.category()));7360    const DeclTypeSpec &typeSpec{7361        MakeNumericType(dyType.category(), dyType.kind())};7362    ProcEntityDetails details;7363    details.set_type(typeSpec);7364    symbol.set_details(std::move(details));7365    symbol.set(Symbol::Flag::Function);7366    if (interface->IsElemental()) {7367      SetExplicitAttr(symbol, Attr::ELEMENTAL);7368    }7369    if (interface->IsPure()) {7370      SetExplicitAttr(symbol, Attr::PURE);7371    }7372    Resolve(name, symbol);7373    return true;7374  } else {7375    return false;7376  }7377}7378 7379// Checks for all locality-specs: LOCAL, LOCAL_INIT, and SHARED7380bool DeclarationVisitor::PassesSharedLocalityChecks(7381    const parser::Name &name, Symbol &symbol) {7382  if (!IsVariableName(symbol)) {7383    SayLocalMustBeVariable(name, symbol); // C11247384    return false;7385  }7386  if (symbol.owner() == currScope()) { // C1125 and C11267387    SayAlreadyDeclared(name, symbol);7388    return false;7389  }7390  return true;7391}7392 7393// Checks for locality-specs LOCAL, LOCAL_INIT, and REDUCE7394bool DeclarationVisitor::PassesLocalityChecks(7395    const parser::Name &name, Symbol &symbol, Symbol::Flag flag) {7396  bool isReduce{flag == Symbol::Flag::LocalityReduce};7397  const char *specName{7398      flag == Symbol::Flag::LocalityLocalInit ? "LOCAL_INIT" : "LOCAL"};7399  if (IsAllocatable(symbol) && !isReduce) { // F'2023 C11307400    SayWithDecl(name, symbol,7401        "ALLOCATABLE variable '%s' not allowed in a %s locality-spec"_err_en_US,7402        specName);7403    return false;7404  }7405  if (IsOptional(symbol)) { // F'2023 C1130-C11317406    SayWithDecl(name, symbol,7407        "OPTIONAL argument '%s' not allowed in a locality-spec"_err_en_US);7408    return false;7409  }7410  if (IsIntentIn(symbol)) { // F'2023 C1130-C11317411    SayWithDecl(name, symbol,7412        "INTENT IN argument '%s' not allowed in a locality-spec"_err_en_US);7413    return false;7414  }7415  if (IsFinalizable(symbol) && !isReduce) { // F'2023 C11307416    SayWithDecl(name, symbol,7417        "Finalizable variable '%s' not allowed in a %s locality-spec"_err_en_US,7418        specName);7419    return false;7420  }7421  if (evaluate::IsCoarray(symbol) && !isReduce) { // F'2023 C11307422    SayWithDecl(name, symbol,7423        "Coarray '%s' not allowed in a %s locality-spec"_err_en_US, specName);7424    return false;7425  }7426  if (const DeclTypeSpec * type{symbol.GetType()}) {7427    if (type->IsPolymorphic() && IsDummy(symbol) && !IsPointer(symbol) &&7428        !isReduce) { // F'2023 C11307429      SayWithDecl(name, symbol,7430          "Nonpointer polymorphic argument '%s' not allowed in a %s locality-spec"_err_en_US,7431          specName);7432      return false;7433    }7434    if (const DerivedTypeSpec *derived{type->AsDerived()}) { // F'2023 C11307435      if (auto bad{FindAllocatableUltimateComponent(*derived)}) {7436        SayWithDecl(name, symbol,7437            "Derived type variable '%s' with ultimate ALLOCATABLE component '%s' not allowed in a %s locality-spec"_err_en_US,7438            bad.BuildResultDesignatorName(), specName);7439        return false;7440      }7441    }7442  }7443  if (symbol.attrs().test(Attr::ASYNCHRONOUS) && isReduce) { // F'2023 C11317444    SayWithDecl(name, symbol,7445        "ASYNCHRONOUS variable '%s' not allowed in a REDUCE locality-spec"_err_en_US);7446    return false;7447  }7448  if (symbol.attrs().test(Attr::VOLATILE) && isReduce) { // F'2023 C11317449    SayWithDecl(name, symbol,7450        "VOLATILE variable '%s' not allowed in a REDUCE locality-spec"_err_en_US);7451    return false;7452  }7453  if (IsAssumedSizeArray(symbol)) { // F'2023 C1130-C11317454    SayWithDecl(name, symbol,7455        "Assumed size array '%s' not allowed in a locality-spec"_err_en_US);7456    return false;7457  }7458  if (std::optional<Message> whyNot{WhyNotDefinable(7459          name.source, currScope(), DefinabilityFlags{}, symbol)}) {7460    SayWithReason(name, symbol,7461        "'%s' may not appear in a locality-spec because it is not definable"_err_en_US,7462        std::move(whyNot->set_severity(parser::Severity::Because)));7463    return false;7464  }7465  return PassesSharedLocalityChecks(name, symbol);7466}7467 7468Symbol &DeclarationVisitor::FindOrDeclareEnclosingEntity(7469    const parser::Name &name) {7470  Symbol *prev{FindSymbol(name)};7471  if (!prev) {7472    // Declare the name as an object in the enclosing scope so that7473    // the name can't be repurposed there later as something else.7474    prev = &MakeSymbol(InclusiveScope(), name.source, Attrs{});7475    ConvertToObjectEntity(*prev);7476    ApplyImplicitRules(*prev);7477  }7478  return *prev;7479}7480 7481void DeclarationVisitor::DeclareLocalEntity(7482    const parser::Name &name, Symbol::Flag flag) {7483  Symbol &prev{FindOrDeclareEnclosingEntity(name)};7484  if (PassesLocalityChecks(name, prev, flag)) {7485    if (auto *symbol{&MakeHostAssocSymbol(name, prev)}) {7486      symbol->set(flag);7487    }7488  }7489}7490 7491Symbol *DeclarationVisitor::DeclareStatementEntity(7492    const parser::DoVariable &doVar,7493    const std::optional<parser::IntegerTypeSpec> &type) {7494  const auto &name{parser::UnwrapRef<parser::Name>(doVar)};7495  const DeclTypeSpec *declTypeSpec{nullptr};7496  if (auto *prev{FindSymbol(name)}) {7497    if (prev->owner() == currScope()) {7498      SayAlreadyDeclared(name, *prev);7499      return nullptr;7500    }7501    name.symbol = nullptr;7502    // F'2023 19.4 p5 ambiguous rule about outer declarations7503    declTypeSpec = prev->GetType();7504  }7505  Symbol &symbol{DeclareEntity<ObjectEntityDetails>(name, {})};7506  if (!symbol.has<ObjectEntityDetails>()) {7507    return nullptr; // error was reported in DeclareEntity7508  }7509  if (type) {7510    declTypeSpec = ProcessTypeSpec(*type);7511  }7512  if (declTypeSpec) {7513    // Subtlety: Don't let a "*length" specifier (if any is pending) affect the7514    // declaration of this implied DO loop control variable.7515    auto restorer{7516        common::ScopedSet(charInfo_.length, std::optional<ParamValue>{})};7517    SetType(name, *declTypeSpec);7518  } else {7519    ApplyImplicitRules(symbol);7520  }7521  return Resolve(name, &symbol);7522}7523 7524// Set the type of an entity or report an error.7525void DeclarationVisitor::SetType(7526    const parser::Name &name, const DeclTypeSpec &type) {7527  CHECK(name.symbol);7528  auto &symbol{*name.symbol};7529  if (charInfo_.length) { // Declaration has "*length" (R723)7530    auto length{std::move(*charInfo_.length)};7531    charInfo_.length.reset();7532    if (type.category() == DeclTypeSpec::Character) {7533      auto kind{type.characterTypeSpec().kind()};7534      // Recurse with correct type.7535      SetType(name,7536          currScope().MakeCharacterType(std::move(length), std::move(kind)));7537      return;7538    } else { // C7537539      Say(name,7540          "A length specifier cannot be used to declare the non-character entity '%s'"_err_en_US);7541    }7542  }7543  if (auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {7544    if (proc->procInterface()) {7545      Say(name,7546          "'%s' has an explicit interface and may not also have a type"_err_en_US);7547      context().SetError(symbol);7548      return;7549    }7550  }7551  auto *prevType{symbol.GetType()};7552  if (!prevType) {7553    if (symbol.test(Symbol::Flag::InDataStmt) && isImplicitNoneType()) {7554      context().Warn(common::LanguageFeature::ForwardRefImplicitNoneData,7555          name.source,7556          "'%s' appeared in a DATA statement before its type was declared under IMPLICIT NONE(TYPE)"_port_en_US,7557          name.source);7558    }7559    symbol.SetType(type);7560  } else if (symbol.has<UseDetails>()) {7561    // error recovery case, redeclaration of use-associated name7562  } else if (HadForwardRef(symbol)) {7563    // error recovery after use of host-associated name7564  } else if (!symbol.test(Symbol::Flag::Implicit)) {7565    SayWithDecl(7566        name, symbol, "The type of '%s' has already been declared"_err_en_US);7567    context().SetError(symbol);7568  } else if (type != *prevType) {7569    SayWithDecl(name, symbol,7570        "The type of '%s' has already been implicitly declared"_err_en_US);7571    context().SetError(symbol);7572  } else {7573    symbol.set(Symbol::Flag::Implicit, false);7574  }7575}7576 7577std::optional<DerivedTypeSpec> DeclarationVisitor::ResolveDerivedType(7578    const parser::Name &name) {7579  Scope &outer{NonDerivedTypeScope()};7580  Symbol *symbol{FindSymbol(outer, name)};7581  Symbol *ultimate{symbol ? &symbol->GetUltimate() : nullptr};7582  auto *generic{ultimate ? ultimate->detailsIf<GenericDetails>() : nullptr};7583  if (generic) {7584    if (Symbol * genDT{generic->derivedType()}) {7585      symbol = genDT;7586      generic = nullptr;7587    }7588  }7589  if (!symbol || symbol->has<UnknownDetails>() ||7590      (generic && &ultimate->owner() == &outer)) {7591    if (allowForwardReferenceToDerivedType()) {7592      if (!symbol) {7593        symbol = &MakeSymbol(outer, name.source, Attrs{});7594        Resolve(name, *symbol);7595      } else if (generic) {7596        // forward ref to type with later homonymous generic7597        symbol = &outer.MakeSymbol(name.source, Attrs{}, UnknownDetails{});7598        generic->set_derivedType(*symbol);7599        name.symbol = symbol;7600      }7601      DerivedTypeDetails details;7602      details.set_isForwardReferenced(true);7603      symbol->set_details(std::move(details));7604    } else { // C7327605      Say(name, "Derived type '%s' not found"_err_en_US);7606      return std::nullopt;7607    }7608  } else if (&DEREF(symbol).owner() != &outer &&7609      !ultimate->has<GenericDetails>()) {7610    // Prevent a later declaration in this scope of a host-associated7611    // type name.7612    outer.add_importName(name.source);7613  }7614  if (CheckUseError(name)) {7615    return std::nullopt;7616  } else if (symbol->GetUltimate().has<DerivedTypeDetails>()) {7617    return DerivedTypeSpec{name.source, *symbol};7618  } else {7619    Say(name, "'%s' is not a derived type"_err_en_US);7620    return std::nullopt;7621  }7622}7623 7624std::optional<DerivedTypeSpec> DeclarationVisitor::ResolveExtendsType(7625    const parser::Name &typeName, const parser::Name *extendsName) {7626  if (extendsName) {7627    if (typeName.source == extendsName->source) {7628      Say(extendsName->source,7629          "Derived type '%s' cannot extend itself"_err_en_US);7630    } else if (auto dtSpec{ResolveDerivedType(*extendsName)}) {7631      if (!dtSpec->IsForwardReferenced()) {7632        return dtSpec;7633      }7634      Say(typeName.source,7635          "Derived type '%s' cannot extend type '%s' that has not yet been defined"_err_en_US,7636          typeName.source, extendsName->source);7637    }7638  }7639  return std::nullopt;7640}7641 7642Symbol *DeclarationVisitor::NoteInterfaceName(const parser::Name &name) {7643  // The symbol is checked later by CheckExplicitInterface() and7644  // CheckBindings().  It can be a forward reference.7645  if (!NameIsKnownOrIntrinsic(name)) {7646    Symbol &symbol{MakeSymbol(InclusiveScope(), name.source, Attrs{})};7647    Resolve(name, symbol);7648  }7649  return name.symbol;7650}7651 7652void DeclarationVisitor::CheckExplicitInterface(const parser::Name &name) {7653  if (const Symbol * symbol{name.symbol}) {7654    const Symbol &ultimate{symbol->GetUltimate()};7655    if (!context().HasError(*symbol) && !context().HasError(ultimate) &&7656        !BypassGeneric(ultimate).HasExplicitInterface()) {7657      Say(name,7658          "'%s' must be an abstract interface or a procedure with an explicit interface"_err_en_US,7659          symbol->name());7660    }7661  }7662}7663 7664// Create a symbol for a type parameter, component, or procedure binding in7665// the current derived type scope. Return false on error.7666Symbol *DeclarationVisitor::MakeTypeSymbol(7667    const parser::Name &name, Details &&details) {7668  return Resolve(name, MakeTypeSymbol(name.source, std::move(details)));7669}7670Symbol *DeclarationVisitor::MakeTypeSymbol(7671    const SourceName &name, Details &&details) {7672  Scope &derivedType{currScope()};7673  CHECK(derivedType.IsDerivedType());7674  if (auto *symbol{FindInScope(derivedType, name)}) { // C7427675    Say2(name,7676        "Type parameter, component, or procedure binding '%s'"7677        " already defined in this type"_err_en_US,7678        *symbol, "Previous definition of '%s'"_en_US);7679    return nullptr;7680  } else {7681    auto attrs{GetAttrs()};7682    // Apply binding-private-stmt if present and this is a procedure binding7683    if (derivedTypeInfo_.privateBindings &&7684        !attrs.HasAny({Attr::PUBLIC, Attr::PRIVATE}) &&7685        std::holds_alternative<ProcBindingDetails>(details)) {7686      attrs.set(Attr::PRIVATE);7687    }7688    Symbol &result{MakeSymbol(name, attrs, std::move(details))};7689    SetCUDADataAttr(name, result, cudaDataAttr());7690    return &result;7691  }7692}7693 7694// Return true if it is ok to declare this component in the current scope.7695// Otherwise, emit an error and return false.7696bool DeclarationVisitor::OkToAddComponent(7697    const parser::Name &name, const Symbol *extends) {7698  for (const Scope *scope{&currScope()}; scope;) {7699    CHECK(scope->IsDerivedType());7700    if (auto *prev{FindInScope(*scope, name.source)}) {7701      std::optional<parser::MessageFixedText> msg;7702      std::optional<common::UsageWarning> warning;7703      if (context().HasError(*prev)) { // don't pile on7704      } else if (CheckAccessibleSymbol(currScope(), *prev)) {7705        // inaccessible component -- redeclaration is ok7706        if (extends) {7707          // The parent type has a component of same name, but it remains7708          // extensible outside its module since that component is PRIVATE.7709        } else if (context().ShouldWarn(7710                       common::UsageWarning::RedeclaredInaccessibleComponent)) {7711          msg =7712              "Component '%s' is inaccessibly declared in or as a parent of this derived type"_warn_en_US;7713          warning = common::UsageWarning::RedeclaredInaccessibleComponent;7714        }7715      } else if (extends) {7716        msg =7717            "Type cannot be extended as it has a component named '%s'"_err_en_US;7718      } else if (prev->test(Symbol::Flag::ParentComp)) {7719        msg =7720            "'%s' is a parent type of this type and so cannot be a component"_err_en_US;7721      } else if (scope == &currScope()) {7722        msg =7723            "Component '%s' is already declared in this derived type"_err_en_US;7724      } else {7725        msg =7726            "Component '%s' is already declared in a parent of this derived type"_err_en_US;7727      }7728      if (msg) {7729        auto &said{Say2(name, std::move(*msg), *prev,7730            "Previous declaration of '%s'"_en_US)};7731        if (msg->severity() == parser::Severity::Error) {7732          Resolve(name, *prev);7733          return false;7734        }7735        if (warning) {7736          said.set_usageWarning(*warning);7737        }7738      }7739    }7740    if (scope == &currScope() && extends) {7741      // The parent component has not yet been added to the scope.7742      scope = extends->scope();7743    } else {7744      scope = scope->GetDerivedTypeParent();7745    }7746  }7747  return true;7748}7749 7750ParamValue DeclarationVisitor::GetParamValue(7751    const parser::TypeParamValue &x, common::TypeParamAttr attr) {7752  return common::visit(7753      common::visitors{7754          [=](const parser::ScalarIntExpr &x) { // C7047755            return ParamValue{EvaluateIntExpr(x), attr};7756          },7757          [=](const parser::Star &) { return ParamValue::Assumed(attr); },7758          [=](const parser::TypeParamValue::Deferred &) {7759            return ParamValue::Deferred(attr);7760          },7761      },7762      x.u);7763}7764 7765// ConstructVisitor implementation7766 7767void ConstructVisitor::ResolveIndexName(7768    const parser::ConcurrentControl &control) {7769  const parser::Name &name{std::get<parser::Name>(control.t)};7770  auto *prev{FindSymbol(name)};7771  if (prev) {7772    if (prev->owner() == currScope()) {7773      SayAlreadyDeclared(name, *prev);7774      return;7775    } else if (prev->owner().kind() == Scope::Kind::Forall &&7776        context().ShouldWarn(7777            common::LanguageFeature::OddIndexVariableRestrictions)) {7778      SayWithDecl(name, *prev,7779          "Index variable '%s' should not also be an index in an enclosing FORALL or DO CONCURRENT"_port_en_US)7780          .set_languageFeature(7781              common::LanguageFeature::OddIndexVariableRestrictions);7782    }7783    name.symbol = nullptr;7784  }7785  auto &symbol{DeclareObjectEntity(name)};7786  if (symbol.GetType()) {7787    // type came from explicit type-spec7788  } else if (!prev) {7789    ApplyImplicitRules(symbol);7790  } else {7791    // Odd rules in F'2023 19.4 paras 6 & 8.7792    Symbol &prevRoot{prev->GetUltimate()};7793    if (const auto *type{prevRoot.GetType()}) {7794      symbol.SetType(*type);7795    } else {7796      ApplyImplicitRules(symbol);7797    }7798    if (prevRoot.has<ObjectEntityDetails>() ||7799        ConvertToObjectEntity(prevRoot)) {7800      if (prevRoot.IsObjectArray() &&7801          context().ShouldWarn(7802              common::LanguageFeature::OddIndexVariableRestrictions)) {7803        SayWithDecl(name, *prev,7804            "Index variable '%s' should be scalar in the enclosing scope"_port_en_US)7805            .set_languageFeature(7806                common::LanguageFeature::OddIndexVariableRestrictions);7807      }7808    } else if (!prevRoot.has<CommonBlockDetails>() &&7809        context().ShouldWarn(7810            common::LanguageFeature::OddIndexVariableRestrictions)) {7811      SayWithDecl(name, *prev,7812          "Index variable '%s' should be a scalar object or common block if it is present in the enclosing scope"_port_en_US)7813          .set_languageFeature(7814              common::LanguageFeature::OddIndexVariableRestrictions);7815    }7816  }7817  EvaluateExpr(parser::Scalar{parser::Integer{common::Clone(name)}});7818}7819 7820// We need to make sure that all of the index-names get declared before the7821// expressions in the loop control are evaluated so that references to the7822// index-names in the expressions are correctly detected.7823bool ConstructVisitor::Pre(const parser::ConcurrentHeader &header) {7824  BeginDeclTypeSpec();7825  Walk(std::get<std::optional<parser::IntegerTypeSpec>>(header.t));7826  const auto &controls{7827      std::get<std::list<parser::ConcurrentControl>>(header.t)};7828  for (const auto &control : controls) {7829    ResolveIndexName(control);7830  }7831  Walk(controls);7832  Walk(std::get<std::optional<parser::ScalarLogicalExpr>>(header.t));7833  EndDeclTypeSpec();7834  return false;7835}7836 7837bool ConstructVisitor::Pre(const parser::LocalitySpec::Local &x) {7838  for (auto &name : x.v) {7839    DeclareLocalEntity(name, Symbol::Flag::LocalityLocal);7840  }7841  return false;7842}7843 7844bool ConstructVisitor::Pre(const parser::LocalitySpec::LocalInit &x) {7845  for (auto &name : x.v) {7846    DeclareLocalEntity(name, Symbol::Flag::LocalityLocalInit);7847  }7848  return false;7849}7850 7851bool ConstructVisitor::Pre(const parser::LocalitySpec::Reduce &x) {7852  for (const auto &name : std::get<std::list<parser::Name>>(x.t)) {7853    DeclareLocalEntity(name, Symbol::Flag::LocalityReduce);7854  }7855  return false;7856}7857 7858bool ConstructVisitor::Pre(const parser::LocalitySpec::Shared &x) {7859  for (const auto &name : x.v) {7860    if (!FindSymbol(name)) {7861      context().Warn(common::UsageWarning::ImplicitShared, name.source,7862          "Variable '%s' with SHARED locality implicitly declared"_warn_en_US,7863          name.source);7864    }7865    Symbol &prev{FindOrDeclareEnclosingEntity(name)};7866    if (PassesSharedLocalityChecks(name, prev)) {7867      MakeHostAssocSymbol(name, prev).set(Symbol::Flag::LocalityShared);7868    }7869  }7870  return false;7871}7872 7873bool ConstructVisitor::Pre(const parser::AcSpec &x) {7874  ProcessTypeSpec(x.type);7875  Walk(x.values);7876  return false;7877}7878 7879// Section 19.4, paragraph 5 says that each ac-do-variable has the scope of the7880// enclosing ac-implied-do7881bool ConstructVisitor::Pre(const parser::AcImpliedDo &x) {7882  auto &values{std::get<std::list<parser::AcValue>>(x.t)};7883  auto &control{std::get<parser::AcImpliedDoControl>(x.t)};7884  auto &type{std::get<std::optional<parser::IntegerTypeSpec>>(control.t)};7885  auto &bounds{std::get<parser::AcImpliedDoControl::Bounds>(control.t)};7886  // F'2018 has the scope of the implied DO variable covering the entire7887  // implied DO production (19.4(5)), which seems wrong in cases where the name7888  // of the implied DO variable appears in one of the bound expressions. Thus7889  // this extension, which shrinks the scope of the variable to exclude the7890  // expressions in the bounds.7891  auto restore{BeginCheckOnIndexUseInOwnBounds(bounds.name)};7892  Walk(bounds.lower);7893  Walk(bounds.upper);7894  Walk(bounds.step);7895  EndCheckOnIndexUseInOwnBounds(restore);7896  PushScope(Scope::Kind::ImpliedDos, nullptr);7897  DeclareStatementEntity(bounds.name, type);7898  Walk(values);7899  PopScope();7900  return false;7901}7902 7903bool ConstructVisitor::Pre(const parser::DataImpliedDo &x) {7904  auto &objects{std::get<std::list<parser::DataIDoObject>>(x.t)};7905  auto &type{std::get<std::optional<parser::IntegerTypeSpec>>(x.t)};7906  auto &bounds{std::get<parser::DataImpliedDo::Bounds>(x.t)};7907  // See comment in Pre(AcImpliedDo) above.7908  auto restore{BeginCheckOnIndexUseInOwnBounds(bounds.name)};7909  Walk(bounds.lower);7910  Walk(bounds.upper);7911  Walk(bounds.step);7912  EndCheckOnIndexUseInOwnBounds(restore);7913  PushScope(Scope::Kind::ImpliedDos, nullptr);7914  DeclareStatementEntity(bounds.name, type);7915  Walk(objects);7916  PopScope();7917  return false;7918}7919 7920// Sets InDataStmt flag on a variable (or misidentified function) in a DATA7921// statement so that the predicate IsInitialized() will be true7922// during semantic analysis before the symbol's initializer is constructed.7923bool ConstructVisitor::Pre(const parser::DataIDoObject &x) {7924  common::visit(7925      common::visitors{7926          [&](const parser::Scalar<Indirection<parser::Designator>> &y) {7927            const auto &designator{parser::UnwrapRef<parser::Designator>(y)};7928            Walk(designator);7929            const parser::Name &first{parser::GetFirstName(designator)};7930            if (first.symbol) {7931              first.symbol->set(Symbol::Flag::InDataStmt);7932            }7933          },7934          [&](const Indirection<parser::DataImpliedDo> &y) { Walk(y); },7935      },7936      x.u);7937  return false;7938}7939 7940bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {7941  // Subtle: DATA statements may appear in both the specification and7942  // execution parts, but should be treated as if in the execution part7943  // for purposes of implicit variable declaration vs. host association.7944  // When a name first appears as an object in a DATA statement, it should7945  // be implicitly declared locally as if it had been assigned.7946  auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)};7947  common::visit(7948      common::visitors{7949          [&](const Indirection<parser::Variable> &y) {7950            auto restorer{common::ScopedSet(deferImplicitTyping_, true)};7951            Walk(y.value());7952            const parser::Name &first{parser::GetFirstName(y.value())};7953            if (first.symbol) {7954              first.symbol->set(Symbol::Flag::InDataStmt);7955            }7956          },7957          [&](const parser::DataImpliedDo &y) {7958            // Don't push scope here, since it's done when visiting7959            // DataImpliedDo.7960            Walk(y);7961          },7962      },7963      x.u);7964  return false;7965}7966 7967bool ConstructVisitor::Pre(const parser::DataStmtValue &x) {7968  const auto &data{std::get<parser::DataStmtConstant>(x.t)};7969  auto &mutableData{const_cast<parser::DataStmtConstant &>(data)};7970  if (auto *elem{parser::Unwrap<parser::ArrayElement>(mutableData)}) {7971    if (const auto *name{std::get_if<parser::Name>(&elem->base.u)}) {7972      if (const Symbol * symbol{FindSymbol(*name)};7973          symbol && symbol->GetUltimate().has<DerivedTypeDetails>()) {7974        mutableData.u = elem->ConvertToStructureConstructor(7975            DerivedTypeSpec{name->source, *symbol});7976      }7977    }7978  }7979  return true;7980}7981 7982bool ConstructVisitor::Pre(const parser::DoConstruct &x) {7983  if (x.IsDoConcurrent()) {7984    // The new scope has Kind::Forall for index variable name conflict7985    // detection with nested FORALL/DO CONCURRENT constructs in7986    // ResolveIndexName().7987    PushScope(Scope::Kind::Forall, nullptr);7988  }7989  return true;7990}7991void ConstructVisitor::Post(const parser::DoConstruct &x) {7992  if (x.IsDoConcurrent()) {7993    PopScope();7994  }7995}7996 7997bool ConstructVisitor::Pre(const parser::ForallConstruct &) {7998  PushScope(Scope::Kind::Forall, nullptr);7999  return true;8000}8001void ConstructVisitor::Post(const parser::ForallConstruct &) { PopScope(); }8002bool ConstructVisitor::Pre(const parser::ForallStmt &) {8003  PushScope(Scope::Kind::Forall, nullptr);8004  return true;8005}8006void ConstructVisitor::Post(const parser::ForallStmt &) { PopScope(); }8007 8008bool ConstructVisitor::Pre(const parser::BlockConstruct &x) {8009  const auto &[blockStmt, specPart, execPart, endBlockStmt] = x.t;8010  Walk(blockStmt);8011  CheckDef(blockStmt.statement.v);8012  PushScope(Scope::Kind::BlockConstruct, nullptr);8013  Walk(specPart);8014  HandleImpliedAsynchronousInScope(execPart);8015  Walk(execPart);8016  Walk(endBlockStmt);8017  PopScope();8018  CheckRef(endBlockStmt.statement.v);8019  return false;8020}8021 8022void ConstructVisitor::Post(const parser::Selector &x) {8023  GetCurrentAssociation().selector = ResolveSelector(x);8024}8025 8026void ConstructVisitor::Post(const parser::AssociateStmt &x) {8027  CheckDef(x.t);8028  PushScope(Scope::Kind::OtherConstruct, nullptr);8029  const auto assocCount{std::get<std::list<parser::Association>>(x.t).size()};8030  for (auto nthLastAssoc{assocCount}; nthLastAssoc > 0; --nthLastAssoc) {8031    SetCurrentAssociation(nthLastAssoc);8032    if (auto *symbol{MakeAssocEntity()}) {8033      const MaybeExpr &expr{GetCurrentAssociation().selector.expr};8034      if (ExtractCoarrayRef(expr)) { // C11038035        Say("Selector must not be a coindexed object"_err_en_US);8036      }8037      if (IsAssumedRank(expr)) {8038        Say("Selector must not be assumed-rank"_err_en_US);8039      }8040      SetTypeFromAssociation(*symbol);8041      SetAttrsFromAssociation(*symbol);8042    }8043  }8044  PopAssociation(assocCount);8045}8046 8047void ConstructVisitor::Post(const parser::EndAssociateStmt &x) {8048  PopScope();8049  CheckRef(x.v);8050}8051 8052bool ConstructVisitor::Pre(const parser::Association &x) {8053  PushAssociation();8054  const auto &name{std::get<parser::Name>(x.t)};8055  GetCurrentAssociation().name = &name;8056  return true;8057}8058 8059bool ConstructVisitor::Pre(const parser::ChangeTeamStmt &x) {8060  CheckDef(x.t);8061  PushScope(Scope::Kind::OtherConstruct, nullptr);8062  PushAssociation();8063  return true;8064}8065 8066void ConstructVisitor::Post(const parser::CoarrayAssociation &x) {8067  const auto &decl{std::get<parser::CodimensionDecl>(x.t)};8068  const auto &name{std::get<parser::Name>(decl.t)};8069  if (auto *symbol{FindInScope(name)}) {8070    const auto &selector{std::get<parser::Selector>(x.t)};8071    if (auto sel{ResolveSelector(selector)}) {8072      const Symbol *whole{UnwrapWholeSymbolDataRef(sel.expr)};8073      if (!whole || whole->Corank() == 0) {8074        Say(sel.source, // C11168075            "Selector in coarray association must name a coarray"_err_en_US);8076      } else if (auto dynType{sel.expr->GetType()}) {8077        if (!symbol->GetType()) {8078          symbol->SetType(ToDeclTypeSpec(std::move(*dynType)));8079        }8080      }8081    }8082  }8083}8084 8085void ConstructVisitor::Post(const parser::EndChangeTeamStmt &x) {8086  PopAssociation();8087  PopScope();8088  CheckRef(x.t);8089}8090 8091bool ConstructVisitor::Pre(const parser::SelectTypeConstruct &) {8092  PushAssociation();8093  return true;8094}8095 8096void ConstructVisitor::Post(const parser::SelectTypeConstruct &) {8097  PopAssociation();8098}8099 8100void ConstructVisitor::Post(const parser::SelectTypeStmt &x) {8101  auto &association{GetCurrentAssociation()};8102  if (const std::optional<parser::Name> &name{std::get<1>(x.t)}) {8103    // This isn't a name in the current scope, it is in each TypeGuardStmt8104    MakePlaceholder(*name, MiscDetails::Kind::SelectTypeAssociateName);8105    association.name = &*name;8106    if (ExtractCoarrayRef(association.selector.expr)) { // C11038107      Say("Selector must not be a coindexed object"_err_en_US);8108    }8109    if (association.selector.expr) {8110      auto exprType{association.selector.expr->GetType()};8111      if (exprType && !exprType->IsPolymorphic()) { // C11598112        Say(association.selector.source,8113            "Selector '%s' in SELECT TYPE statement must be "8114            "polymorphic"_err_en_US);8115      }8116    }8117  } else {8118    if (const Symbol *8119        whole{UnwrapWholeSymbolDataRef(association.selector.expr)}) {8120      ConvertToObjectEntity(const_cast<Symbol &>(*whole));8121      if (!IsVariableName(*whole)) {8122        Say(association.selector.source, // C9018123            "Selector is not a variable"_err_en_US);8124        association = {};8125      }8126      if (const DeclTypeSpec * type{whole->GetType()}) {8127        if (!type->IsPolymorphic()) { // C11598128          Say(association.selector.source,8129              "Selector '%s' in SELECT TYPE statement must be "8130              "polymorphic"_err_en_US);8131        }8132      }8133    } else {8134      Say(association.selector.source, // C11578135          "Selector is not a named variable: 'associate-name =>' is required"_err_en_US);8136      association = {};8137    }8138  }8139}8140 8141void ConstructVisitor::Post(const parser::SelectRankStmt &x) {8142  auto &association{GetCurrentAssociation()};8143  if (const std::optional<parser::Name> &name{std::get<1>(x.t)}) {8144    // This isn't a name in the current scope, it is in each SelectRankCaseStmt8145    MakePlaceholder(*name, MiscDetails::Kind::SelectRankAssociateName);8146    association.name = &*name;8147  }8148}8149 8150bool ConstructVisitor::Pre(const parser::SelectTypeConstruct::TypeCase &) {8151  PushScope(Scope::Kind::OtherConstruct, nullptr);8152  return true;8153}8154void ConstructVisitor::Post(const parser::SelectTypeConstruct::TypeCase &) {8155  PopScope();8156}8157 8158bool ConstructVisitor::Pre(const parser::SelectRankConstruct::RankCase &) {8159  PushScope(Scope::Kind::OtherConstruct, nullptr);8160  return true;8161}8162void ConstructVisitor::Post(const parser::SelectRankConstruct::RankCase &) {8163  PopScope();8164}8165 8166bool ConstructVisitor::Pre(const parser::TypeGuardStmt::Guard &x) {8167  if (std::holds_alternative<parser::DerivedTypeSpec>(x.u)) {8168    // CLASS IS (t)8169    SetDeclTypeSpecCategory(DeclTypeSpec::Category::ClassDerived);8170  }8171  return true;8172}8173 8174void ConstructVisitor::Post(const parser::TypeGuardStmt::Guard &x) {8175  if (auto *symbol{MakeAssocEntity()}) {8176    if (std::holds_alternative<parser::Default>(x.u)) {8177      SetTypeFromAssociation(*symbol);8178    } else if (const auto *type{GetDeclTypeSpec()}) {8179      symbol->SetType(*type);8180      symbol->get<AssocEntityDetails>().set_isTypeGuard();8181    }8182    SetAttrsFromAssociation(*symbol);8183  }8184}8185 8186void ConstructVisitor::Post(const parser::SelectRankCaseStmt::Rank &x) {8187  if (auto *symbol{MakeAssocEntity()}) {8188    SetTypeFromAssociation(*symbol);8189    auto &details{symbol->get<AssocEntityDetails>()};8190    // Don't call SetAttrsFromAssociation() for SELECT RANK.8191    Attrs selectorAttrs{8192        evaluate::GetAttrs(GetCurrentAssociation().selector.expr)};8193    Attrs attrsToKeep{Attr::ASYNCHRONOUS, Attr::TARGET, Attr::VOLATILE};8194    if (const auto *rankValue{8195            std::get_if<parser::ScalarIntConstantExpr>(&x.u)}) {8196      // RANK(n)8197      if (auto expr{EvaluateIntExpr(*rankValue)}) {8198        if (auto val{evaluate::ToInt64(*expr)}) {8199          details.set_rank(*val);8200          attrsToKeep |= Attrs{Attr::ALLOCATABLE, Attr::POINTER};8201        } else {8202          Say("RANK() expression must be constant"_err_en_US);8203        }8204      }8205    } else if (std::holds_alternative<parser::Star>(x.u)) {8206      // RANK(*): assumed-size8207      details.set_IsAssumedSize();8208    } else {8209      CHECK(std::holds_alternative<parser::Default>(x.u));8210      // RANK DEFAULT: assumed-rank8211      details.set_IsAssumedRank();8212      attrsToKeep |= Attrs{Attr::ALLOCATABLE, Attr::POINTER};8213    }8214    symbol->attrs() |= selectorAttrs & attrsToKeep;8215  }8216}8217 8218bool ConstructVisitor::Pre(const parser::SelectRankConstruct &) {8219  PushAssociation();8220  return true;8221}8222 8223void ConstructVisitor::Post(const parser::SelectRankConstruct &) {8224  PopAssociation();8225}8226 8227bool ConstructVisitor::CheckDef(const std::optional<parser::Name> &x) {8228  if (x && !x->symbol) {8229    // Construct names are not scoped by BLOCK in the standard, but many,8230    // but not all, compilers do treat them as if they were so scoped.8231    if (Symbol * inner{FindInScope(currScope(), *x)}) {8232      SayAlreadyDeclared(*x, *inner);8233    } else {8234      if (context().ShouldWarn(common::LanguageFeature::BenignNameClash)) {8235        if (Symbol *8236            other{FindInScopeOrBlockConstructs(InclusiveScope(), x->source)}) {8237          SayWithDecl(*x, *other,8238              "The construct name '%s' should be distinct at the subprogram level"_port_en_US)8239              .set_languageFeature(common::LanguageFeature::BenignNameClash);8240        }8241      }8242      MakeSymbol(*x, MiscDetails{MiscDetails::Kind::ConstructName});8243    }8244  }8245  return true;8246}8247 8248void ConstructVisitor::CheckRef(const std::optional<parser::Name> &x) {8249  if (x) {8250    // Just add an occurrence of this name; checking is done in ValidateLabels8251    FindSymbol(*x);8252  }8253}8254 8255// Make a symbol for the associating entity of the current association.8256Symbol *ConstructVisitor::MakeAssocEntity() {8257  Symbol *symbol{nullptr};8258  auto &association{GetCurrentAssociation()};8259  if (association.name) {8260    symbol = &MakeSymbol(*association.name, UnknownDetails{});8261    if (symbol->has<AssocEntityDetails>() && symbol->owner() == currScope()) {8262      Say(*association.name, // C11028263          "The associate name '%s' is already used in this associate statement"_err_en_US);8264      return nullptr;8265    }8266  } else if (const Symbol *8267      whole{UnwrapWholeSymbolDataRef(association.selector.expr)}) {8268    symbol = &MakeSymbol(whole->name());8269  } else {8270    return nullptr;8271  }8272  if (auto &expr{association.selector.expr}) {8273    symbol->set_details(AssocEntityDetails{common::Clone(*expr)});8274  } else {8275    symbol->set_details(AssocEntityDetails{});8276  }8277  return symbol;8278}8279 8280// Set the type of symbol based on the current association selector.8281void ConstructVisitor::SetTypeFromAssociation(Symbol &symbol) {8282  auto &details{symbol.get<AssocEntityDetails>()};8283  const MaybeExpr *pexpr{&details.expr()};8284  if (!*pexpr) {8285    pexpr = &GetCurrentAssociation().selector.expr;8286  }8287  if (*pexpr) {8288    const SomeExpr &expr{**pexpr};8289    if (std::optional<evaluate::DynamicType> type{expr.GetType()}) {8290      if (const auto *charExpr{8291              evaluate::UnwrapExpr<evaluate::Expr<evaluate::SomeCharacter>>(8292                  expr)}) {8293        symbol.SetType(ToDeclTypeSpec(std::move(*type),8294            FoldExpr(common::visit(8295                [](const auto &kindChar) { return kindChar.LEN(); },8296                charExpr->u))));8297      } else {8298        symbol.SetType(ToDeclTypeSpec(std::move(*type)));8299      }8300    } else {8301      // BOZ literals, procedure designators, &c. are not acceptable8302      Say(symbol.name(), "Associate name '%s' must have a type"_err_en_US);8303    }8304  }8305}8306 8307// If current selector is a variable, set some of its attributes on symbol.8308// For ASSOCIATE, CHANGE TEAM, and SELECT TYPE only; not SELECT RANK.8309void ConstructVisitor::SetAttrsFromAssociation(Symbol &symbol) {8310  Attrs attrs{evaluate::GetAttrs(GetCurrentAssociation().selector.expr)};8311  symbol.attrs() |=8312      attrs & Attrs{Attr::TARGET, Attr::ASYNCHRONOUS, Attr::VOLATILE};8313  if (attrs.test(Attr::POINTER)) {8314    SetImplicitAttr(symbol, Attr::TARGET);8315  }8316}8317 8318ConstructVisitor::Selector ConstructVisitor::ResolveSelector(8319    const parser::Selector &x) {8320  return common::visit(common::visitors{8321                           [&](const parser::Expr &expr) {8322                             return Selector{expr.source, EvaluateExpr(x)};8323                           },8324                           [&](const parser::Variable &var) {8325                             return Selector{var.GetSource(), EvaluateExpr(x)};8326                           },8327                       },8328      x.u);8329}8330 8331// Set the current association to the nth to the last association on the8332// association stack.  The top of the stack is at n = 1.  This allows access8333// to the interior of a list of associations at the top of the stack.8334void ConstructVisitor::SetCurrentAssociation(std::size_t n) {8335  CHECK(n > 0 && n <= associationStack_.size());8336  currentAssociation_ = &associationStack_[associationStack_.size() - n];8337}8338 8339ConstructVisitor::Association &ConstructVisitor::GetCurrentAssociation() {8340  CHECK(currentAssociation_);8341  return *currentAssociation_;8342}8343 8344void ConstructVisitor::PushAssociation() {8345  associationStack_.emplace_back(Association{});8346  currentAssociation_ = &associationStack_.back();8347}8348 8349void ConstructVisitor::PopAssociation(std::size_t count) {8350  CHECK(count > 0 && count <= associationStack_.size());8351  associationStack_.resize(associationStack_.size() - count);8352  currentAssociation_ =8353      associationStack_.empty() ? nullptr : &associationStack_.back();8354}8355 8356const DeclTypeSpec &ConstructVisitor::ToDeclTypeSpec(8357    evaluate::DynamicType &&type) {8358  switch (type.category()) {8359    SWITCH_COVERS_ALL_CASES8360  case common::TypeCategory::Integer:8361  case common::TypeCategory::Unsigned:8362  case common::TypeCategory::Real:8363  case common::TypeCategory::Complex:8364    return context().MakeNumericType(type.category(), type.kind());8365  case common::TypeCategory::Logical:8366    return context().MakeLogicalType(type.kind());8367  case common::TypeCategory::Derived:8368    if (type.IsAssumedType()) {8369      return currScope().MakeTypeStarType();8370    } else if (type.IsUnlimitedPolymorphic()) {8371      return currScope().MakeClassStarType();8372    } else {8373      return currScope().MakeDerivedType(8374          type.IsPolymorphic() ? DeclTypeSpec::ClassDerived8375                               : DeclTypeSpec::TypeDerived,8376          common::Clone(type.GetDerivedTypeSpec())8377 8378      );8379    }8380  case common::TypeCategory::Character:8381    CRASH_NO_CASE;8382  }8383}8384 8385const DeclTypeSpec &ConstructVisitor::ToDeclTypeSpec(8386    evaluate::DynamicType &&type, MaybeSubscriptIntExpr &&length) {8387  CHECK(type.category() == common::TypeCategory::Character);8388  if (length) {8389    return currScope().MakeCharacterType(8390        ParamValue{SomeIntExpr{*std::move(length)}, common::TypeParamAttr::Len},8391        KindExpr{type.kind()});8392  } else {8393    return currScope().MakeCharacterType(8394        ParamValue::Deferred(common::TypeParamAttr::Len),8395        KindExpr{type.kind()});8396  }8397}8398 8399class ExecutionPartSkimmerBase {8400public:8401  template <typename A> bool Pre(const A &) { return true; }8402  template <typename A> void Post(const A &) {}8403 8404  bool InNestedBlockConstruct() const { return blockDepth_ > 0; }8405 8406  bool Pre(const parser::AssociateConstruct &) {8407    PushScope();8408    return true;8409  }8410  void Post(const parser::AssociateConstruct &) { PopScope(); }8411  bool Pre(const parser::Association &x) {8412    Hide(std::get<parser::Name>(x.t));8413    return true;8414  }8415  bool Pre(const parser::BlockConstruct &) {8416    PushScope();8417    ++blockDepth_;8418    return true;8419  }8420  void Post(const parser::BlockConstruct &) {8421    --blockDepth_;8422    PopScope();8423  }8424  // Note declarations of local names in BLOCK constructs.8425  // Don't have to worry about INTENT(), VALUE, or OPTIONAL8426  // (pertinent only to dummy arguments), ASYNCHRONOUS/VOLATILE,8427  // or accessibility attributes,8428  bool Pre(const parser::EntityDecl &x) {8429    Hide(std::get<parser::ObjectName>(x.t));8430    return true;8431  }8432  bool Pre(const parser::ObjectDecl &x) {8433    Hide(std::get<parser::ObjectName>(x.t));8434    return true;8435  }8436  bool Pre(const parser::PointerDecl &x) {8437    Hide(std::get<parser::Name>(x.t));8438    return true;8439  }8440  bool Pre(const parser::BindEntity &x) {8441    Hide(std::get<parser::Name>(x.t));8442    return true;8443  }8444  bool Pre(const parser::ContiguousStmt &x) {8445    for (const parser::Name &name : x.v) {8446      Hide(name);8447    }8448    return true;8449  }8450  bool Pre(const parser::DimensionStmt::Declaration &x) {8451    Hide(std::get<parser::Name>(x.t));8452    return true;8453  }8454  bool Pre(const parser::ExternalStmt &x) {8455    for (const parser::Name &name : x.v) {8456      Hide(name);8457    }8458    return true;8459  }8460  bool Pre(const parser::IntrinsicStmt &x) {8461    for (const parser::Name &name : x.v) {8462      Hide(name);8463    }8464    return true;8465  }8466  bool Pre(const parser::CodimensionStmt &x) {8467    for (const parser::CodimensionDecl &decl : x.v) {8468      Hide(std::get<parser::Name>(decl.t));8469    }8470    return true;8471  }8472  void Post(const parser::ImportStmt &x) {8473    if (x.kind == common::ImportKind::None ||8474        x.kind == common::ImportKind::Only) {8475      if (!nestedScopes_.front().importOnly.has_value()) {8476        nestedScopes_.front().importOnly.emplace();8477      }8478      for (const auto &name : x.names) {8479        nestedScopes_.front().importOnly->emplace(name.source);8480      }8481    } else {8482      // no special handling needed for explicit names or IMPORT, ALL8483    }8484  }8485  void Post(const parser::UseStmt &x) {8486    if (const auto *onlyList{std::get_if<std::list<parser::Only>>(&x.u)}) {8487      for (const auto &only : *onlyList) {8488        if (const auto *name{std::get_if<parser::Name>(&only.u)}) {8489          Hide(*name);8490        } else if (const auto *rename{std::get_if<parser::Rename>(&only.u)}) {8491          if (const auto *names{8492                  std::get_if<parser::Rename::Names>(&rename->u)}) {8493            Hide(std::get<0>(names->t));8494          }8495        }8496      }8497    } else {8498      // USE may or may not shadow symbols in host scopes8499      nestedScopes_.front().hasUseWithoutOnly = true;8500    }8501  }8502  bool Pre(const parser::DerivedTypeStmt &x) {8503    Hide(std::get<parser::Name>(x.t));8504    PushScope();8505    return true;8506  }8507  void Post(const parser::DerivedTypeDef &) { PopScope(); }8508  bool Pre(const parser::SelectTypeConstruct &) {8509    PushScope();8510    return true;8511  }8512  void Post(const parser::SelectTypeConstruct &) { PopScope(); }8513  bool Pre(const parser::SelectTypeStmt &x) {8514    if (const auto &maybeName{std::get<1>(x.t)}) {8515      Hide(*maybeName);8516    }8517    return true;8518  }8519  bool Pre(const parser::SelectRankConstruct &) {8520    PushScope();8521    return true;8522  }8523  void Post(const parser::SelectRankConstruct &) { PopScope(); }8524  bool Pre(const parser::SelectRankStmt &x) {8525    if (const auto &maybeName{std::get<1>(x.t)}) {8526      Hide(*maybeName);8527    }8528    return true;8529  }8530 8531  // Iterator-modifiers contain variable declarations, and do introduce8532  // a new scope. These variables can only have integer types, and their8533  // scope only extends until the end of the clause. A potential alternative8534  // to the code below may be to ignore OpenMP clauses, but it's not clear8535  // if OMP-specific checks can be avoided altogether.8536  bool Pre(const parser::OmpClause &x) {8537    if (OmpVisitor::NeedsScope(x)) {8538      PushScope();8539    }8540    return true;8541  }8542  void Post(const parser::OmpClause &x) {8543    if (OmpVisitor::NeedsScope(x)) {8544      PopScope();8545    }8546  }8547 8548protected:8549  bool IsHidden(SourceName name) {8550    for (const auto &scope : nestedScopes_) {8551      if (scope.locals.find(name) != scope.locals.end()) {8552        return true; // shadowed by nested declaration8553      }8554      if (scope.hasUseWithoutOnly) {8555        break;8556      }8557      if (scope.importOnly &&8558          scope.importOnly->find(name) == scope.importOnly->end()) {8559        return true; // not imported8560      }8561    }8562    return false;8563  }8564 8565  void EndWalk() { CHECK(nestedScopes_.empty()); }8566 8567private:8568  void PushScope() { nestedScopes_.emplace_front(); }8569  void PopScope() { nestedScopes_.pop_front(); }8570  void Hide(const parser::Name &name) {8571    nestedScopes_.front().locals.emplace(name.source);8572  }8573 8574  int blockDepth_{0};8575  struct NestedScopeInfo {8576    bool hasUseWithoutOnly{false};8577    std::set<SourceName> locals;8578    std::optional<std::set<SourceName>> importOnly;8579  };8580  std::list<NestedScopeInfo> nestedScopes_;8581};8582 8583class ExecutionPartAsyncIOSkimmer : public ExecutionPartSkimmerBase {8584public:8585  explicit ExecutionPartAsyncIOSkimmer(SemanticsContext &context)8586      : context_{context} {}8587 8588  void Walk(const parser::Block &block) {8589    parser::Walk(block, *this);8590    EndWalk();8591  }8592 8593  const std::set<SourceName> asyncIONames() const { return asyncIONames_; }8594 8595  using ExecutionPartSkimmerBase::Post;8596  using ExecutionPartSkimmerBase::Pre;8597 8598  bool Pre(const parser::IoControlSpec::Asynchronous &async) {8599    if (auto folded{evaluate::Fold(8600            context_.foldingContext(), AnalyzeExpr(context_, async.v))}) {8601      if (auto str{8602              evaluate::GetScalarConstantValue<evaluate::Ascii>(*folded)}) {8603        for (char ch : *str) {8604          if (ch != ' ') {8605            inAsyncIO_ = ch == 'y' || ch == 'Y';8606            break;8607          }8608        }8609      }8610    }8611    return true;8612  }8613  void Post(const parser::ReadStmt &) { inAsyncIO_ = false; }8614  void Post(const parser::WriteStmt &) { inAsyncIO_ = false; }8615  void Post(const parser::IoControlSpec::Size &size) {8616    if (const auto *designator{8617            parser::Unwrap<common::Indirection<parser::Designator>>(size)}) {8618      NoteAsyncIODesignator(designator->value());8619    }8620  }8621  void Post(const parser::InputItem &x) {8622    if (const auto *var{std::get_if<parser::Variable>(&x.u)}) {8623      if (const auto *designator{8624              std::get_if<common::Indirection<parser::Designator>>(&var->u)}) {8625        NoteAsyncIODesignator(designator->value());8626      }8627    }8628  }8629  void Post(const parser::OutputItem &x) {8630    if (const auto *expr{std::get_if<parser::Expr>(&x.u)}) {8631      if (const auto *designator{8632              std::get_if<common::Indirection<parser::Designator>>(&expr->u)}) {8633        NoteAsyncIODesignator(designator->value());8634      }8635    }8636  }8637 8638private:8639  void NoteAsyncIODesignator(const parser::Designator &designator) {8640    if (inAsyncIO_ && !InNestedBlockConstruct()) {8641      const parser::Name &name{parser::GetFirstName(designator)};8642      if (!IsHidden(name.source)) {8643        asyncIONames_.insert(name.source);8644      }8645    }8646  }8647 8648  SemanticsContext &context_;8649  bool inAsyncIO_{false};8650  std::set<SourceName> asyncIONames_;8651};8652 8653// Any data list item or SIZE= specifier of an I/O data transfer statement8654// with ASYNCHRONOUS="YES" implicitly has the ASYNCHRONOUS attribute in the8655// local scope.8656void ConstructVisitor::HandleImpliedAsynchronousInScope(8657    const parser::Block &block) {8658  ExecutionPartAsyncIOSkimmer skimmer{context()};8659  skimmer.Walk(block);8660  for (auto name : skimmer.asyncIONames()) {8661    if (Symbol * symbol{currScope().FindSymbol(name)}) {8662      if (!symbol->attrs().test(Attr::ASYNCHRONOUS)) {8663        if (&symbol->owner() != &currScope()) {8664          symbol = &*currScope()8665                         .try_emplace(name, HostAssocDetails{*symbol})8666                         .first->second;8667        }8668        if (symbol->has<AssocEntityDetails>()) {8669          symbol = const_cast<Symbol *>(&GetAssociationRoot(*symbol));8670        }8671        SetImplicitAttr(*symbol, Attr::ASYNCHRONOUS);8672      }8673    }8674  }8675}8676 8677// ResolveNamesVisitor implementation8678 8679bool ResolveNamesVisitor::Pre(const parser::FunctionReference &x) {8680  HandleCall(Symbol::Flag::Function, x.v);8681  return false;8682}8683bool ResolveNamesVisitor::Pre(const parser::CallStmt &x) {8684  HandleCall(Symbol::Flag::Subroutine, x.call);8685  Walk(x.chevrons);8686  return false;8687}8688 8689bool ResolveNamesVisitor::Pre(const parser::ImportStmt &x) {8690  auto &scope{currScope()};8691  // Check C896 and C899: where IMPORT statements are allowed8692  switch (scope.kind()) {8693  case Scope::Kind::Module:8694    if (scope.IsModule()) {8695      Say("IMPORT is not allowed in a module scoping unit"_err_en_US);8696      return false;8697    } else if (x.kind == common::ImportKind::None) {8698      Say("IMPORT,NONE is not allowed in a submodule scoping unit"_err_en_US);8699      return false;8700    }8701    break;8702  case Scope::Kind::MainProgram:8703    Say("IMPORT is not allowed in a main program scoping unit"_err_en_US);8704    return false;8705  case Scope::Kind::Subprogram:8706    if (scope.parent().IsGlobal()) {8707      Say("IMPORT is not allowed in an external subprogram scoping unit"_err_en_US);8708      return false;8709    }8710    break;8711  case Scope::Kind::BlockData: // C1415 (in part)8712    Say("IMPORT is not allowed in a BLOCK DATA subprogram"_err_en_US);8713    return false;8714  default:;8715  }8716  if (auto error{scope.SetImportKind(x.kind)}) {8717    Say(std::move(*error));8718  }8719  for (auto &name : x.names) {8720    if (Symbol * outer{FindSymbol(scope.parent(), name)}) {8721      scope.add_importName(name.source);8722      if (Symbol * symbol{FindInScope(name)}) {8723        if (outer->GetUltimate() == symbol->GetUltimate()) {8724          context().Warn(common::LanguageFeature::BenignNameClash, name.source,8725              "The same '%s' is already present in this scope"_port_en_US,8726              name.source);8727        } else {8728          Say(name,8729              "A distinct '%s' is already present in this scope"_err_en_US)8730              .Attach(symbol->name(), "Previous declaration of '%s'"_en_US,8731                  symbol->name().ToString())8732              .Attach(outer->name(), "Declaration of '%s' in host scope"_en_US,8733                  outer->name().ToString());8734        }8735      }8736    } else {8737      Say(name, "'%s' not found in host scope"_err_en_US);8738    }8739  }8740  prevImportStmt_ = currStmtSource();8741  return false;8742}8743 8744const parser::Name *DeclarationVisitor::ResolveStructureComponent(8745    const parser::StructureComponent &x) {8746  return FindComponent(ResolveDataRef(x.base), x.component);8747}8748 8749const parser::Name *DeclarationVisitor::ResolveDesignator(8750    const parser::Designator &x) {8751  return common::visit(8752      common::visitors{8753          [&](const parser::DataRef &x) { return ResolveDataRef(x); },8754          [&](const parser::Substring &x) {8755            Walk(std::get<parser::SubstringRange>(x.t).t);8756            return ResolveDataRef(std::get<parser::DataRef>(x.t));8757          },8758      },8759      x.u);8760}8761 8762const parser::Name *DeclarationVisitor::ResolveDataRef(8763    const parser::DataRef &x) {8764  return common::visit(8765      common::visitors{8766          [=](const parser::Name &y) { return ResolveName(y); },8767          [=](const Indirection<parser::StructureComponent> &y) {8768            return ResolveStructureComponent(y.value());8769          },8770          [&](const Indirection<parser::ArrayElement> &y) {8771            Walk(y.value().subscripts);8772            const parser::Name *name{ResolveDataRef(y.value().base)};8773            if (name && name->symbol) {8774              if (!IsProcedure(*name->symbol)) {8775                ConvertToObjectEntity(*name->symbol);8776              } else if (!context().HasError(*name->symbol)) {8777                SayWithDecl(*name, *name->symbol,8778                    "Cannot reference function '%s' as data"_err_en_US);8779                context().SetError(*name->symbol);8780              }8781            }8782            return name;8783          },8784          [&](const Indirection<parser::CoindexedNamedObject> &y) {8785            Walk(y.value().imageSelector);8786            return ResolveDataRef(y.value().base);8787          },8788      },8789      x.u);8790}8791 8792// If implicit types are allowed, ensure name is in the symbol table.8793// Otherwise, report an error if it hasn't been declared.8794const parser::Name *DeclarationVisitor::ResolveName(const parser::Name &name) {8795  if (!FindSymbol(name)) {8796    if (FindAndMarkDeclareTargetSymbol(name)) {8797      return &name;8798    }8799  }8800  if (CheckForHostAssociatedImplicit(name)) {8801    NotePossibleBadForwardRef(name);8802    return &name;8803  }8804  if (Symbol * symbol{name.symbol}) {8805    if (CheckUseError(name)) {8806      return nullptr; // reported an error8807    }8808    NotePossibleBadForwardRef(name);8809    symbol->set(Symbol::Flag::ImplicitOrError, false);8810    if (IsUplevelReference(*symbol)) {8811      MakeHostAssocSymbol(name, *symbol);8812    } else if (IsDummy(*symbol)) {8813      CheckEntryDummyUse(name.source, symbol);8814      ConvertToObjectEntity(*symbol);8815      if (IsEarlyDeclaredDummyArgument(*symbol)) {8816        ForgetEarlyDeclaredDummyArgument(*symbol);8817        if (isImplicitNoneType()) {8818          context().Warn(common::LanguageFeature::ForwardRefImplicitNone,8819              name.source,8820              "'%s' was used under IMPLICIT NONE(TYPE) before being explicitly typed"_warn_en_US,8821              name.source);8822        } else if (TypesMismatchIfNonNull(8823                       symbol->GetType(), GetImplicitType(*symbol))) {8824          context().Warn(common::LanguageFeature::ForwardRefExplicitTypeDummy,8825              name.source,8826              "'%s' was used before being explicitly typed (and its implicit type would differ)"_warn_en_US,8827              name.source);8828        }8829      }8830      ApplyImplicitRules(*symbol);8831    } else if (!symbol->GetType() && FindCommonBlockContaining(*symbol)) {8832      ConvertToObjectEntity(*symbol);8833      ApplyImplicitRules(*symbol);8834    } else if (const auto *tpd{symbol->detailsIf<TypeParamDetails>()};8835        tpd && !tpd->attr()) {8836      Say(name,8837          "Type parameter '%s' was referenced before being declared"_err_en_US,8838          name.source);8839      context().SetError(*symbol);8840    }8841    if (checkIndexUseInOwnBounds_ &&8842        *checkIndexUseInOwnBounds_ == name.source && !InModuleFile()) {8843      context().Warn(common::LanguageFeature::ImpliedDoIndexScope, name.source,8844          "Implied DO index '%s' uses an object of the same name in its bounds expressions"_port_en_US,8845          name.source);8846    }8847    return &name;8848  }8849  if (isImplicitNoneType() && !deferImplicitTyping_) {8850    Say(name, "No explicit type declared for '%s'"_err_en_US);8851    return nullptr;8852  }8853  // Create the symbol, then ensure that it is accessible8854  if (checkIndexUseInOwnBounds_ && *checkIndexUseInOwnBounds_ == name.source) {8855    Say(name,8856        "Implied DO index '%s' uses itself in its own bounds expressions"_err_en_US,8857        name.source);8858  }8859  MakeSymbol(InclusiveScope(), name.source, Attrs{});8860  auto *symbol{FindSymbol(name)};8861  if (!symbol) {8862    Say(name,8863        "'%s' from host scoping unit is not accessible due to IMPORT"_err_en_US);8864    return nullptr;8865  }8866  ConvertToObjectEntity(*symbol);8867  ApplyImplicitRules(*symbol);8868  NotePossibleBadForwardRef(name);8869  return &name;8870}8871 8872// A specification expression may refer to a symbol in the host procedure that8873// is implicitly typed. Because specification parts are processed before8874// execution parts, this may be the first time we see the symbol. It can't be a8875// local in the current scope (because it's in a specification expression) so8876// either it is implicitly declared in the host procedure or it is an error.8877// We create a symbol in the host assuming it is the former; if that proves to8878// be wrong we report an error later in CheckDeclarations().8879bool DeclarationVisitor::CheckForHostAssociatedImplicit(8880    const parser::Name &name) {8881  if (!inSpecificationPart_ || inEquivalenceStmt_) {8882    return false;8883  }8884  if (name.symbol) {8885    ApplyImplicitRules(*name.symbol, true);8886  }8887  if (Scope * host{GetHostProcedure()}; host && !isImplicitNoneType(*host)) {8888    Symbol *hostSymbol{nullptr};8889    if (!name.symbol) {8890      if (currScope().CanImport(name.source)) {8891        hostSymbol = &MakeSymbol(*host, name.source, Attrs{});8892        ConvertToObjectEntity(*hostSymbol);8893        ApplyImplicitRules(*hostSymbol);8894        hostSymbol->set(Symbol::Flag::ImplicitOrError);8895      }8896    } else if (name.symbol->test(Symbol::Flag::ImplicitOrError)) {8897      hostSymbol = name.symbol;8898    }8899    if (hostSymbol) {8900      Symbol &symbol{MakeHostAssocSymbol(name, *hostSymbol)};8901      if (auto *assoc{symbol.detailsIf<HostAssocDetails>()}) {8902        if (isImplicitNoneType()) {8903          assoc->implicitOrExplicitTypeError = true;8904        } else {8905          assoc->implicitOrSpecExprError = true;8906        }8907        return true;8908      }8909    }8910  }8911  return false;8912}8913 8914bool DeclarationVisitor::IsUplevelReference(const Symbol &symbol) {8915  if (symbol.owner().IsTopLevel()) {8916    return false;8917  }8918  const Scope &symbolUnit{GetProgramUnitContaining(symbol)};8919  if (symbolUnit == GetProgramUnitContaining(currScope())) {8920    return false;8921  } else {8922    Scope::Kind kind{symbolUnit.kind()};8923    return kind == Scope::Kind::Subprogram || kind == Scope::Kind::MainProgram;8924  }8925}8926 8927// base is a part-ref of a derived type; find the named component in its type.8928// Also handles intrinsic type parameter inquiries (%kind, %len) and8929// COMPLEX component references (%re, %im).8930const parser::Name *DeclarationVisitor::FindComponent(8931    const parser::Name *base, const parser::Name &component) {8932  if (!base || !base->symbol) {8933    return nullptr;8934  }8935  if (auto *misc{base->symbol->detailsIf<MiscDetails>()}) {8936    if (component.source == "kind") {8937      if (misc->kind() == MiscDetails::Kind::ComplexPartRe ||8938          misc->kind() == MiscDetails::Kind::ComplexPartIm ||8939          misc->kind() == MiscDetails::Kind::KindParamInquiry ||8940          misc->kind() == MiscDetails::Kind::LenParamInquiry) {8941        // x%{re,im,kind,len}%kind8942        MakePlaceholder(component, MiscDetails::Kind::KindParamInquiry);8943        return &component;8944      }8945    }8946  }8947  CheckEntryDummyUse(base->source, base->symbol);8948  auto &symbol{base->symbol->GetUltimate()};8949  if (!symbol.has<AssocEntityDetails>() && !ConvertToObjectEntity(symbol)) {8950    SayWithDecl(*base, symbol,8951        "'%s' is not an object and may not be used as the base of a component reference or type parameter inquiry"_err_en_US);8952    return nullptr;8953  }8954  auto *type{symbol.GetType()};8955  if (!type) {8956    return nullptr; // should have already reported error8957  }8958  if (const IntrinsicTypeSpec * intrinsic{type->AsIntrinsic()}) {8959    auto category{intrinsic->category()};8960    MiscDetails::Kind miscKind{MiscDetails::Kind::None};8961    if (component.source == "kind") {8962      miscKind = MiscDetails::Kind::KindParamInquiry;8963    } else if (category == TypeCategory::Character) {8964      if (component.source == "len") {8965        miscKind = MiscDetails::Kind::LenParamInquiry;8966      }8967    } else if (category == TypeCategory::Complex) {8968      if (component.source == "re") {8969        miscKind = MiscDetails::Kind::ComplexPartRe;8970      } else if (component.source == "im") {8971        miscKind = MiscDetails::Kind::ComplexPartIm;8972      }8973    }8974    if (miscKind != MiscDetails::Kind::None) {8975      MakePlaceholder(component, miscKind);8976      return &component;8977    }8978  } else if (DerivedTypeSpec * derived{type->AsDerived()}) {8979    derived->Instantiate(currScope()); // in case of forward referenced type8980    if (const Scope * scope{derived->scope()}) {8981      if (Resolve(component, scope->FindComponent(component.source))) {8982        if (auto msg{CheckAccessibleSymbol(currScope(), *component.symbol)}) {8983          context().Say(component.source, *msg);8984        }8985        return &component;8986      } else {8987        SayDerivedType(component.source,8988            "Component '%s' not found in derived type '%s'"_err_en_US, *scope);8989      }8990    }8991    return nullptr;8992  }8993  if (symbol.test(Symbol::Flag::Implicit)) {8994    Say(*base,8995        "'%s' is not an object of derived type; it is implicitly typed"_err_en_US);8996  } else {8997    SayWithDecl(8998        *base, symbol, "'%s' is not an object of derived type"_err_en_US);8999  }9000  return nullptr;9001}9002 9003bool DeclarationVisitor::FindAndMarkDeclareTargetSymbol(9004    const parser::Name &name) {9005  if (!specPartState_.declareTargetNames.empty()) {9006    if (specPartState_.declareTargetNames.count(name.source)) {9007      if (!currScope().IsTopLevel()) {9008        // Search preceding scopes until we find a matching symbol or run out9009        // of scopes to search, we skip the current scope as it's already been9010        // designated as implicit here.9011        for (auto *scope = &currScope().parent();; scope = &scope->parent()) {9012          if (Symbol * symbol{scope->FindSymbol(name.source)}) {9013            if (symbol->test(Symbol::Flag::Subroutine) ||9014                symbol->test(Symbol::Flag::Function)) {9015              const auto [sym, success]{currScope().try_emplace(9016                  symbol->name(), Attrs{}, HostAssocDetails{*symbol})};9017              assert(success &&9018                  "FindAndMarkDeclareTargetSymbol could not emplace new "9019                  "subroutine/function symbol");9020              name.symbol = &*sym->second;9021              symbol->test(Symbol::Flag::Subroutine)9022                  ? name.symbol->set(Symbol::Flag::Subroutine)9023                  : name.symbol->set(Symbol::Flag::Function);9024              return true;9025            }9026            // if we find a symbol that is not a function or subroutine, we9027            // currently escape without doing anything.9028            break;9029          }9030 9031          // This is our loop exit condition, as parent() has an inbuilt assert9032          // if you call it on a top level scope, rather than returning a null9033          // value.9034          if (scope->IsTopLevel()) {9035            return false;9036          }9037        }9038      }9039    }9040  }9041  return false;9042}9043 9044void DeclarationVisitor::Initialization(const parser::Name &name,9045    const parser::Initialization &init, bool inComponentDecl) {9046  // Traversal of the initializer was deferred to here so that the9047  // symbol being declared can be available for use in the expression, e.g.:9048  //   real, parameter :: x = tiny(x)9049  if (!name.symbol) {9050    return;9051  }9052  Symbol &ultimate{name.symbol->GetUltimate()};9053  // TODO: check C762 - all bounds and type parameters of component9054  // are colons or constant expressions if component is initialized9055  common::visit(9056      common::visitors{9057          [&](const parser::ConstantExpr &expr) {9058            Walk(expr);9059            if (IsNamedConstant(ultimate) || inComponentDecl) {9060              NonPointerInitialization(name, expr);9061            } else {9062              // Defer analysis so forward references to nested subprograms9063              // can be properly resolved when they appear in structure9064              // constructors.9065              ultimate.set(Symbol::Flag::InDataStmt);9066            }9067          },9068          [&](const std::list<Indirection<parser::DataStmtValue>> &values) {9069            Walk(values);9070            if (inComponentDecl) {9071              LegacyDataInitialization(name, values);9072            } else {9073              ultimate.set(Symbol::Flag::InDataStmt);9074            }9075          },9076          [&](const parser::NullInit &null) { // => NULL()9077            Walk(null);9078            if (auto nullInit{EvaluateExpr(null)}) {9079              if (!evaluate::IsNullPointer(&*nullInit)) { // C8139080                Say(null.v.value().source,9081                    "Pointer initializer must be intrinsic NULL()"_err_en_US);9082              } else if (IsPointer(ultimate)) {9083                if (auto *object{ultimate.detailsIf<ObjectEntityDetails>()}) {9084                  CHECK(!object->init());9085                  object->set_init(std::move(*nullInit));9086                } else if (auto *procPtr{9087                               ultimate.detailsIf<ProcEntityDetails>()}) {9088                  CHECK(!procPtr->init());9089                  procPtr->set_init(nullptr);9090                }9091              } else {9092                Say(name,9093                    "Non-pointer component '%s' initialized with null pointer"_err_en_US);9094              }9095            }9096          },9097          [&](const parser::InitialDataTarget &target) {9098            // Defer analysis to the end of the specification part9099            // so that forward references and attribute checks like SAVE9100            // work better.9101            if (inComponentDecl) {9102              PointerInitialization(name, target);9103            } else {9104              auto restorer{common::ScopedSet(deferImplicitTyping_, true)};9105              Walk(target);9106              ultimate.set(Symbol::Flag::InDataStmt);9107            }9108          },9109      },9110      init.u);9111}9112 9113void DeclarationVisitor::PointerInitialization(9114    const parser::Name &name, const parser::InitialDataTarget &target) {9115  if (name.symbol) {9116    Symbol &ultimate{name.symbol->GetUltimate()};9117    if (!context().HasError(ultimate)) {9118      if (IsPointer(ultimate)) {9119        Walk(target);9120        if (MaybeExpr expr{EvaluateExpr(target)}) {9121          // Validation is done in declaration checking.9122          if (auto *details{ultimate.detailsIf<ObjectEntityDetails>()}) {9123            CHECK(!details->init());9124            details->set_init(std::move(*expr));9125            ultimate.set(Symbol::Flag::InDataStmt, false);9126          } else if (auto *details{ultimate.detailsIf<ProcEntityDetails>()}) {9127            // something like "REAL, EXTERNAL, POINTER :: p => t"9128            if (evaluate::IsNullProcedurePointer(&*expr)) {9129              CHECK(!details->init());9130              details->set_init(nullptr);9131            } else if (const Symbol *9132                targetSymbol{evaluate::UnwrapWholeSymbolDataRef(*expr)}) {9133              CHECK(!details->init());9134              details->set_init(*targetSymbol);9135            } else {9136              Say(name,9137                  "Procedure pointer '%s' must be initialized with a procedure name or NULL()"_err_en_US);9138              context().SetError(ultimate);9139            }9140          }9141        }9142      } else {9143        Say(name,9144            "'%s' is not a pointer but is initialized like one"_err_en_US);9145        context().SetError(ultimate);9146      }9147    }9148  }9149}9150void DeclarationVisitor::PointerInitialization(9151    const parser::Name &name, const parser::ProcPointerInit &target) {9152  if (name.symbol) {9153    Symbol &ultimate{name.symbol->GetUltimate()};9154    if (!context().HasError(ultimate)) {9155      if (IsProcedurePointer(ultimate)) {9156        auto &details{ultimate.get<ProcEntityDetails>()};9157        if (details.init()) {9158          Say(name, "'%s' was previously initialized"_err_en_US);9159          context().SetError(ultimate);9160        } else if (const auto *targetName{9161                       std::get_if<parser::Name>(&target.u)}) {9162          Walk(target);9163          if (!CheckUseError(*targetName) && targetName->symbol) {9164            // Validation is done in declaration checking.9165            details.set_init(*targetName->symbol);9166          }9167        } else { // explicit NULL9168          details.set_init(nullptr);9169        }9170      } else {9171        Say(name,9172            "'%s' is not a procedure pointer but is initialized like one"_err_en_US);9173        context().SetError(ultimate);9174      }9175    }9176  }9177}9178 9179bool DeclarationVisitor::CheckNonPointerInitialization(9180    const parser::Name &name, bool inLegacyDataInitialization) {9181  if (!context().HasError(name.symbol)) {9182    Symbol &ultimate{name.symbol->GetUltimate()};9183    if (!context().HasError(ultimate)) {9184      if (IsPointer(ultimate) && !inLegacyDataInitialization) {9185        Say(name,9186            "'%s' is a pointer but is not initialized like one"_err_en_US);9187      } else if (auto *details{ultimate.detailsIf<ObjectEntityDetails>()}) {9188        if (details->init()) {9189          SayWithDecl(name, *name.symbol,9190              "'%s' has already been initialized"_err_en_US);9191        } else if (IsAllocatable(ultimate)) {9192          Say(name, "Allocatable object '%s' cannot be initialized"_err_en_US);9193        } else if (details->isCDefined()) {9194          // CDEFINED variables cannot have initializer, because their storage9195          // may come outside of Fortran.9196          Say(name, "CDEFINED variable cannot be initialized"_err_en_US);9197        } else {9198          return true;9199        }9200      } else {9201        Say(name, "'%s' is not an object that can be initialized"_err_en_US);9202      }9203    }9204  }9205  return false;9206}9207 9208void DeclarationVisitor::NonPointerInitialization(9209    const parser::Name &name, const parser::ConstantExpr &constExpr) {9210  if (CheckNonPointerInitialization(9211          name, /*inLegacyDataInitialization=*/false)) {9212    Symbol &ultimate{name.symbol->GetUltimate()};9213    auto &details{ultimate.get<ObjectEntityDetails>()};9214    const auto &expr{parser::UnwrapRef<parser::Expr>(constExpr)};9215    if (ultimate.owner().IsParameterizedDerivedType()) {9216      // Save the expression for per-instantiation analysis.9217      details.set_unanalyzedPDTComponentInit(&expr);9218    } else if (MaybeExpr folded{EvaluateNonPointerInitializer(9219                   ultimate, constExpr, expr.source)}) {9220      details.set_init(std::move(*folded));9221      ultimate.set(Symbol::Flag::InDataStmt, false);9222    }9223  }9224}9225 9226void DeclarationVisitor::LegacyDataInitialization(const parser::Name &name,9227    const std::list<common::Indirection<parser::DataStmtValue>> &values) {9228  if (CheckNonPointerInitialization(9229          name, /*inLegacyDataInitialization=*/true)) {9230    Symbol &ultimate{name.symbol->GetUltimate()};9231    if (ultimate.owner().IsParameterizedDerivedType()) {9232      Say(name,9233          "Component '%s' in a parameterized data type may not be initialized with a legacy DATA-style value list"_err_en_US,9234          name.source);9235    } else {9236      evaluate::ExpressionAnalyzer exprAnalyzer{context()};9237      for (const auto &value : values) {9238        exprAnalyzer.Analyze(value.value());9239      }9240      DataInitializations inits;9241      auto oldSize{ultimate.size()};9242      if (auto chars{evaluate::characteristics::TypeAndShape::Characterize(9243              ultimate, GetFoldingContext())}) {9244        if (auto size{evaluate::ToInt64(9245                chars->MeasureSizeInBytes(GetFoldingContext()))}) {9246          // Temporarily set the byte size of the component so that we don't9247          // get bogus "initialization out of range" errors below.9248          ultimate.set_size(*size);9249        }9250      }9251      AccumulateDataInitializations(inits, exprAnalyzer, ultimate, values);9252      ConvertToInitializers(inits, exprAnalyzer);9253      ultimate.set_size(oldSize);9254    }9255  }9256}9257 9258void ResolveNamesVisitor::HandleCall(9259    Symbol::Flag procFlag, const parser::Call &call) {9260  common::visit(9261      common::visitors{9262          [&](const parser::Name &x) { HandleProcedureName(procFlag, x); },9263          [&](const parser::ProcComponentRef &x) {9264            Walk(x);9265            const parser::Name &name{x.v.thing.component};9266            if (Symbol * symbol{name.symbol}) {9267              if (IsProcedure(*symbol)) {9268                SetProcFlag(name, *symbol, procFlag);9269              }9270            }9271          },9272      },9273      std::get<parser::ProcedureDesignator>(call.t).u);9274  const auto &arguments{std::get<std::list<parser::ActualArgSpec>>(call.t)};9275  Walk(arguments);9276  // Once an object has appeared in a specification function reference as9277  // a whole scalar actual argument, it cannot be (re)dimensioned later.9278  // The fact that it appeared to be a scalar may determine the resolution9279  // or the result of an inquiry intrinsic function or generic procedure.9280  if (inSpecificationPart_) {9281    for (const auto &argSpec : arguments) {9282      const auto &actual{std::get<parser::ActualArg>(argSpec.t)};9283      if (const auto *expr{9284              std::get_if<common::Indirection<parser::Expr>>(&actual.u)}) {9285        if (const auto *designator{9286                std::get_if<common::Indirection<parser::Designator>>(9287                    &expr->value().u)}) {9288          if (const auto *dataRef{9289                  std::get_if<parser::DataRef>(&designator->value().u)}) {9290            if (const auto *name{std::get_if<parser::Name>(&dataRef->u)};9291                name && name->symbol) {9292              const Symbol &symbol{*name->symbol};9293              const auto *object{symbol.detailsIf<ObjectEntityDetails>()};9294              if (symbol.has<EntityDetails>() ||9295                  (object && !object->IsArray())) {9296                NoteScalarSpecificationArgument(symbol);9297              }9298            }9299          }9300        }9301      }9302    }9303  }9304}9305 9306void ResolveNamesVisitor::HandleProcedureName(9307    Symbol::Flag flag, const parser::Name &name) {9308  CHECK(flag == Symbol::Flag::Function || flag == Symbol::Flag::Subroutine);9309  auto *symbol{FindSymbol(NonDerivedTypeScope(), name)};9310  if (!symbol) {9311    if (IsIntrinsic(name.source, flag)) {9312      symbol = &MakeSymbol(InclusiveScope(), name.source, Attrs{});9313      SetImplicitAttr(*symbol, Attr::INTRINSIC);9314    } else if (const auto ppcBuiltinScope =9315                   currScope().context().GetPPCBuiltinsScope()) {9316      // Check if it is a builtin from the predefined module9317      symbol = FindSymbol(*ppcBuiltinScope, name);9318      if (!symbol) {9319        symbol = &MakeSymbol(context().globalScope(), name.source, Attrs{});9320      }9321    } else {9322      symbol = &MakeSymbol(context().globalScope(), name.source, Attrs{});9323    }9324    Resolve(name, *symbol);9325    ConvertToProcEntity(*symbol, name.source);9326    if (!symbol->attrs().test(Attr::INTRINSIC)) {9327      if (CheckImplicitNoneExternal(name.source, *symbol)) {9328        MakeExternal(*symbol);9329        // Create a place-holder HostAssocDetails symbol to preclude later9330        // use of this name as a local symbol; but don't actually use this new9331        // HostAssocDetails symbol in expressions.9332        MakeHostAssocSymbol(name, *symbol);9333        name.symbol = symbol;9334      }9335    }9336    CheckEntryDummyUse(name.source, symbol);9337    SetProcFlag(name, *symbol, flag);9338  } else if (CheckUseError(name)) {9339    // error was reported9340  } else {9341    symbol = &symbol->GetUltimate();9342    if (!name.symbol ||9343        (name.symbol->has<HostAssocDetails>() && symbol->owner().IsGlobal() &&9344            (symbol->has<ProcEntityDetails>() ||9345                (symbol->has<SubprogramDetails>() &&9346                    symbol->scope() /*not ENTRY*/)))) {9347      name.symbol = symbol;9348    }9349    CheckEntryDummyUse(name.source, symbol);9350    bool convertedToProcEntity{ConvertToProcEntity(*symbol, name.source)};9351    if (convertedToProcEntity && !symbol->attrs().test(Attr::EXTERNAL) &&9352        IsIntrinsic(symbol->name(), flag) && !IsDummy(*symbol)) {9353      AcquireIntrinsicProcedureFlags(*symbol);9354    }9355    if (!SetProcFlag(name, *symbol, flag)) {9356      return; // reported error9357    }9358    CheckImplicitNoneExternal(name.source, *symbol);9359    if (IsProcedure(*symbol) || symbol->has<DerivedTypeDetails>() ||9360        symbol->has<AssocEntityDetails>()) {9361      // Symbols with DerivedTypeDetails and AssocEntityDetails are accepted9362      // here as procedure-designators because this means the related9363      // FunctionReference are mis-parsed structure constructors or array9364      // references that will be fixed later when analyzing expressions.9365    } else if (symbol->has<ObjectEntityDetails>()) {9366      // Symbols with ObjectEntityDetails are also accepted because this can be9367      // a mis-parsed array reference that will be fixed later. Ensure that if9368      // this is a symbol from a host procedure, a symbol with HostAssocDetails9369      // is created for the current scope.9370      // Operate on non ultimate symbol so that HostAssocDetails are also9371      // created for symbols used associated in the host procedure.9372      ResolveName(name);9373    } else if (symbol->test(Symbol::Flag::Implicit)) {9374      Say(name,9375          "Use of '%s' as a procedure conflicts with its implicit definition"_err_en_US);9376    } else {9377      SayWithDecl(name, *symbol,9378          "Use of '%s' as a procedure conflicts with its declaration"_err_en_US);9379    }9380  }9381}9382 9383bool ResolveNamesVisitor::CheckImplicitNoneExternal(9384    const SourceName &name, const Symbol &symbol) {9385  if (symbol.has<ProcEntityDetails>() && isImplicitNoneExternal() &&9386      !symbol.attrs().test(Attr::EXTERNAL) &&9387      !symbol.attrs().test(Attr::INTRINSIC) && !symbol.HasExplicitInterface()) {9388    Say(name,9389        "'%s' is an external procedure without the EXTERNAL attribute in a scope with IMPLICIT NONE(EXTERNAL)"_err_en_US);9390    return false;9391  }9392  return true;9393}9394 9395// Variant of HandleProcedureName() for use while skimming the executable9396// part of a subprogram to catch calls to dummy procedures that are part9397// of the subprogram's interface, and to mark as procedures any symbols9398// that might otherwise have been miscategorized as objects.9399void ResolveNamesVisitor::NoteExecutablePartCall(9400    Symbol::Flag flag, SourceName name, bool hasCUDAChevrons) {9401  // Subtlety: The symbol pointers in the parse tree are not set, because9402  // they might end up resolving elsewhere (e.g., construct entities in9403  // SELECT TYPE).9404  if (Symbol * symbol{currScope().FindSymbol(name)}) {9405    Symbol::Flag other{flag == Symbol::Flag::Subroutine9406            ? Symbol::Flag::Function9407            : Symbol::Flag::Subroutine};9408    if (!symbol->test(other)) {9409      ConvertToProcEntity(*symbol, name);9410      if (auto *details{symbol->detailsIf<ProcEntityDetails>()}) {9411        symbol->set(flag);9412        if (IsDummy(*symbol)) {9413          SetImplicitAttr(*symbol, Attr::EXTERNAL);9414        }9415        ApplyImplicitRules(*symbol);9416        if (hasCUDAChevrons) {9417          details->set_isCUDAKernel();9418        }9419      }9420    }9421  }9422}9423 9424static bool IsLocallyImplicitGlobalSymbol(9425    const Symbol &symbol, const parser::Name &localName) {9426  if (symbol.owner().IsGlobal()) {9427    const auto *subp{symbol.detailsIf<SubprogramDetails>()};9428    const Scope *scope{9429        subp && subp->entryScope() ? subp->entryScope() : symbol.scope()};9430    return !(scope && scope->sourceRange().Contains(localName.source));9431  }9432  return false;9433}9434 9435// Check and set the Function or Subroutine flag on symbol; false on error.9436bool ResolveNamesVisitor::SetProcFlag(9437    const parser::Name &name, Symbol &symbol, Symbol::Flag flag) {9438  if (symbol.test(Symbol::Flag::Function) && flag == Symbol::Flag::Subroutine) {9439    SayWithDecl(9440        name, symbol, "Cannot call function '%s' like a subroutine"_err_en_US);9441    context().SetError(symbol);9442    return false;9443  } else if (symbol.test(Symbol::Flag::Subroutine) &&9444      flag == Symbol::Flag::Function) {9445    SayWithDecl(9446        name, symbol, "Cannot call subroutine '%s' like a function"_err_en_US);9447    context().SetError(symbol);9448    return false;9449  } else if (flag == Symbol::Flag::Function &&9450      IsLocallyImplicitGlobalSymbol(symbol, name) &&9451      TypesMismatchIfNonNull(symbol.GetType(), GetImplicitType(symbol))) {9452    SayWithDecl(name, symbol,9453        "Implicit declaration of function '%s' has a different result type than in previous declaration"_err_en_US);9454    return false;9455  } else if (const auto *proc{symbol.detailsIf<ProcEntityDetails>()}) {9456    if (IsPointer(symbol) && !proc->type() && !proc->procInterface()) {9457      // PROCEDURE(), POINTER -- errors will be emitted later about a lack9458      // of known characteristics if used as a function9459    } else {9460      symbol.set(flag); // in case it hasn't been set yet9461      if (flag == Symbol::Flag::Function) {9462        ApplyImplicitRules(symbol);9463      }9464      if (symbol.attrs().test(Attr::INTRINSIC)) {9465        AcquireIntrinsicProcedureFlags(symbol);9466      }9467    }9468  } else if (symbol.GetType() && flag == Symbol::Flag::Subroutine) {9469    SayWithDecl(9470        name, symbol, "Cannot call function '%s' like a subroutine"_err_en_US);9471    context().SetError(symbol);9472  } else if (symbol.attrs().test(Attr::INTRINSIC)) {9473    AcquireIntrinsicProcedureFlags(symbol);9474  }9475  return true;9476}9477 9478bool ModuleVisitor::Pre(const parser::AccessStmt &x) {9479  Attr accessAttr{AccessSpecToAttr(std::get<parser::AccessSpec>(x.t))};9480  if (!currScope().IsModule()) { // C8699481    Say(currStmtSource().value(),9482        "%s statement may only appear in the specification part of a module"_err_en_US,9483        EnumToString(accessAttr));9484    return false;9485  }9486  const auto &accessIds{std::get<std::list<parser::AccessId>>(x.t)};9487  if (accessIds.empty()) {9488    if (prevAccessStmt_) { // C8699489      Say("The default accessibility of this module has already been declared"_err_en_US)9490          .Attach(*prevAccessStmt_, "Previous declaration"_en_US);9491    }9492    prevAccessStmt_ = currStmtSource();9493    auto *moduleDetails{DEREF(currScope().symbol()).detailsIf<ModuleDetails>()};9494    DEREF(moduleDetails).set_isDefaultPrivate(accessAttr == Attr::PRIVATE);9495  } else {9496    for (const auto &accessId : accessIds) {9497      GenericSpecInfo info{accessId.v.value()};9498      auto *symbol{FindInScope(info.symbolName())};9499      if (!symbol && !info.kind().IsName()) {9500        symbol = &MakeSymbol(info.symbolName(), Attrs{}, GenericDetails{});9501      }9502      info.Resolve(&SetAccess(info.symbolName(), accessAttr, symbol));9503    }9504  }9505  return false;9506}9507 9508// Set the access specification for this symbol.9509Symbol &ModuleVisitor::SetAccess(9510    const SourceName &name, Attr attr, Symbol *symbol) {9511  if (!symbol) {9512    symbol = &MakeSymbol(name);9513  }9514  Attrs &attrs{symbol->attrs()};9515  if (attrs.HasAny({Attr::PUBLIC, Attr::PRIVATE})) {9516    // PUBLIC/PRIVATE already set: make it a fatal error if it changed9517    Attr prev{attrs.test(Attr::PUBLIC) ? Attr::PUBLIC : Attr::PRIVATE};9518    if (attr != prev) {9519      Say(name,9520          "The accessibility of '%s' has already been specified as %s"_err_en_US,9521          MakeOpName(name), EnumToString(prev));9522    } else {9523      context().Warn(common::LanguageFeature::RedundantAttribute, name,9524          "The accessibility of '%s' has already been specified as %s"_warn_en_US,9525          MakeOpName(name), EnumToString(prev));9526    }9527  } else {9528    attrs.set(attr);9529  }9530  return *symbol;9531}9532 9533static bool NeedsExplicitType(const Symbol &symbol) {9534  if (symbol.has<UnknownDetails>()) {9535    return true;9536  } else if (const auto *details{symbol.detailsIf<EntityDetails>()}) {9537    return !details->type();9538  } else if (const auto *details{symbol.detailsIf<ObjectEntityDetails>()}) {9539    return !details->type();9540  } else if (const auto *details{symbol.detailsIf<ProcEntityDetails>()}) {9541    return !details->procInterface() && !details->type();9542  } else {9543    return false;9544  }9545}9546 9547void ResolveNamesVisitor::HandleDerivedTypesInImplicitStmts(9548    const parser::ImplicitPart &implicitPart,9549    const std::list<parser::DeclarationConstruct> &decls) {9550  // Detect derived type definitions and create symbols for them now if9551  // they appear in IMPLICIT statements so that these forward-looking9552  // references will not be ambiguous with host associations.9553  std::set<SourceName> implicitDerivedTypes;9554  for (const auto &ipStmt : implicitPart.v) {9555    if (const auto *impl{std::get_if<9556            parser::Statement<common::Indirection<parser::ImplicitStmt>>>(9557            &ipStmt.u)}) {9558      if (const auto *specs{std::get_if<std::list<parser::ImplicitSpec>>(9559              &impl->statement.value().u)}) {9560        for (const auto &spec : *specs) {9561          const auto &declTypeSpec{9562              std::get<parser::DeclarationTypeSpec>(spec.t)};9563          if (const auto *dtSpec{common::visit(9564                  common::visitors{9565                      [](const parser::DeclarationTypeSpec::Type &x) {9566                        return &x.derived;9567                      },9568                      [](const parser::DeclarationTypeSpec::Class &x) {9569                        return &x.derived;9570                      },9571                      [](const auto &) -> const parser::DerivedTypeSpec * {9572                        return nullptr;9573                      }},9574                  declTypeSpec.u)}) {9575            implicitDerivedTypes.emplace(9576                std::get<parser::Name>(dtSpec->t).source);9577          }9578        }9579      }9580    }9581  }9582  if (!implicitDerivedTypes.empty()) {9583    for (const auto &decl : decls) {9584      if (const auto *spec{9585              std::get_if<parser::SpecificationConstruct>(&decl.u)}) {9586        if (const auto *dtDef{9587                std::get_if<common::Indirection<parser::DerivedTypeDef>>(9588                    &spec->u)}) {9589          const parser::DerivedTypeStmt &dtStmt{9590              std::get<parser::Statement<parser::DerivedTypeStmt>>(9591                  dtDef->value().t)9592                  .statement};9593          const parser::Name &name{std::get<parser::Name>(dtStmt.t)};9594          if (implicitDerivedTypes.find(name.source) !=9595                  implicitDerivedTypes.end() &&9596              !FindInScope(name)) {9597            DerivedTypeDetails details;9598            details.set_isForwardReferenced(true);9599            Resolve(name, MakeSymbol(name, std::move(details)));9600            implicitDerivedTypes.erase(name.source);9601          }9602        }9603      }9604    }9605  }9606}9607 9608bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {9609  const auto &[accDecls, ompDecls, compilerDirectives, useStmts, importStmts,9610      implicitPart, decls] = x.t;9611  auto flagRestorer{common::ScopedSet(inSpecificationPart_, true)};9612  auto stateRestorer{9613      common::ScopedSet(specPartState_, SpecificationPartState{})};9614  Walk(accDecls);9615  Walk(ompDecls);9616  Walk(compilerDirectives);9617  for (const auto &useStmt : useStmts) {9618    CollectUseRenames(useStmt.statement.value());9619  }9620  Walk(useStmts);9621  UseCUDABuiltinNames();9622  ClearUseRenames();9623  ClearUseOnly();9624  ClearModuleUses();9625  Walk(importStmts);9626  HandleDerivedTypesInImplicitStmts(implicitPart, decls);9627  Walk(implicitPart);9628  for (const auto &decl : decls) {9629    if (const auto *spec{9630            std::get_if<parser::SpecificationConstruct>(&decl.u)}) {9631      PreSpecificationConstruct(*spec);9632    }9633  }9634  Walk(decls);9635  FinishSpecificationPart(decls);9636  return false;9637}9638 9639void ResolveNamesVisitor::UseCUDABuiltinNames() {9640  if (FindCUDADeviceContext(&currScope())) {9641    for (const auto &[name, symbol] : context().GetCUDABuiltinsScope()) {9642      if (!FindInScope(name)) {9643        auto &localSymbol{MakeSymbol(name)};9644        localSymbol.set_details(UseDetails{name, *symbol});9645        localSymbol.flags() = symbol->flags();9646      }9647    }9648  }9649}9650 9651// Initial processing on specification constructs, before visiting them.9652void ResolveNamesVisitor::PreSpecificationConstruct(9653    const parser::SpecificationConstruct &spec) {9654  common::visit(9655      common::visitors{9656          [&](const parser::Statement<9657              common::Indirection<parser::TypeDeclarationStmt>> &y) {9658            EarlyDummyTypeDeclaration(y);9659          },9660          [&](const parser::Statement<Indirection<parser::GenericStmt>> &y) {9661            CreateGeneric(std::get<parser::GenericSpec>(y.statement.value().t));9662          },9663          [&](const Indirection<parser::InterfaceBlock> &y) {9664            const auto &stmt{std::get<parser::Statement<parser::InterfaceStmt>>(9665                y.value().t)};9666            if (const auto *spec{parser::Unwrap<parser::GenericSpec>(stmt)}) {9667              CreateGeneric(*spec);9668            }9669          },9670          [&](const parser::Statement<parser::OtherSpecificationStmt> &y) {9671            common::visit(9672                common::visitors{9673                    [&](const common::Indirection<parser::CommonStmt> &z) {9674                      CreateCommonBlockSymbols(z.value());9675                    },9676                    [&](const common::Indirection<parser::TargetStmt> &z) {9677                      CreateObjectSymbols(z.value().v, Attr::TARGET);9678                    },9679                    [](const auto &) {},9680                },9681                y.statement.u);9682          },9683          [](const auto &) {},9684      },9685      spec.u);9686}9687 9688void ResolveNamesVisitor::EarlyDummyTypeDeclaration(9689    const parser::Statement<common::Indirection<parser::TypeDeclarationStmt>>9690        &stmt) {9691  context().set_location(stmt.source);9692  const auto &[declTypeSpec, attrs, entities] = stmt.statement.value().t;9693  if (const auto *intrin{9694          std::get_if<parser::IntrinsicTypeSpec>(&declTypeSpec.u)}) {9695    if (const auto *intType{std::get_if<parser::IntegerTypeSpec>(&intrin->u)}) {9696      if (const auto &kind{intType->v}) {9697        if (!parser::Unwrap<parser::KindSelector::StarSize>(*kind) &&9698            !parser::Unwrap<parser::IntLiteralConstant>(*kind)) {9699          return;9700        }9701      }9702      const DeclTypeSpec *type{nullptr};9703      for (const auto &ent : entities) {9704        const auto &objName{std::get<parser::ObjectName>(ent.t)};9705        Resolve(objName, FindInScope(currScope(), objName));9706        if (Symbol * symbol{objName.symbol};9707            symbol && IsDummy(*symbol) && NeedsType(*symbol)) {9708          if (!type) {9709            type = ProcessTypeSpec(declTypeSpec);9710            if (!type || !type->IsNumeric(TypeCategory::Integer)) {9711              break;9712            }9713          }9714          symbol->SetType(*type);9715          NoteEarlyDeclaredDummyArgument(*symbol);9716          // Set the Implicit flag to disable bogus errors from9717          // being emitted later when this declaration is processed9718          // again normally.9719          symbol->set(Symbol::Flag::Implicit);9720        }9721      }9722    }9723  }9724}9725 9726void ResolveNamesVisitor::CreateCommonBlockSymbols(9727    const parser::CommonStmt &commonStmt) {9728  for (const parser::CommonStmt::Block &block : commonStmt.blocks) {9729    const auto &[name, objects] = block.t;9730    Symbol &commonBlock{MakeCommonBlockSymbol(name, commonStmt.source)};9731    for (const auto &object : objects) {9732      Symbol &obj{DeclareObjectEntity(std::get<parser::Name>(object.t))};9733      if (auto *details{obj.detailsIf<ObjectEntityDetails>()}) {9734        details->set_commonBlock(commonBlock);9735        commonBlock.get<CommonBlockDetails>().add_object(obj);9736      }9737    }9738  }9739}9740 9741void ResolveNamesVisitor::CreateObjectSymbols(9742    const std::list<parser::ObjectDecl> &decls, Attr attr) {9743  for (const parser::ObjectDecl &decl : decls) {9744    SetImplicitAttr(DeclareEntity<ObjectEntityDetails>(9745                        std::get<parser::ObjectName>(decl.t), Attrs{}),9746        attr);9747  }9748}9749 9750void ResolveNamesVisitor::CreateGeneric(const parser::GenericSpec &x) {9751  auto info{GenericSpecInfo{x}};9752  SourceName symbolName{info.symbolName()};9753  if (IsLogicalConstant(context(), symbolName)) {9754    Say(symbolName,9755        "Logical constant '%s' may not be used as a defined operator"_err_en_US);9756    return;9757  }9758  GenericDetails genericDetails;9759  Symbol *existing{nullptr};9760  // Check all variants of names, e.g. "operator(.ne.)" for "operator(/=)"9761  for (const std::string &n : GetAllNames(context(), symbolName)) {9762    existing = currScope().FindSymbol(SourceName{n});9763    if (existing) {9764      break;9765    }9766  }9767  if (existing) {9768    Symbol &ultimate{existing->GetUltimate()};9769    if (auto *existingGeneric{ultimate.detailsIf<GenericDetails>()}) {9770      if (&existing->owner() == &currScope()) {9771        if (const auto *existingUse{existing->detailsIf<UseDetails>()}) {9772          // Create a local copy of a use associated generic so that9773          // it can be locally extended without corrupting the original.9774          genericDetails.CopyFrom(*existingGeneric);9775          if (existingGeneric->specific()) {9776            genericDetails.set_specific(*existingGeneric->specific());9777          }9778          AddGenericUse(9779              genericDetails, existing->name(), existingUse->symbol());9780        } else if (existing == &ultimate) {9781          // Extending an extant generic in the same scope9782          info.Resolve(existing);9783          return;9784        } else {9785          // Host association of a generic is handled elsewhere9786          CHECK(existing->has<HostAssocDetails>());9787        }9788      } else {9789        // Create a new generic for this scope.9790      }9791    } else if (ultimate.has<SubprogramDetails>() ||9792        ultimate.has<SubprogramNameDetails>()) {9793      genericDetails.set_specific(*existing);9794    } else if (ultimate.has<ProcEntityDetails>()) {9795      if (existing->name() != symbolName ||9796          !ultimate.attrs().test(Attr::INTRINSIC)) {9797        genericDetails.set_specific(*existing);9798      }9799    } else if (ultimate.has<DerivedTypeDetails>()) {9800      genericDetails.set_derivedType(*existing);9801    } else if (&existing->owner() == &currScope()) {9802      SayAlreadyDeclared(symbolName, *existing);9803      return;9804    }9805    if (&existing->owner() == &currScope()) {9806      EraseSymbol(*existing);9807    }9808  }9809  info.Resolve(&MakeSymbol(symbolName, Attrs{}, std::move(genericDetails)));9810}9811 9812void ResolveNamesVisitor::FinishSpecificationPart(9813    const std::list<parser::DeclarationConstruct> &decls) {9814  misparsedStmtFuncFound_ = false;9815  funcResultStack().CompleteFunctionResultType();9816  CheckImports();9817  for (auto &pair : currScope()) {9818    auto &symbol{*pair.second};9819    if (inInterfaceBlock()) {9820      ConvertToObjectEntity(symbol);9821    }9822    if (NeedsExplicitType(symbol)) {9823      ApplyImplicitRules(symbol);9824    }9825    if (IsDummy(symbol) && isImplicitNoneType() &&9826        symbol.test(Symbol::Flag::Implicit) && !context().HasError(symbol)) {9827      Say(symbol.name(),9828          "No explicit type declared for dummy argument '%s'"_err_en_US);9829      context().SetError(symbol);9830    }9831    if (symbol.has<GenericDetails>()) {9832      CheckGenericProcedures(symbol);9833    }9834    if (!symbol.has<HostAssocDetails>()) {9835      CheckPossibleBadForwardRef(symbol);9836    }9837    // Propagate BIND(C) attribute to procedure entities from their interfaces,9838    // but not the NAME=, even if it is empty (which would be a reasonable9839    // and useful behavior, actually).  This interpretation is not at all9840    // clearly described in the standard, but matches the behavior of several9841    // other compilers.9842    if (auto *proc{symbol.detailsIf<ProcEntityDetails>()}; proc &&9843        !proc->isDummy() && !IsPointer(symbol) &&9844        !symbol.attrs().test(Attr::BIND_C)) {9845      if (const Symbol * iface{proc->procInterface()};9846          iface && IsBindCProcedure(*iface)) {9847        SetImplicitAttr(symbol, Attr::BIND_C);9848        SetBindNameOn(symbol);9849      }9850    }9851  }9852  currScope().InstantiateDerivedTypes();9853  for (const auto &decl : decls) {9854    if (const auto *statement{std::get_if<9855            parser::Statement<common::Indirection<parser::StmtFunctionStmt>>>(9856            &decl.u)}) {9857      messageHandler().set_currStmtSource(statement->source);9858      AnalyzeStmtFunctionStmt(statement->statement.value());9859    }9860  }9861  // TODO: what about instantiations in BLOCK?9862  CheckSaveStmts();9863  CheckCommonBlocks();9864  if (!inInterfaceBlock()) {9865    // TODO: warn for the case where the EQUIVALENCE statement is in a9866    // procedure declaration in an interface block9867    CheckEquivalenceSets();9868  }9869}9870 9871// Analyze the bodies of statement functions now that the symbols in this9872// specification part have been fully declared and implicitly typed.9873// (Statement function references are not allowed in specification9874// expressions, so it's safe to defer processing their definitions.)9875void ResolveNamesVisitor::AnalyzeStmtFunctionStmt(9876    const parser::StmtFunctionStmt &stmtFunc) {9877  const auto &name{std::get<parser::Name>(stmtFunc.t)};9878  Symbol *symbol{name.symbol};9879  auto *details{symbol ? symbol->detailsIf<SubprogramDetails>() : nullptr};9880  if (!details || !symbol->scope() ||9881      &symbol->scope()->parent() != &currScope() || details->isInterface() ||9882      details->isDummy() || details->entryScope() ||9883      details->moduleInterface() || symbol->test(Symbol::Flag::Subroutine)) {9884    return; // error recovery9885  }9886  // Resolve the symbols on the RHS of the statement function.9887  PushScope(*symbol->scope());9888  const auto &parsedExpr{std::get<parser::Scalar<parser::Expr>>(stmtFunc.t)};9889  Walk(parsedExpr);9890  PopScope();9891  if (auto expr{AnalyzeExpr(context(), stmtFunc)}) {9892    if (auto type{evaluate::DynamicType::From(*symbol)}) {9893      if (auto converted{evaluate::ConvertToType(*type, std::move(*expr))}) {9894        details->set_stmtFunction(std::move(*converted));9895      } else {9896        Say(name.source,9897            "Defining expression of statement function '%s' cannot be converted to its result type %s"_err_en_US,9898            name.source, type->AsFortran());9899      }9900    } else {9901      details->set_stmtFunction(std::move(*expr));9902    }9903  }9904  if (!details->stmtFunction()) {9905    context().SetError(*symbol);9906  }9907}9908 9909void ResolveNamesVisitor::CheckImports() {9910  auto &scope{currScope()};9911  switch (scope.GetImportKind()) {9912  case common::ImportKind::None:9913    break;9914  case common::ImportKind::All:9915    // C8102: all entities in host must not be hidden9916    for (const auto &pair : scope.parent()) {9917      auto &name{pair.first};9918      std::optional<SourceName> scopeName{scope.GetName()};9919      if (!scopeName || name != *scopeName) {9920        CheckImport(prevImportStmt_.value(), name);9921      }9922    }9923    break;9924  case common::ImportKind::Default:9925  case common::ImportKind::Only:9926    // C8102: entities named in IMPORT must not be hidden9927    for (auto &name : scope.importNames()) {9928      CheckImport(name, name);9929    }9930    break;9931  }9932}9933 9934void ResolveNamesVisitor::CheckImport(9935    const SourceName &location, const SourceName &name) {9936  if (auto *symbol{FindInScope(name)}) {9937    const Symbol &ultimate{symbol->GetUltimate()};9938    if (&ultimate.owner() == &currScope()) {9939      Say(location, "'%s' from host is not accessible"_err_en_US, name)9940          .Attach(symbol->name(), "'%s' is hidden by this entity"_because_en_US,9941              symbol->name());9942    }9943  }9944}9945 9946bool ResolveNamesVisitor::Pre(const parser::ImplicitStmt &x) {9947  return CheckNotInBlock("IMPLICIT") && // C11079948      ImplicitRulesVisitor::Pre(x);9949}9950 9951void ResolveNamesVisitor::Post(const parser::PointerObject &x) {9952  common::visit(common::visitors{9953                    [&](const parser::Name &x) { ResolveName(x); },9954                    [&](const parser::StructureComponent &x) {9955                      ResolveStructureComponent(x);9956                    },9957                },9958      x.u);9959}9960void ResolveNamesVisitor::Post(const parser::AllocateObject &x) {9961  common::visit(common::visitors{9962                    [&](const parser::Name &x) { ResolveName(x); },9963                    [&](const parser::StructureComponent &x) {9964                      ResolveStructureComponent(x);9965                    },9966                },9967      x.u);9968}9969 9970bool ResolveNamesVisitor::Pre(const parser::PointerAssignmentStmt &x) {9971  const auto &dataRef{std::get<parser::DataRef>(x.t)};9972  const auto &bounds{std::get<parser::PointerAssignmentStmt::Bounds>(x.t)};9973  const auto &expr{std::get<parser::Expr>(x.t)};9974  ResolveDataRef(dataRef);9975  Symbol *ptrSymbol{parser::GetLastName(dataRef).symbol};9976  Walk(bounds);9977  // Resolve unrestricted specific intrinsic procedures as in "p => cos".9978  if (const parser::Name * name{parser::Unwrap<parser::Name>(expr)}) {9979    if (NameIsKnownOrIntrinsic(*name)) {9980      if (Symbol * symbol{name->symbol}) {9981        if (IsProcedurePointer(ptrSymbol) &&9982            !ptrSymbol->test(Symbol::Flag::Function) &&9983            !ptrSymbol->test(Symbol::Flag::Subroutine)) {9984          if (symbol->test(Symbol::Flag::Function)) {9985            ApplyImplicitRules(*ptrSymbol);9986          }9987        }9988        // If the name is known because it is an object entity from a host9989        // procedure, create a host associated symbol.9990        if (symbol->GetUltimate().has<ObjectEntityDetails>() &&9991            IsUplevelReference(*symbol)) {9992          MakeHostAssocSymbol(*name, *symbol);9993        }9994      }9995      return false;9996    }9997    // Can also reference a global external procedure here9998    if (auto it{context().globalScope().find(name->source)};9999        it != context().globalScope().end()) {10000      Symbol &global{*it->second};10001      if (IsProcedure(global)) {10002        Resolve(*name, global);10003        return false;10004      }10005    }10006    if (IsProcedurePointer(parser::GetLastName(dataRef).symbol) &&10007        !FindSymbol(*name)) {10008      // Unknown target of procedure pointer must be an external procedure10009      Symbol &symbol{MakeSymbol(10010          context().globalScope(), name->source, Attrs{Attr::EXTERNAL})};10011      symbol.implicitAttrs().set(Attr::EXTERNAL);10012      Resolve(*name, symbol);10013      ConvertToProcEntity(symbol, name->source);10014      return false;10015    }10016  }10017  Walk(expr);10018  return false;10019}10020void ResolveNamesVisitor::Post(const parser::Designator &x) {10021  ResolveDesignator(x);10022}10023void ResolveNamesVisitor::Post(const parser::SubstringInquiry &x) {10024  Walk(std::get<parser::SubstringRange>(x.v.t).t);10025  ResolveDataRef(std::get<parser::DataRef>(x.v.t));10026}10027 10028void ResolveNamesVisitor::Post(const parser::ProcComponentRef &x) {10029  ResolveStructureComponent(x.v.thing);10030}10031void ResolveNamesVisitor::Post(const parser::TypeGuardStmt &x) {10032  DeclTypeSpecVisitor::Post(x);10033  ConstructVisitor::Post(x);10034}10035bool ResolveNamesVisitor::Pre(const parser::StmtFunctionStmt &x) {10036  if (HandleStmtFunction(x)) {10037    return false;10038  } else {10039    // This is an array element or pointer-valued function assignment:10040    // resolve the names of indices/arguments10041    const auto &names{std::get<std::list<parser::Name>>(x.t)};10042    for (auto &name : names) {10043      ResolveName(name);10044    }10045    return true;10046  }10047}10048 10049bool ResolveNamesVisitor::Pre(const parser::DefinedOpName &x) {10050  const parser::Name &name{x.v};10051  if (FindSymbol(name)) {10052    // OK10053  } else if (IsLogicalConstant(context(), name.source)) {10054    Say(name,10055        "Logical constant '%s' may not be used as a defined operator"_err_en_US);10056  } else {10057    // Resolved later in expression semantics10058    MakePlaceholder(name, MiscDetails::Kind::TypeBoundDefinedOp);10059  }10060  return false;10061}10062 10063void ResolveNamesVisitor::Post(const parser::AssignStmt &x) {10064  if (auto *name{ResolveName(std::get<parser::Name>(x.t))}) {10065    CheckEntryDummyUse(name->source, name->symbol);10066    ConvertToObjectEntity(DEREF(name->symbol));10067  }10068}10069void ResolveNamesVisitor::Post(const parser::AssignedGotoStmt &x) {10070  if (auto *name{ResolveName(std::get<parser::Name>(x.t))}) {10071    CheckEntryDummyUse(name->source, name->symbol);10072    ConvertToObjectEntity(DEREF(name->symbol));10073  }10074}10075 10076void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {10077  if (std::holds_alternative<parser::CompilerDirective::VectorAlways>(x.u) ||10078      std::holds_alternative<parser::CompilerDirective::Unroll>(x.u) ||10079      std::holds_alternative<parser::CompilerDirective::UnrollAndJam>(x.u) ||10080      std::holds_alternative<parser::CompilerDirective::NoVector>(x.u) ||10081      std::holds_alternative<parser::CompilerDirective::NoUnroll>(x.u) ||10082      std::holds_alternative<parser::CompilerDirective::NoUnrollAndJam>(x.u) ||10083      std::holds_alternative<parser::CompilerDirective::ForceInline>(x.u) ||10084      std::holds_alternative<parser::CompilerDirective::Inline>(x.u) ||10085      std::holds_alternative<parser::CompilerDirective::Prefetch>(x.u) ||10086      std::holds_alternative<parser::CompilerDirective::NoInline>(x.u) ||10087      std::holds_alternative<parser::CompilerDirective::IVDep>(x.u)) {10088    return;10089  }10090  if (const auto *tkr{10091          std::get_if<std::list<parser::CompilerDirective::IgnoreTKR>>(&x.u)}) {10092    if (currScope().IsTopLevel() ||10093        GetProgramUnitContaining(currScope()).kind() !=10094            Scope::Kind::Subprogram) {10095      Say(x.source,10096          "!DIR$ IGNORE_TKR directive must appear in a subroutine or function"_err_en_US);10097      return;10098    }10099    if (!inSpecificationPart_) {10100      Say(x.source,10101          "!DIR$ IGNORE_TKR directive must appear in the specification part"_err_en_US);10102      return;10103    }10104    if (tkr->empty()) {10105      Symbol *symbol{currScope().symbol()};10106      if (SubprogramDetails *10107          subp{symbol ? symbol->detailsIf<SubprogramDetails>() : nullptr}) {10108        subp->set_defaultIgnoreTKR(true);10109      }10110    } else {10111      for (const parser::CompilerDirective::IgnoreTKR &item : *tkr) {10112        common::IgnoreTKRSet set;10113        if (const auto &maybeList{10114                std::get<std::optional<std::list<const char *>>>(item.t)}) {10115          for (const char *p : *maybeList) {10116            if (p) {10117              switch (*p) {10118              case 't':10119                set.set(common::IgnoreTKR::Type);10120                break;10121              case 'k':10122                set.set(common::IgnoreTKR::Kind);10123                break;10124              case 'r':10125                set.set(common::IgnoreTKR::Rank);10126                break;10127              case 'd':10128                set.set(common::IgnoreTKR::Device);10129                break;10130              case 'm':10131                set.set(common::IgnoreTKR::Managed);10132                break;10133              case 'c':10134                set.set(common::IgnoreTKR::Contiguous);10135                break;10136              case 'p':10137                set.set(common::IgnoreTKR::Pointer);10138                break;10139              case 'a':10140                set = common::ignoreTKRAll;10141                break;10142              default:10143                Say(x.source,10144                    "'%c' is not a valid letter for !DIR$ IGNORE_TKR directive"_err_en_US,10145                    *p);10146                set = common::ignoreTKRAll;10147                break;10148              }10149            }10150          }10151          if (set.empty()) {10152            Say(x.source,10153                "!DIR$ IGNORE_TKR directive may not have an empty parenthesized list of letters"_err_en_US);10154          }10155        } else { // no (list)10156          set = common::ignoreTKRAll;10157          ;10158        }10159        const auto &name{std::get<parser::Name>(item.t)};10160        Symbol *symbol{FindSymbol(name)};10161        if (!symbol) {10162          symbol = &MakeSymbol(name, Attrs{}, ObjectEntityDetails{});10163        }10164        if (symbol->owner() != currScope()) {10165          SayWithDecl(10166              name, *symbol, "'%s' must be local to this subprogram"_err_en_US);10167        } else {10168          ConvertToObjectEntity(*symbol);10169          if (auto *object{symbol->detailsIf<ObjectEntityDetails>()}) {10170            object->set_ignoreTKR(set);10171          } else {10172            SayWithDecl(name, *symbol, "'%s' must be an object"_err_en_US);10173          }10174        }10175      }10176    }10177  } else if (context().ShouldWarn(common::UsageWarning::IgnoredDirective)) {10178    Say(x.source, "Unrecognized compiler directive was ignored"_warn_en_US)10179        .set_usageWarning(common::UsageWarning::IgnoredDirective);10180  }10181}10182 10183bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) {10184  if (std::holds_alternative<common::Indirection<parser::CompilerDirective>>(10185          x.u)) {10186    // TODO: global directives10187    return true;10188  }10189  if (std::holds_alternative<10190          common::Indirection<parser::OpenACCRoutineConstruct>>(x.u)) {10191    ResolveAccParts(context(), x, &topScope_);10192    return false;10193  }10194  ProgramTree &root{ProgramTree::Build(x, context())};10195  SetScope(topScope_);10196  ResolveSpecificationParts(root);10197  FinishSpecificationParts(root);10198  ResolveExecutionParts(root);10199  FinishExecutionParts(root);10200  ResolveAccParts(context(), x, /*topScope=*/nullptr);10201  ResolveOmpParts(context(), x);10202  return false;10203}10204 10205template <typename A> std::set<SourceName> GetUses(const A &x) {10206  std::set<SourceName> uses;10207  if constexpr (!std::is_same_v<A, parser::CompilerDirective> &&10208      !std::is_same_v<A, parser::OpenACCRoutineConstruct>) {10209    const auto &spec{std::get<parser::SpecificationPart>(x.t)};10210    const auto &unitUses{std::get<10211        std::list<parser::Statement<common::Indirection<parser::UseStmt>>>>(10212        spec.t)};10213    for (const auto &u : unitUses) {10214      uses.insert(u.statement.value().moduleName.source);10215    }10216  }10217  return uses;10218}10219 10220bool ResolveNamesVisitor::Pre(const parser::Program &x) {10221  if (Scope * hermetic{context().currentHermeticModuleFileScope()}) {10222    // Processing either the dependent modules or first module of a10223    // hermetic module file; ensure that the hermetic module scope has10224    // its implicit rules map entry.10225    ImplicitRulesVisitor::BeginScope(*hermetic);10226  }10227  std::map<SourceName, const parser::ProgramUnit *> modules;10228  std::set<SourceName> uses;10229  bool disordered{false};10230  for (const auto &progUnit : x.v) {10231    if (const auto *indMod{10232            std::get_if<common::Indirection<parser::Module>>(&progUnit.u)}) {10233      const parser::Module &mod{indMod->value()};10234      const auto &moduleStmt{10235          std::get<parser::Statement<parser::ModuleStmt>>(mod.t)};10236      const SourceName &name{moduleStmt.statement.v.source};10237      if (auto iter{modules.find(name)}; iter != modules.end()) {10238        Say(name,10239            "Module '%s' appears multiple times in a compilation unit"_err_en_US)10240            .Attach(iter->first, "First definition of module"_en_US);10241        return true;10242      }10243      modules.emplace(name, &progUnit);10244      if (auto iter{uses.find(name)}; iter != uses.end()) {10245        if (context().ShouldWarn(common::LanguageFeature::MiscUseExtensions)) {10246          Say(name,10247              "A USE statement referencing module '%s' appears earlier in this compilation unit"_port_en_US,10248              name)10249              .Attach(*iter, "First USE of module"_en_US);10250        }10251        disordered = true;10252      }10253    }10254    for (SourceName used : common::visit(10255             [](const auto &indUnit) { return GetUses(indUnit.value()); },10256             progUnit.u)) {10257      uses.insert(used);10258    }10259  }10260  if (!disordered) {10261    return true;10262  }10263  // Process modules in topological order10264  std::vector<const parser::ProgramUnit *> moduleOrder;10265  while (!modules.empty()) {10266    bool ok;10267    for (const auto &pair : modules) {10268      const SourceName &name{pair.first};10269      const parser::ProgramUnit &progUnit{*pair.second};10270      const parser::Module &m{10271          std::get<common::Indirection<parser::Module>>(progUnit.u).value()};10272      ok = true;10273      for (const SourceName &use : GetUses(m)) {10274        if (modules.find(use) != modules.end()) {10275          ok = false;10276          break;10277        }10278      }10279      if (ok) {10280        moduleOrder.push_back(&progUnit);10281        modules.erase(name);10282        break;10283      }10284    }10285    if (!ok) {10286      Message *msg{nullptr};10287      for (const auto &pair : modules) {10288        if (msg) {10289          msg->Attach(pair.first, "Module in a cycle"_en_US);10290        } else {10291          msg = &Say(pair.first,10292              "Some modules in this compilation unit form one or more cycles of dependence"_err_en_US);10293        }10294      }10295      return false;10296    }10297  }10298  // Modules can be ordered.  Process them first, and then all of the other10299  // program units.10300  for (const parser::ProgramUnit *progUnit : moduleOrder) {10301    Walk(*progUnit);10302  }10303  for (const auto &progUnit : x.v) {10304    if (!std::get_if<common::Indirection<parser::Module>>(&progUnit.u)) {10305      Walk(progUnit);10306    }10307  }10308  return false;10309}10310 10311// References to procedures need to record that their symbols are known10312// to be procedures, so that they don't get converted to objects by default.10313class ExecutionPartCallSkimmer : public ExecutionPartSkimmerBase {10314public:10315  explicit ExecutionPartCallSkimmer(ResolveNamesVisitor &resolver)10316      : resolver_{resolver} {}10317 10318  void Walk(const parser::ExecutionPart &exec) {10319    parser::Walk(exec, *this);10320    EndWalk();10321  }10322 10323  using ExecutionPartSkimmerBase::Post;10324  using ExecutionPartSkimmerBase::Pre;10325 10326  void Post(const parser::FunctionReference &fr) {10327    NoteCall(Symbol::Flag::Function, fr.v, false);10328  }10329  void Post(const parser::CallStmt &cs) {10330    NoteCall(Symbol::Flag::Subroutine, cs.call, cs.chevrons.has_value());10331  }10332 10333private:10334  void NoteCall(10335      Symbol::Flag flag, const parser::Call &call, bool hasCUDAChevrons) {10336    auto &designator{std::get<parser::ProcedureDesignator>(call.t)};10337    if (const auto *name{std::get_if<parser::Name>(&designator.u)}) {10338      if (!IsHidden(name->source)) {10339        resolver_.NoteExecutablePartCall(flag, name->source, hasCUDAChevrons);10340      }10341    }10342  }10343 10344  ResolveNamesVisitor &resolver_;10345};10346 10347// Build the scope tree and resolve names in the specification parts of this10348// node and its children10349void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {10350  if (node.isSpecificationPartResolved()) {10351    return; // been here already10352  }10353  node.set_isSpecificationPartResolved();10354  if (!BeginScopeForNode(node)) {10355    return; // an error prevented scope from being created10356  }10357  Scope &scope{currScope()};10358  node.set_scope(scope);10359  AddSubpNames(node);10360  common::visit(10361      [&](const auto *x) {10362        if (x) {10363          Walk(*x);10364        }10365      },10366      node.stmt());10367  Walk(node.spec());10368  bool inDeviceSubprogram{false};10369  // If this is a function, convert result to an object. This is to prevent the10370  // result from being converted later to a function symbol if it is called10371  // inside the function.10372  // If the result is function pointer, then ConvertToObjectEntity will not10373  // convert the result to an object, and calling the symbol inside the function10374  // will result in calls to the result pointer.10375  // A function cannot be called recursively if RESULT was not used to define a10376  // distinct result name (15.6.2.2 point 4.).10377  if (Symbol * symbol{scope.symbol()}) {10378    if (auto *details{symbol->detailsIf<SubprogramDetails>()}) {10379      if (details->isFunction()) {10380        ConvertToObjectEntity(const_cast<Symbol &>(details->result()));10381      }10382      // Check the current procedure is a device procedure to apply implicit10383      // attribute at the end.10384      if (auto attrs{details->cudaSubprogramAttrs()}) {10385        if (*attrs == common::CUDASubprogramAttrs::Device ||10386            *attrs == common::CUDASubprogramAttrs::Global ||10387            *attrs == common::CUDASubprogramAttrs::Grid_Global) {10388          inDeviceSubprogram = true;10389        }10390      }10391    }10392  }10393  if (node.IsModule()) {10394    ApplyDefaultAccess();10395  }10396  for (auto &child : node.children()) {10397    ResolveSpecificationParts(child);10398  }10399  if (node.exec()) {10400    ExecutionPartCallSkimmer{*this}.Walk(*node.exec());10401    HandleImpliedAsynchronousInScope(node.exec()->v);10402  }10403  EndScopeForNode(node);10404  // Ensure that every object entity has a type.10405  bool inModule{node.GetKind() == ProgramTree::Kind::Module ||10406      node.GetKind() == ProgramTree::Kind::Submodule};10407  for (auto &pair : *node.scope()) {10408    Symbol &symbol{*pair.second};10409    if (inModule && symbol.attrs().test(Attr::EXTERNAL) && !IsPointer(symbol) &&10410        !symbol.test(Symbol::Flag::Function) &&10411        !symbol.test(Symbol::Flag::Subroutine)) {10412      // in a module, external proc without return type is subroutine10413      symbol.set(10414          symbol.GetType() ? Symbol::Flag::Function : Symbol::Flag::Subroutine);10415    }10416    ApplyImplicitRules(symbol);10417    // Apply CUDA implicit attributes if needed.10418    if (inDeviceSubprogram) {10419      SetImplicitCUDADevice(symbol);10420    }10421    // Main program local objects usually don't have an implied SAVE attribute,10422    // as one might think, but in the exceptional case of a derived type10423    // local object that contains a coarray, we have to mark it as an10424    // implied SAVE so that evaluate::IsSaved() will return true.10425    if (node.scope()->kind() == Scope::Kind::MainProgram) {10426      if (const auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {10427        if (const DeclTypeSpec * type{object->type()}) {10428          if (const DerivedTypeSpec * derived{type->AsDerived()}) {10429            if (!IsSaved(symbol) && FindCoarrayPotentialComponent(*derived)) {10430              SetImplicitAttr(symbol, Attr::SAVE);10431            }10432          }10433        }10434      }10435    }10436  }10437}10438 10439// Add SubprogramNameDetails symbols for module and internal subprograms and10440// their ENTRY statements.10441void ResolveNamesVisitor::AddSubpNames(ProgramTree &node) {10442  auto kind{10443      node.IsModule() ? SubprogramKind::Module : SubprogramKind::Internal};10444  for (auto &child : node.children()) {10445    auto &symbol{MakeSymbol(child.name(), SubprogramNameDetails{kind, child})};10446    if (child.HasModulePrefix()) {10447      SetExplicitAttr(symbol, Attr::MODULE);10448    }10449    if (child.bindingSpec()) {10450      SetExplicitAttr(symbol, Attr::BIND_C);10451    }10452    auto childKind{child.GetKind()};10453    if (childKind == ProgramTree::Kind::Function) {10454      symbol.set(Symbol::Flag::Function);10455    } else if (childKind == ProgramTree::Kind::Subroutine) {10456      symbol.set(Symbol::Flag::Subroutine);10457    } else {10458      continue; // make ENTRY symbols only where valid10459    }10460    for (const auto &entryStmt : child.entryStmts()) {10461      SubprogramNameDetails details{kind, child};10462      auto &symbol{10463          MakeSymbol(std::get<parser::Name>(entryStmt->t), std::move(details))};10464      symbol.set(child.GetSubpFlag());10465      if (child.HasModulePrefix()) {10466        SetExplicitAttr(symbol, Attr::MODULE);10467      }10468      if (child.bindingSpec()) {10469        SetExplicitAttr(symbol, Attr::BIND_C);10470      }10471    }10472  }10473  for (const auto &generic : node.genericSpecs()) {10474    if (const auto *name{std::get_if<parser::Name>(&generic->u)}) {10475      if (currScope().find(name->source) != currScope().end()) {10476        // If this scope has both a generic interface and a contained10477        // subprogram with the same name, create the generic's symbol10478        // now so that any other generics of the same name that are pulled10479        // into scope later via USE association will properly merge instead10480        // of raising a bogus error due a conflict with the subprogram.10481        CreateGeneric(*generic);10482      }10483    }10484  }10485}10486 10487// Push a new scope for this node or return false on error.10488bool ResolveNamesVisitor::BeginScopeForNode(const ProgramTree &node) {10489  switch (node.GetKind()) {10490    SWITCH_COVERS_ALL_CASES10491  case ProgramTree::Kind::Program:10492    PushScope(Scope::Kind::MainProgram,10493        &MakeSymbol(node.name(), MainProgramDetails{}));10494    return true;10495  case ProgramTree::Kind::Function:10496  case ProgramTree::Kind::Subroutine:10497    return BeginSubprogram(node.name(), node.GetSubpFlag(),10498        node.HasModulePrefix(), node.bindingSpec(), &node.entryStmts());10499  case ProgramTree::Kind::MpSubprogram:10500    return BeginMpSubprogram(node.name());10501  case ProgramTree::Kind::Module:10502    BeginModule(node.name(), false);10503    return true;10504  case ProgramTree::Kind::Submodule:10505    return BeginSubmodule(node.name(), node.GetParentId());10506  case ProgramTree::Kind::BlockData:10507    PushBlockDataScope(node.name());10508    return true;10509  }10510}10511 10512void ResolveNamesVisitor::EndScopeForNode(const ProgramTree &node) {10513  std::optional<parser::CharBlock> stmtSource;10514  const std::optional<parser::LanguageBindingSpec> *binding{nullptr};10515  common::visit(10516      common::visitors{10517          [&](const parser::Statement<parser::FunctionStmt> *stmt) {10518            if (stmt) {10519              stmtSource = stmt->source;10520              if (const auto &maybeSuffix{10521                      std::get<std::optional<parser::Suffix>>(10522                          stmt->statement.t)}) {10523                binding = &maybeSuffix->binding;10524              }10525            }10526          },10527          [&](const parser::Statement<parser::SubroutineStmt> *stmt) {10528            if (stmt) {10529              stmtSource = stmt->source;10530              binding = &std::get<std::optional<parser::LanguageBindingSpec>>(10531                  stmt->statement.t);10532            }10533          },10534          [](const auto *) {},10535      },10536      node.stmt());10537  EndSubprogram(stmtSource, binding, &node.entryStmts());10538}10539 10540// Some analyses and checks, such as the processing of initializers of10541// pointers, are deferred until all of the pertinent specification parts10542// have been visited.  This deferred processing enables the use of forward10543// references in these circumstances.10544// Data statement objects with implicit derived types are finally10545// resolved here.10546class DeferredCheckVisitor {10547public:10548  explicit DeferredCheckVisitor(ResolveNamesVisitor &resolver)10549      : resolver_{resolver} {}10550 10551  template <typename A> void Walk(const A &x) { parser::Walk(x, *this); }10552 10553  template <typename A> bool Pre(const A &) { return true; }10554  template <typename A> void Post(const A &) {}10555 10556  void Post(const parser::DerivedTypeStmt &x) {10557    const auto &name{std::get<parser::Name>(x.t)};10558    if (Symbol * symbol{name.symbol}) {10559      if (Scope * scope{symbol->scope()}) {10560        if (scope->IsDerivedType()) {10561          CHECK(outerScope_ == nullptr);10562          outerScope_ = &resolver_.currScope();10563          resolver_.SetScope(*scope);10564        }10565      }10566    }10567  }10568  void Post(const parser::EndTypeStmt &) {10569    if (outerScope_) {10570      resolver_.SetScope(*outerScope_);10571      outerScope_ = nullptr;10572    }10573  }10574 10575  void Post(const parser::ProcInterface &pi) {10576    if (const auto *name{std::get_if<parser::Name>(&pi.u)}) {10577      resolver_.CheckExplicitInterface(*name);10578    }10579  }10580  bool Pre(const parser::EntityDecl &decl) {10581    Init(std::get<parser::Name>(decl.t),10582        std::get<std::optional<parser::Initialization>>(decl.t));10583    return false;10584  }10585  bool Pre(const parser::ProcDecl &decl) {10586    if (const auto &init{10587            std::get<std::optional<parser::ProcPointerInit>>(decl.t)}) {10588      resolver_.PointerInitialization(std::get<parser::Name>(decl.t), *init);10589    }10590    return false;10591  }10592  void Post(const parser::TypeBoundProcedureStmt::WithInterface &tbps) {10593    resolver_.CheckExplicitInterface(tbps.interfaceName);10594  }10595  void Post(const parser::TypeBoundProcedureStmt::WithoutInterface &tbps) {10596    if (outerScope_) {10597      resolver_.CheckBindings(tbps);10598    }10599  }10600  bool Pre(const parser::DataStmtObject &) {10601    ++dataStmtObjectNesting_;10602    return true;10603  }10604  void Post(const parser::DataStmtObject &) { --dataStmtObjectNesting_; }10605  void Post(const parser::Designator &x) {10606    if (dataStmtObjectNesting_ > 0) {10607      resolver_.ResolveDesignator(x);10608    }10609  }10610 10611private:10612  void Init(const parser::Name &name,10613      const std::optional<parser::Initialization> &init) {10614    if (init) {10615      if (const auto *target{10616              std::get_if<parser::InitialDataTarget>(&init->u)}) {10617        resolver_.PointerInitialization(name, *target);10618      } else if (name.symbol) {10619        if (const auto *object{name.symbol->detailsIf<ObjectEntityDetails>()};10620            !object || !object->init()) {10621          if (const auto *expr{std::get_if<parser::ConstantExpr>(&init->u)}) {10622            resolver_.NonPointerInitialization(name, *expr);10623          } else {10624            // Don't check legacy DATA /initialization/ here.  Component10625            // initializations will have already been handled, and variable10626            // initializations need to be done in DATA checking so that10627            // EQUIVALENCE storage association can be handled.10628          }10629        }10630      }10631    }10632  }10633 10634  ResolveNamesVisitor &resolver_;10635  Scope *outerScope_{nullptr};10636  int dataStmtObjectNesting_{0};10637};10638 10639// Perform checks and completions that need to happen after all of10640// the specification parts but before any of the execution parts.10641void ResolveNamesVisitor::FinishSpecificationParts(const ProgramTree &node) {10642  if (!node.scope()) {10643    return; // error occurred creating scope10644  }10645  auto flagRestorer{common::ScopedSet(inSpecificationPart_, true)};10646  SetScope(*node.scope());10647  // The initializers of pointers and non-PARAMETER objects, the default10648  // initializers of components, and non-deferred type-bound procedure10649  // bindings have not yet been traversed.10650  // We do that now, when any forward references that appeared10651  // in those initializers will resolve to the right symbols without10652  // incurring spurious errors with IMPLICIT NONE or forward references10653  // to nested subprograms.10654  DeferredCheckVisitor{*this}.Walk(node.spec());10655  for (Scope &childScope : currScope().children()) {10656    if (childScope.IsParameterizedDerivedTypeInstantiation()) {10657      FinishDerivedTypeInstantiation(childScope);10658    }10659  }10660  for (const auto &child : node.children()) {10661    FinishSpecificationParts(child);10662  }10663}10664 10665void ResolveNamesVisitor::FinishExecutionParts(const ProgramTree &node) {10666  if (node.scope()) {10667    SetScope(*node.scope());10668    if (node.exec()) {10669      DeferredCheckVisitor{*this}.Walk(*node.exec());10670    }10671    for (const auto &child : node.children()) {10672      FinishExecutionParts(child);10673    }10674  }10675}10676 10677// Duplicate and fold component object pointer default initializer designators10678// using the actual type parameter values of each particular instantiation.10679// Validation is done later in declaration checking.10680void ResolveNamesVisitor::FinishDerivedTypeInstantiation(Scope &scope) {10681  CHECK(scope.IsDerivedType() && !scope.symbol());10682  if (DerivedTypeSpec * spec{scope.derivedTypeSpec()}) {10683    spec->Instantiate(currScope());10684    const Symbol &origTypeSymbol{spec->typeSymbol()};10685    if (const Scope * origTypeScope{origTypeSymbol.scope()}) {10686      CHECK(origTypeScope->IsDerivedType() &&10687          origTypeScope->symbol() == &origTypeSymbol);10688      auto &foldingContext{GetFoldingContext()};10689      auto restorer{foldingContext.WithPDTInstance(*spec)};10690      for (auto &pair : scope) {10691        Symbol &comp{*pair.second};10692        const Symbol &origComp{DEREF(FindInScope(*origTypeScope, comp.name()))};10693        if (IsPointer(comp)) {10694          if (auto *details{comp.detailsIf<ObjectEntityDetails>()}) {10695            auto origDetails{origComp.get<ObjectEntityDetails>()};10696            if (const MaybeExpr & init{origDetails.init()}) {10697              SomeExpr newInit{*init};10698              MaybeExpr folded{FoldExpr(std::move(newInit))};10699              details->set_init(std::move(folded));10700            }10701          }10702        }10703      }10704    }10705  }10706}10707 10708// Resolve names in the execution part of this node and its children10709void ResolveNamesVisitor::ResolveExecutionParts(const ProgramTree &node) {10710  if (!node.scope()) {10711    return; // error occurred creating scope10712  }10713  SetScope(*node.scope());10714  if (const auto *exec{node.exec()}) {10715    Walk(*exec);10716  }10717  FinishNamelists();10718  if (node.IsModule()) {10719    // A second final pass to catch new symbols added from implicitly10720    // typed names in NAMELIST groups or the specification parts of10721    // module subprograms.10722    ApplyDefaultAccess();10723  }10724  PopScope(); // converts unclassified entities into objects10725  for (const auto &child : node.children()) {10726    ResolveExecutionParts(child);10727  }10728}10729 10730void ResolveNamesVisitor::Post(const parser::Program &x) {10731  // ensure that all temps were deallocated10732  CHECK(!attrs_);10733  CHECK(!cudaDataAttr_);10734  CHECK(!GetDeclTypeSpec());10735}10736 10737// A singleton instance of the scope -> IMPLICIT rules mapping is10738// shared by all instances of ResolveNamesVisitor and accessed by this10739// pointer when the visitors (other than the top-level original) are10740// constructed.10741static ImplicitRulesMap *sharedImplicitRulesMap{nullptr};10742 10743bool ResolveNames(10744    SemanticsContext &context, const parser::Program &program, Scope &top) {10745  ImplicitRulesMap implicitRulesMap;10746  auto restorer{common::ScopedSet(sharedImplicitRulesMap, &implicitRulesMap)};10747  ResolveNamesVisitor{context, implicitRulesMap, top}.Walk(program);10748  return !context.AnyFatalError();10749}10750 10751// Processes a module (but not internal) function when it is referenced10752// in a specification expression in a sibling procedure.10753void ResolveSpecificationParts(10754    SemanticsContext &context, const Symbol &subprogram) {10755  auto originalLocation{context.location()};10756  ImplicitRulesMap implicitRulesMap;10757  bool localImplicitRulesMap{false};10758  if (!sharedImplicitRulesMap) {10759    sharedImplicitRulesMap = &implicitRulesMap;10760    localImplicitRulesMap = true;10761  }10762  ResolveNamesVisitor visitor{10763      context, *sharedImplicitRulesMap, context.globalScope()};10764  const auto &details{subprogram.get<SubprogramNameDetails>()};10765  ProgramTree &node{details.node()};10766  const Scope &moduleScope{subprogram.owner()};10767  if (localImplicitRulesMap) {10768    visitor.BeginScope(const_cast<Scope &>(moduleScope));10769  } else {10770    visitor.SetScope(const_cast<Scope &>(moduleScope));10771  }10772  visitor.ResolveSpecificationParts(node);10773  context.set_location(std::move(originalLocation));10774  if (localImplicitRulesMap) {10775    sharedImplicitRulesMap = nullptr;10776  }10777}10778 10779} // namespace Fortran::semantics10780