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

#include "resolve-directives.h"

#include "check-acc-structure.h"
#include "check-omp-structure.h"
#include "resolve-names-utils.h"
#include "flang/Common/idioms.h"
#include "flang/Evaluate/fold.h"
#include "flang/Evaluate/tools.h"
#include "flang/Evaluate/type.h"
#include "flang/Parser/parse-tree-visitor.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Parser/tools.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/openmp-modifiers.h"
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include <list>
#include <map>
#include <sstream>

template <typename T>
static Fortran::semantics::Scope *GetScope(
    Fortran::semantics::SemanticsContext &context, const T &x) {
  std::optional<Fortran::parser::CharBlock> source{GetLastSource(x)};
  return source ? &context.FindScope(*source) : nullptr;
}

namespace Fortran::semantics {

template <typename T> class DirectiveAttributeVisitor {
public:
  explicit DirectiveAttributeVisitor(SemanticsContext &context)
      : context_{context} {}

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

protected:
  struct DirContext {
    DirContext(const parser::CharBlock &source, T d, Scope &s)
        : directiveSource{source}, directive{d}, scope{s} {}
    parser::CharBlock directiveSource;
    T directive;
    Scope &scope;
    Symbol::Flag defaultDSA{Symbol::Flag::AccShared}; // TODOACC
    std::map<const Symbol *, Symbol::Flag> objectWithDSA;
    bool withinConstruct{false};
    std::int64_t associatedLoopLevel{0};
  };

  DirContext &GetContext() {
    CHECK(!dirContext_.empty());
    return dirContext_.back();
  }
  std::optional<DirContext> GetContextIf() {
    return dirContext_.empty()
        ? std::nullopt
        : std::make_optional<DirContext>(dirContext_.back());
  }
  void PushContext(const parser::CharBlock &source, T dir, Scope &scope) {
    dirContext_.emplace_back(source, dir, scope);
  }
  void PushContext(const parser::CharBlock &source, T dir) {
    dirContext_.emplace_back(source, dir, context_.FindScope(source));
  }
  void PopContext() { dirContext_.pop_back(); }
  void SetContextDirectiveSource(parser::CharBlock &dir) {
    GetContext().directiveSource = dir;
  }
  Scope &currScope() { return GetContext().scope; }
  void SetContextDefaultDSA(Symbol::Flag flag) {
    GetContext().defaultDSA = flag;
  }
  void AddToContextObjectWithDSA(
      const Symbol &symbol, Symbol::Flag flag, DirContext &context) {
    context.objectWithDSA.emplace(&symbol, flag);
  }
  void AddToContextObjectWithDSA(const Symbol &symbol, Symbol::Flag flag) {
    AddToContextObjectWithDSA(symbol, flag, GetContext());
  }
  bool IsObjectWithDSA(const Symbol &symbol) {
    auto it{GetContext().objectWithDSA.find(&symbol)};
    return it != GetContext().objectWithDSA.end();
  }
  void SetContextAssociatedLoopLevel(std::int64_t level) {
    GetContext().associatedLoopLevel = level;
  }
  Symbol &MakeAssocSymbol(
      const SourceName &name, const Symbol &prev, Scope &scope) {
    const auto pair{scope.try_emplace(name, Attrs{}, HostAssocDetails{prev})};
    return *pair.first->second;
  }
  Symbol &MakeAssocSymbol(const SourceName &name, const Symbol &prev) {
    return MakeAssocSymbol(name, prev, currScope());
  }
  void AddDataSharingAttributeObject(SymbolRef object) {
    dataSharingAttributeObjects_.insert(object);
  }
  void ClearDataSharingAttributeObjects() {
    dataSharingAttributeObjects_.clear();
  }
  bool HasDataSharingAttributeObject(const Symbol &);
  const parser::Name *GetLoopIndex(const parser::DoConstruct &);
  const parser::DoConstruct *GetDoConstructIf(
      const parser::ExecutionPartConstruct &);
  Symbol *DeclareNewPrivateAccessEntity(const Symbol &, Symbol::Flag, Scope &);
  Symbol *DeclarePrivateAccessEntity(
      const parser::Name &, Symbol::Flag, Scope &);
  Symbol *DeclarePrivateAccessEntity(Symbol &, Symbol::Flag, Scope &);
  Symbol *DeclareOrMarkOtherAccessEntity(const parser::Name &, Symbol::Flag);

  UnorderedSymbolSet dataSharingAttributeObjects_; // on one directive
  SemanticsContext &context_;
  std::vector<DirContext> dirContext_; // used as a stack
};

class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
public:
  explicit AccAttributeVisitor(SemanticsContext &context, Scope *topScope)
      : DirectiveAttributeVisitor(context), topScope_(topScope) {}

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

  bool Pre(const parser::OpenACCBlockConstruct &);
  void Post(const parser::OpenACCBlockConstruct &) { PopContext(); }
  bool Pre(const parser::OpenACCCombinedConstruct &);
  void Post(const parser::OpenACCCombinedConstruct &) { PopContext(); }

  bool Pre(const parser::OpenACCDeclarativeConstruct &);
  void Post(const parser::OpenACCDeclarativeConstruct &) { PopContext(); }

  void Post(const parser::AccDeclarativeDirective &) {
    GetContext().withinConstruct = true;
  }

  bool Pre(const parser::OpenACCRoutineConstruct &);
  bool Pre(const parser::AccBindClause &);
  void Post(const parser::OpenACCStandaloneDeclarativeConstruct &);

  void Post(const parser::AccBeginBlockDirective &) {
    GetContext().withinConstruct = true;
  }

  bool Pre(const parser::OpenACCLoopConstruct &);
  void Post(const parser::OpenACCLoopConstruct &) { PopContext(); }
  void Post(const parser::AccLoopDirective &) {
    GetContext().withinConstruct = true;
  }

  bool Pre(const parser::OpenACCStandaloneConstruct &);
  void Post(const parser::OpenACCStandaloneConstruct &) { PopContext(); }
  void Post(const parser::AccStandaloneDirective &) {
    GetContext().withinConstruct = true;
  }

  bool Pre(const parser::OpenACCCacheConstruct &);
  void Post(const parser::OpenACCCacheConstruct &) { PopContext(); }

  void Post(const parser::AccDefaultClause &);

  bool Pre(const parser::AccClause::Attach &);
  bool Pre(const parser::AccClause::Detach &);

  bool Pre(const parser::AccClause::Copy &x) {
    ResolveAccObjectList(x.v, Symbol::Flag::AccCopy);
    return false;
  }

  bool Pre(const parser::AccClause::Create &x) {
    const auto &objectList{std::get<parser::AccObjectList>(x.v.t)};
    ResolveAccObjectList(objectList, Symbol::Flag::AccCreate);
    return false;
  }

  bool Pre(const parser::AccClause::Copyin &x) {
    const auto &objectList{std::get<parser::AccObjectList>(x.v.t)};
    const auto &modifier{
        std::get<std::optional<parser::AccDataModifier>>(x.v.t)};
    if (modifier &&
        (*modifier).v == parser::AccDataModifier::Modifier::ReadOnly) {
      ResolveAccObjectList(objectList, Symbol::Flag::AccCopyInReadOnly);
    } else {
      ResolveAccObjectList(objectList, Symbol::Flag::AccCopyIn);
    }
    return false;
  }

  bool Pre(const parser::AccClause::Copyout &x) {
    const auto &objectList{std::get<parser::AccObjectList>(x.v.t)};
    ResolveAccObjectList(objectList, Symbol::Flag::AccCopyOut);
    return false;
  }

  bool Pre(const parser::AccClause::Present &x) {
    ResolveAccObjectList(x.v, Symbol::Flag::AccPresent);
    return false;
  }
  bool Pre(const parser::AccClause::Private &x) {
    ResolveAccObjectList(x.v, Symbol::Flag::AccPrivate);
    return false;
  }
  bool Pre(const parser::AccClause::Firstprivate &x) {
    ResolveAccObjectList(x.v, Symbol::Flag::AccFirstPrivate);
    return false;
  }

  bool Pre(const parser::AccClause::Device &x) {
    ResolveAccObjectList(x.v, Symbol::Flag::AccDevice);
    return false;
  }

  bool Pre(const parser::AccClause::DeviceResident &x) {
    ResolveAccObjectList(x.v, Symbol::Flag::AccDeviceResident);
    return false;
  }

  bool Pre(const parser::AccClause::Deviceptr &x) {
    ResolveAccObjectList(x.v, Symbol::Flag::AccDevicePtr);
    return false;
  }

  bool Pre(const parser::AccClause::Link &x) {
    ResolveAccObjectList(x.v, Symbol::Flag::AccLink);
    return false;
  }

  bool Pre(const parser::AccClause::Host &x) {
    ResolveAccObjectList(x.v, Symbol::Flag::AccHost);
    return false;
  }

  bool Pre(const parser::AccClause::Self &x) {
    const std::optional<parser::AccSelfClause> &accSelfClause = x.v;
    if (accSelfClause &&
        std::holds_alternative<parser::AccObjectList>((*accSelfClause).u)) {
      const auto &accObjectList =
          std::get<parser::AccObjectList>((*accSelfClause).u);
      ResolveAccObjectList(accObjectList, Symbol::Flag::AccSelf);
    }
    return false;
  }

  void Post(const parser::Name &);

private:
  std::int64_t GetAssociatedLoopLevelFromClauses(const parser::AccClauseList &);

  Symbol::Flags dataSharingAttributeFlags{Symbol::Flag::AccShared,
      Symbol::Flag::AccPrivate, Symbol::Flag::AccFirstPrivate,
      Symbol::Flag::AccReduction};

  Symbol::Flags dataMappingAttributeFlags{Symbol::Flag::AccCreate,
      Symbol::Flag::AccCopyIn, Symbol::Flag::AccCopyOut,
      Symbol::Flag::AccDelete, Symbol::Flag::AccPresent};

  Symbol::Flags accDataMvtFlags{
      Symbol::Flag::AccDevice, Symbol::Flag::AccHost, Symbol::Flag::AccSelf};

  Symbol::Flags accFlagsRequireMark{Symbol::Flag::AccCreate,
      Symbol::Flag::AccCopyIn, Symbol::Flag::AccCopyInReadOnly,
      Symbol::Flag::AccCopy, Symbol::Flag::AccCopyOut,
      Symbol::Flag::AccDevicePtr, Symbol::Flag::AccDeviceResident,
      Symbol::Flag::AccLink, Symbol::Flag::AccPresent};

  void CheckAssociatedLoop(const parser::DoConstruct &);
  void ResolveAccObjectList(const parser::AccObjectList &, Symbol::Flag);
  void ResolveAccObject(const parser::AccObject &, Symbol::Flag);
  Symbol *ResolveAcc(const parser::Name &, Symbol::Flag, Scope &);
  Symbol *ResolveAcc(Symbol &, Symbol::Flag, Scope &);
  Symbol *ResolveName(const parser::Name &, bool parentScope = false);
  Symbol *ResolveFctName(const parser::Name &);
  Symbol *ResolveAccCommonBlockName(const parser::Name *);
  Symbol *DeclareOrMarkOtherAccessEntity(const parser::Name &, Symbol::Flag);
  Symbol *DeclareOrMarkOtherAccessEntity(Symbol &, Symbol::Flag);
  void CheckMultipleAppearances(
      const parser::Name &, const Symbol &, Symbol::Flag);
  void AllowOnlyArrayAndSubArray(const parser::AccObjectList &objectList);
  void DoNotAllowAssumedSizedArray(const parser::AccObjectList &objectList);
  void AllowOnlyVariable(const parser::AccObject &object);
  void EnsureAllocatableOrPointer(
      const llvm::acc::Clause clause, const parser::AccObjectList &objectList);
  void AddRoutineInfoToSymbol(
      Symbol &, const parser::OpenACCRoutineConstruct &);
  Scope *topScope_;
};

// Data-sharing and Data-mapping attributes for data-refs in OpenMP construct
class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
public:
  explicit OmpAttributeVisitor(SemanticsContext &context)
      : DirectiveAttributeVisitor(context) {}

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

  template <typename A> bool Pre(const parser::Statement<A> &statement) {
    currentStatementSource_ = statement.source;
    // Keep track of the labels in all the labelled statements
    if (statement.label) {
      auto label{statement.label.value()};
      // Get the context to check if the labelled statement is in an
      // enclosing OpenMP construct
      std::optional<DirContext> thisContext{GetContextIf()};
      targetLabels_.emplace(
          label, std::make_pair(currentStatementSource_, thisContext));
      // Check if a statement that causes a jump to the 'label'
      // has already been encountered
      auto range{sourceLabels_.equal_range(label)};
      for (auto it{range.first}; it != range.second; ++it) {
        // Check if both the statement with 'label' and the statement that
        // causes a jump to the 'label' are in the same scope
        CheckLabelContext(it->second.first, currentStatementSource_,
            it->second.second, thisContext);
      }
    }
    return true;
  }

  bool Pre(const parser::InternalSubprogram &) {
    // Clear the labels being tracked in the previous scope
    ClearLabels();
    return true;
  }

  bool Pre(const parser::ModuleSubprogram &) {
    // Clear the labels being tracked in the previous scope
    ClearLabels();
    return true;
  }

  bool Pre(const parser::StmtFunctionStmt &x) {
    const auto &parsedExpr{std::get<parser::Scalar<parser::Expr>>(x.t)};
    if (const auto *expr{GetExpr(context_, parsedExpr)}) {
      for (const Symbol &symbol : evaluate::CollectSymbols(*expr)) {
        if (!IsStmtFunctionDummy(symbol)) {
          stmtFunctionExprSymbols_.insert(symbol.GetUltimate());
        }
      }
    }
    return true;
  }

  bool Pre(const parser::OmpDirectiveSpecification &x) {
    PushContext(x.source, std::get<llvm::omp::Directive>(x.t));
    return true;
  }
  void Post(const parser::OmpDirectiveSpecification &) { PopContext(); }
  bool Pre(const parser::OmpMetadirectiveDirective &x) {
    PushContext(x.source, llvm::omp::Directive::OMPD_metadirective);
    return true;
  }
  void Post(const parser::OmpMetadirectiveDirective &) { PopContext(); }

  bool Pre(const parser::OpenMPBlockConstruct &);
  void Post(const parser::OpenMPBlockConstruct &);

  void Post(const parser::OmpBeginBlockDirective &) {
    GetContext().withinConstruct = true;
  }

  bool Pre(const parser::OpenMPSimpleStandaloneConstruct &);
  void Post(const parser::OpenMPSimpleStandaloneConstruct &) { PopContext(); }

  bool Pre(const parser::OpenMPLoopConstruct &);
  void Post(const parser::OpenMPLoopConstruct &) { PopContext(); }
  void Post(const parser::OmpBeginLoopDirective &) {
    GetContext().withinConstruct = true;
  }
  bool Pre(const parser::DoConstruct &);

  bool Pre(const parser::OpenMPSectionsConstruct &);
  void Post(const parser::OpenMPSectionsConstruct &) { PopContext(); }

  bool Pre(const parser::OpenMPCriticalConstruct &critical);
  void Post(const parser::OpenMPCriticalConstruct &) { PopContext(); }

  bool Pre(const parser::OpenMPDeclareSimdConstruct &x) {
    PushContext(x.source, llvm::omp::Directive::OMPD_declare_simd);
    const auto &name{std::get<std::optional<parser::Name>>(x.t)};
    if (name) {
      ResolveOmpName(*name, Symbol::Flag::OmpDeclareSimd);
    }
    return true;
  }
  void Post(const parser::OpenMPDeclareSimdConstruct &) { PopContext(); }

  bool Pre(const parser::OpenMPDepobjConstruct &x) {
    PushContext(x.source, llvm::omp::Directive::OMPD_depobj);
    auto &object{std::get<parser::OmpObject>(x.t)};
    ResolveOmpObject(object, Symbol::Flag::OmpDependObject);
    return true;
  }
  void Post(const parser::OpenMPDepobjConstruct &) { PopContext(); }

  bool Pre(const parser::OpenMPRequiresConstruct &x) {
    using Flags = WithOmpDeclarative::RequiresFlags;
    using Requires = WithOmpDeclarative::RequiresFlag;
    PushContext(x.source, llvm::omp::Directive::OMPD_requires);

    // Gather information from the clauses.
    Flags flags;
    std::optional<common::OmpAtomicDefaultMemOrderType> memOrder;
    for (const auto &clause : std::get<parser::OmpClauseList>(x.t).v) {
      flags |= common::visit(
          common::visitors{
              [&memOrder](
                  const parser::OmpClause::AtomicDefaultMemOrder &atomic) {
                memOrder = atomic.v.v;
                return Flags{};
              },
              [](const parser::OmpClause::ReverseOffload &) {
                return Flags{Requires::ReverseOffload};
              },
              [](const parser::OmpClause::UnifiedAddress &) {
                return Flags{Requires::UnifiedAddress};
              },
              [](const parser::OmpClause::UnifiedSharedMemory &) {
                return Flags{Requires::UnifiedSharedMemory};
              },
              [](const parser::OmpClause::DynamicAllocators &) {
                return Flags{Requires::DynamicAllocators};
              },
              [](const auto &) { return Flags{}; }},
          clause.u);
    }
    // Merge clauses into parents' symbols details.
    AddOmpRequiresToScope(currScope(), flags, memOrder);
    return true;
  }
  void Post(const parser::OpenMPRequiresConstruct &) { PopContext(); }

  bool Pre(const parser::OpenMPDeclareTargetConstruct &);
  void Post(const parser::OpenMPDeclareTargetConstruct &) { PopContext(); }

  bool Pre(const parser::OpenMPDeclareMapperConstruct &);
  void Post(const parser::OpenMPDeclareMapperConstruct &) { PopContext(); }

  bool Pre(const parser::OpenMPThreadprivate &);
  void Post(const parser::OpenMPThreadprivate &) { PopContext(); }

  bool Pre(const parser::OpenMPDeclarativeAllocate &);
  void Post(const parser::OpenMPDeclarativeAllocate &) { PopContext(); }

  bool Pre(const parser::OpenMPDispatchConstruct &);
  void Post(const parser::OpenMPDispatchConstruct &) { PopContext(); }

  bool Pre(const parser::OpenMPExecutableAllocate &);
  void Post(const parser::OpenMPExecutableAllocate &);

  bool Pre(const parser::OpenMPAllocatorsConstruct &);
  void Post(const parser::OpenMPAllocatorsConstruct &);

  void Post(const parser::OmpObjectList &x) {
    // The objects from OMP clauses should have already been resolved,
    // except common blocks (the ResolveNamesVisitor does not visit
    // parser::Name, those are dealt with as members of other structures).
    // Iterate over elements of x, and resolve any common blocks that
    // are still unresolved.
    for (const parser::OmpObject &obj : x.v) {
      auto *name{std::get_if<parser::Name>(&obj.u)};
      if (name && !name->symbol) {
        Resolve(*name, currScope().MakeCommonBlock(name->source));
      }
    }
  }

  // 2.15.3 Data-Sharing Attribute Clauses
  bool Pre(const parser::OmpClause::Inclusive &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpInclusiveScan);
    return false;
  }
  bool Pre(const parser::OmpClause::Exclusive &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpExclusiveScan);
    return false;
  }
  void Post(const parser::OmpDefaultClause &);
  bool Pre(const parser::OmpClause::Shared &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpShared);
    return false;
  }
  bool Pre(const parser::OmpClause::Private &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpPrivate);
    return false;
  }
  bool Pre(const parser::OmpAllocateClause &x) {
    const auto &objectList{std::get<parser::OmpObjectList>(x.t)};
    ResolveOmpObjectList(objectList, Symbol::Flag::OmpAllocate);
    return false;
  }
  bool Pre(const parser::OmpClause::Firstprivate &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpFirstPrivate);
    return false;
  }
  bool Pre(const parser::OmpClause::Lastprivate &x) {
    const auto &objList{std::get<parser::OmpObjectList>(x.v.t)};
    ResolveOmpObjectList(objList, Symbol::Flag::OmpLastPrivate);
    return false;
  }
  bool Pre(const parser::OmpClause::Copyin &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpCopyIn);
    return false;
  }
  bool Pre(const parser::OmpClause::Copyprivate &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpCopyPrivate);
    return false;
  }
  bool Pre(const parser::OmpLinearClause &x) {
    auto &objects{std::get<parser::OmpObjectList>(x.t)};
    ResolveOmpObjectList(objects, Symbol::Flag::OmpLinear);
    return false;
  }

  bool Pre(const parser::OmpClause::Reduction &x) {
    const auto &objList{std::get<parser::OmpObjectList>(x.v.t)};
    ResolveOmpObjectList(objList, Symbol::Flag::OmpReduction);

    if (auto &modifiers{OmpGetModifiers(x.v)}) {
      auto createDummyProcSymbol = [&](const parser::Name *name) {
        // If name resolution failed, create a dummy symbol
        const auto namePair{currScope().try_emplace(
            name->source, Attrs{}, ProcEntityDetails{})};
        auto &newSymbol{*namePair.first->second};
        if (context_.intrinsics().IsIntrinsic(name->ToString())) {
          newSymbol.attrs().set(Attr::INTRINSIC);
        }
        name->symbol = &newSymbol;
      };

      for (auto &mod : *modifiers) {
        if (!std::holds_alternative<parser::OmpReductionIdentifier>(mod.u)) {
          continue;
        }
        auto &opr{std::get<parser::OmpReductionIdentifier>(mod.u)};
        if (auto *procD{parser::Unwrap<parser::ProcedureDesignator>(opr.u)}) {
          if (auto *name{parser::Unwrap<parser::Name>(procD->u)}) {
            if (!name->symbol) {
              if (!ResolveName(name)) {
                createDummyProcSymbol(name);
              }
            }
          }
          if (auto *procRef{
                  parser::Unwrap<parser::ProcComponentRef>(procD->u)}) {
            if (!procRef->v.thing.component.symbol) {
              if (!ResolveName(&procRef->v.thing.component)) {
                createDummyProcSymbol(&procRef->v.thing.component);
              }
            }
          }
        }
      }
      using ReductionModifier = parser::OmpReductionModifier;
      if (auto *maybeModifier{
              OmpGetUniqueModifier<ReductionModifier>(modifiers)}) {
        if (maybeModifier->v == ReductionModifier::Value::Inscan) {
          ResolveOmpObjectList(objList, Symbol::Flag::OmpInScanReduction);
        }
      }
    }
    return false;
  }

  bool Pre(const parser::OmpAlignedClause &x) {
    const auto &alignedNameList{std::get<parser::OmpObjectList>(x.t)};
    ResolveOmpObjectList(alignedNameList, Symbol::Flag::OmpAligned);
    return false;
  }

  bool Pre(const parser::OmpClause::Nontemporal &x) {
    const auto &nontemporalNameList{x.v};
    ResolveOmpNameList(nontemporalNameList, Symbol::Flag::OmpNontemporal);
    return false;
  }

  void Post(const parser::OmpIteration &x) {
    if (const auto &name{std::get<parser::Name>(x.t)}; !name.symbol) {
      auto *symbol{currScope().FindSymbol(name.source)};
      if (!symbol) {
        // OmpIteration must use an existing object. If there isn't one,
        // create a fake one and flag an error later.
        symbol = &currScope().MakeSymbol(
            name.source, Attrs{}, EntityDetails(/*isDummy=*/true));
      }
      Resolve(name, symbol);
    }
  }

  bool Pre(const parser::OmpClause::UseDevicePtr &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpUseDevicePtr);
    return false;
  }

  bool Pre(const parser::OmpClause::UseDeviceAddr &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpUseDeviceAddr);
    return false;
  }

  bool Pre(const parser::OmpClause::IsDevicePtr &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpIsDevicePtr);
    return false;
  }

  bool Pre(const parser::OmpClause::HasDeviceAddr &x) {
    ResolveOmpObjectList(x.v, Symbol::Flag::OmpHasDeviceAddr);
    return false;
  }

  void Post(const parser::Name &);

  // Keep track of labels in the statements that causes jumps to target labels
  void Post(const parser::GotoStmt &gotoStmt) { CheckSourceLabel(gotoStmt.v); }
  void Post(const parser::ComputedGotoStmt &computedGotoStmt) {
    for (auto &label : std::get<std::list<parser::Label>>(computedGotoStmt.t)) {
      CheckSourceLabel(label);
    }
  }
  void Post(const parser::ArithmeticIfStmt &arithmeticIfStmt) {
    CheckSourceLabel(std::get<1>(arithmeticIfStmt.t));
    CheckSourceLabel(std::get<2>(arithmeticIfStmt.t));
    CheckSourceLabel(std::get<3>(arithmeticIfStmt.t));
  }
  void Post(const parser::AssignedGotoStmt &assignedGotoStmt) {
    for (auto &label : std::get<std::list<parser::Label>>(assignedGotoStmt.t)) {
      CheckSourceLabel(label);
    }
  }
  void Post(const parser::AltReturnSpec &altReturnSpec) {
    CheckSourceLabel(altReturnSpec.v);
  }
  void Post(const parser::ErrLabel &errLabel) { CheckSourceLabel(errLabel.v); }
  void Post(const parser::EndLabel &endLabel) { CheckSourceLabel(endLabel.v); }
  void Post(const parser::EorLabel &eorLabel) { CheckSourceLabel(eorLabel.v); }

  void Post(const parser::OmpMapClause &x) {
    Symbol::Flag ompFlag = Symbol::Flag::OmpMapToFrom;
    auto &mods{OmpGetModifiers(x)};
    if (auto *mapType{OmpGetUniqueModifier<parser::OmpMapType>(mods)}) {
      switch (mapType->v) {
      case parser::OmpMapType::Value::To:
        ompFlag = Symbol::Flag::OmpMapTo;
        break;
      case parser::OmpMapType::Value::From:
        ompFlag = Symbol::Flag::OmpMapFrom;
        break;
      case parser::OmpMapType::Value::Tofrom:
        ompFlag = Symbol::Flag::OmpMapToFrom;
        break;
      case parser::OmpMapType::Value::Alloc:
        ompFlag = Symbol::Flag::OmpMapAlloc;
        break;
      case parser::OmpMapType::Value::Release:
        ompFlag = Symbol::Flag::OmpMapRelease;
        break;
      case parser::OmpMapType::Value::Delete:
        ompFlag = Symbol::Flag::OmpMapDelete;
        break;
      }
    }
    const auto &ompObjList{std::get<parser::OmpObjectList>(x.t)};
    for (const auto &ompObj : ompObjList.v) {
      common::visit(
          common::visitors{
              [&](const parser::Designator &designator) {
                if (const auto *name{
                        semantics::getDesignatorNameIfDataRef(designator)}) {
                  if (name->symbol) {
                    name->symbol->set(ompFlag);
                    AddToContextObjectWithDSA(*name->symbol, ompFlag);
                  }
                  if (name->symbol &&
                      semantics::IsAssumedSizeArray(*name->symbol)) {
                    context_.Say(designator.source,
                        "Assumed-size whole arrays may not appear on the %s "
                        "clause"_err_en_US,
                        "MAP");
                  }
                }
              },
              [&](const auto &name) {},
          },
          ompObj.u);

      ResolveOmpObject(ompObj, ompFlag);
    }
  }

  const parser::OmpClause *associatedClause{nullptr};
  void SetAssociatedClause(const parser::OmpClause &c) {
    associatedClause = &c;
  }
  const parser::OmpClause *GetAssociatedClause() { return associatedClause; }

private:
  std::int64_t GetAssociatedLoopLevelFromClauses(const parser::OmpClauseList &);

  Symbol::Flags dataSharingAttributeFlags{Symbol::Flag::OmpShared,
      Symbol::Flag::OmpPrivate, Symbol::Flag::OmpFirstPrivate,
      Symbol::Flag::OmpLastPrivate, Symbol::Flag::OmpReduction,
      Symbol::Flag::OmpLinear};

  Symbol::Flags privateDataSharingAttributeFlags{Symbol::Flag::OmpPrivate,
      Symbol::Flag::OmpFirstPrivate, Symbol::Flag::OmpLastPrivate};

  Symbol::Flags ompFlagsRequireNewSymbol{Symbol::Flag::OmpPrivate,
      Symbol::Flag::OmpLinear, Symbol::Flag::OmpFirstPrivate,
      Symbol::Flag::OmpLastPrivate, Symbol::Flag::OmpReduction,
      Symbol::Flag::OmpCriticalLock, Symbol::Flag::OmpCopyIn,
      Symbol::Flag::OmpUseDevicePtr, Symbol::Flag::OmpUseDeviceAddr,
      Symbol::Flag::OmpIsDevicePtr, Symbol::Flag::OmpHasDeviceAddr};

  Symbol::Flags ompFlagsRequireMark{Symbol::Flag::OmpThreadprivate,
      Symbol::Flag::OmpDeclareTarget, Symbol::Flag::OmpExclusiveScan,
      Symbol::Flag::OmpInclusiveScan, Symbol::Flag::OmpInScanReduction};

  Symbol::Flags dataCopyingAttributeFlags{
      Symbol::Flag::OmpCopyIn, Symbol::Flag::OmpCopyPrivate};

  std::vector<const parser::Name *> allocateNames_; // on one directive
  UnorderedSymbolSet privateDataSharingAttributeObjects_; // on one directive
  UnorderedSymbolSet stmtFunctionExprSymbols_;
  std::multimap<const parser::Label,
      std::pair<parser::CharBlock, std::optional<DirContext>>>
      sourceLabels_;
  std::map<const parser::Label,
      std::pair<parser::CharBlock, std::optional<DirContext>>>
      targetLabels_;
  parser::CharBlock currentStatementSource_;

  void AddAllocateName(const parser::Name *&object) {
    allocateNames_.push_back(object);
  }
  void ClearAllocateNames() { allocateNames_.clear(); }

  void AddPrivateDataSharingAttributeObjects(SymbolRef object) {
    privateDataSharingAttributeObjects_.insert(object);
  }
  void ClearPrivateDataSharingAttributeObjects() {
    privateDataSharingAttributeObjects_.clear();
  }

  // Predetermined DSA rules
  void PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
      const parser::OpenMPLoopConstruct &);
  void ResolveSeqLoopIndexInParallelOrTaskConstruct(const parser::Name &);

  bool IsNestedInDirective(llvm::omp::Directive directive);
  void ResolveOmpObjectList(const parser::OmpObjectList &, Symbol::Flag);
  void ResolveOmpObject(const parser::OmpObject &, Symbol::Flag);
  Symbol *ResolveOmp(const parser::Name &, Symbol::Flag, Scope &);
  Symbol *ResolveOmp(Symbol &, Symbol::Flag, Scope &);
  Symbol *ResolveOmpCommonBlockName(const parser::Name *);
  void ResolveOmpNameList(const std::list<parser::Name> &, Symbol::Flag);
  void ResolveOmpName(const parser::Name &, Symbol::Flag);
  Symbol *ResolveName(const parser::Name *);
  Symbol *ResolveOmpObjectScope(const parser::Name *);
  Symbol *DeclareOrMarkOtherAccessEntity(const parser::Name &, Symbol::Flag);
  Symbol *DeclareOrMarkOtherAccessEntity(Symbol &, Symbol::Flag);
  void CheckMultipleAppearances(
      const parser::Name &, const Symbol &, Symbol::Flag);

  void CheckDataCopyingClause(
      const parser::Name &, const Symbol &, Symbol::Flag);
  void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause *clause);
  void CheckObjectIsPrivatizable(
      const parser::Name &, const Symbol &, Symbol::Flag);
  void CheckSourceLabel(const parser::Label &);
  void CheckLabelContext(const parser::CharBlock, const parser::CharBlock,
      std::optional<DirContext>, std::optional<DirContext>);
  void ClearLabels() {
    sourceLabels_.clear();
    targetLabels_.clear();
  };
  void CheckAllNamesInAllocateStmt(const parser::CharBlock &source,
      const parser::OmpObjectList &ompObjectList,
      const parser::AllocateStmt &allocate);
  void CheckNameInAllocateStmt(const parser::CharBlock &source,
      const parser::Name &ompObject, const parser::AllocateStmt &allocate);

  std::int64_t ordCollapseLevel{0};

  void AddOmpRequiresToScope(Scope &, WithOmpDeclarative::RequiresFlags,
      std::optional<common::OmpAtomicDefaultMemOrderType>);
  void IssueNonConformanceWarning(
      llvm::omp::Directive D, parser::CharBlock source);

  void CreateImplicitSymbols(
      const Symbol *symbol, std::optional<Symbol::Flag> setFlag = std::nullopt);
};

template <typename T>
bool DirectiveAttributeVisitor<T>::HasDataSharingAttributeObject(
    const Symbol &object) {
  auto it{dataSharingAttributeObjects_.find(object)};
  return it != dataSharingAttributeObjects_.end();
}

template <typename T>
const parser::Name *DirectiveAttributeVisitor<T>::GetLoopIndex(
    const parser::DoConstruct &x) {
  using Bounds = parser::LoopControl::Bounds;
  if (x.GetLoopControl()) {
    if (const Bounds * b{std::get_if<Bounds>(&x.GetLoopControl()->u)}) {
      return &b->name.thing;
    } else {
      return nullptr;
    }
  } else {
    context_
        .Say(std::get<parser::Statement<parser::NonLabelDoStmt>>(x.t).source,
            "Loop control is not present in the DO LOOP"_err_en_US)
        .Attach(GetContext().directiveSource,
            "associated with the enclosing LOOP construct"_en_US);
    return nullptr;
  }
}

template <typename T>
const parser::DoConstruct *DirectiveAttributeVisitor<T>::GetDoConstructIf(
    const parser::ExecutionPartConstruct &x) {
  return parser::Unwrap<parser::DoConstruct>(x);
}

template <typename T>
Symbol *DirectiveAttributeVisitor<T>::DeclareNewPrivateAccessEntity(
    const Symbol &object, Symbol::Flag flag, Scope &scope) {
  assert(object.owner() != currScope());
  auto &symbol{MakeAssocSymbol(object.name(), object, scope)};
  symbol.set(flag);
  if (flag == Symbol::Flag::OmpCopyIn) {
    // The symbol in copyin clause must be threadprivate entity.
    symbol.set(Symbol::Flag::OmpThreadprivate);
  }
  return &symbol;
}

template <typename T>
Symbol *DirectiveAttributeVisitor<T>::DeclarePrivateAccessEntity(
    const parser::Name &name, Symbol::Flag flag, Scope &scope) {
  if (!name.symbol) {
    return nullptr; // not resolved by Name Resolution step, do nothing
  }
  name.symbol = DeclarePrivateAccessEntity(*name.symbol, flag, scope);
  return name.symbol;
}

template <typename T>
Symbol *DirectiveAttributeVisitor<T>::DeclarePrivateAccessEntity(
    Symbol &object, Symbol::Flag flag, Scope &scope) {
  if (object.owner() != currScope()) {
    return DeclareNewPrivateAccessEntity(object, flag, scope);
  } else {
    object.set(flag);
    return &object;
  }
}

bool AccAttributeVisitor::Pre(const parser::OpenACCBlockConstruct &x) {
  const auto &beginBlockDir{std::get<parser::AccBeginBlockDirective>(x.t)};
  const auto &blockDir{std::get<parser::AccBlockDirective>(beginBlockDir.t)};
  switch (blockDir.v) {
  case llvm::acc::Directive::ACCD_data:
  case llvm::acc::Directive::ACCD_host_data:
  case llvm::acc::Directive::ACCD_kernels:
  case llvm::acc::Directive::ACCD_parallel:
  case llvm::acc::Directive::ACCD_serial:
    PushContext(blockDir.source, blockDir.v);
    break;
  default:
    break;
  }
  ClearDataSharingAttributeObjects();
  return true;
}

bool AccAttributeVisitor::Pre(const parser::OpenACCDeclarativeConstruct &x) {
  if (const auto *declConstruct{
          std::get_if<parser::OpenACCStandaloneDeclarativeConstruct>(&x.u)}) {
    const auto &declDir{
        std::get<parser::AccDeclarativeDirective>(declConstruct->t)};
    PushContext(declDir.source, llvm::acc::Directive::ACCD_declare);
  }
  ClearDataSharingAttributeObjects();
  return true;
}

static const parser::AccObjectList &GetAccObjectList(
    const parser::AccClause &clause) {
  if (const auto *copyClause =
          std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
    return copyClause->v;
  } else if (const auto *createClause =
                 std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
    const Fortran::parser::AccObjectListWithModifier &listWithModifier =
        createClause->v;
    const Fortran::parser::AccObjectList &accObjectList =
        std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
    return accObjectList;
  } else if (const auto *copyinClause =
                 std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
    const Fortran::parser::AccObjectListWithModifier &listWithModifier =
        copyinClause->v;
    const Fortran::parser::AccObjectList &accObjectList =
        std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
    return accObjectList;
  } else if (const auto *copyoutClause =
                 std::get_if<Fortran::parser::AccClause::Copyout>(&clause.u)) {
    const Fortran::parser::AccObjectListWithModifier &listWithModifier =
        copyoutClause->v;
    const Fortran::parser::AccObjectList &accObjectList =
        std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
    return accObjectList;
  } else if (const auto *presentClause =
                 std::get_if<Fortran::parser::AccClause::Present>(&clause.u)) {
    return presentClause->v;
  } else if (const auto *deviceptrClause =
                 std::get_if<Fortran::parser::AccClause::Deviceptr>(
                     &clause.u)) {
    return deviceptrClause->v;
  } else if (const auto *deviceResidentClause =
                 std::get_if<Fortran::parser::AccClause::DeviceResident>(
                     &clause.u)) {
    return deviceResidentClause->v;
  } else if (const auto *linkClause =
                 std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
    return linkClause->v;
  } else {
    llvm_unreachable("Clause without object list!");
  }
}

void AccAttributeVisitor::Post(
    const parser::OpenACCStandaloneDeclarativeConstruct &x) {
  const auto &clauseList = std::get<parser::AccClauseList>(x.t);
  for (const auto &clause : clauseList.v) {
    // Restriction - line 2414
    DoNotAllowAssumedSizedArray(GetAccObjectList(clause));
  }
}

bool AccAttributeVisitor::Pre(const parser::OpenACCLoopConstruct &x) {
  const auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)};
  const auto &loopDir{std::get<parser::AccLoopDirective>(beginDir.t)};
  const auto &clauseList{std::get<parser::AccClauseList>(beginDir.t)};
  if (loopDir.v == llvm::acc::Directive::ACCD_loop) {
    PushContext(loopDir.source, loopDir.v);
  }
  ClearDataSharingAttributeObjects();
  SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));
  const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
  CheckAssociatedLoop(*outer);
  return true;
}

bool AccAttributeVisitor::Pre(const parser::OpenACCStandaloneConstruct &x) {
  const auto &standaloneDir{std::get<parser::AccStandaloneDirective>(x.t)};
  switch (standaloneDir.v) {
  case llvm::acc::Directive::ACCD_enter_data:
  case llvm::acc::Directive::ACCD_exit_data:
  case llvm::acc::Directive::ACCD_init:
  case llvm::acc::Directive::ACCD_set:
  case llvm::acc::Directive::ACCD_shutdown:
  case llvm::acc::Directive::ACCD_update:
    PushContext(standaloneDir.source, standaloneDir.v);
    break;
  default:
    break;
  }
  ClearDataSharingAttributeObjects();
  return true;
}

Symbol *AccAttributeVisitor::ResolveName(
    const parser::Name &name, bool parentScope) {
  Symbol *prev{currScope().FindSymbol(name.source)};
  // Check in parent scope if asked for.
  if (!prev && parentScope) {
    prev = currScope().parent().FindSymbol(name.source);
  }
  if (prev != name.symbol) {
    name.symbol = prev;
  }
  return prev;
}

Symbol *AccAttributeVisitor::ResolveFctName(const parser::Name &name) {
  Symbol *prev{currScope().FindSymbol(name.source)};
  if (!prev || (prev && prev->IsFuncResult())) {
    prev = currScope().parent().FindSymbol(name.source);
    if (!prev) {
      prev = &context_.globalScope().MakeSymbol(
          name.source, Attrs{}, ProcEntityDetails{});
    }
  }
  if (prev != name.symbol) {
    name.symbol = prev;
  }
  return prev;
}

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

template <typename T>
MaybeExpr EvaluateExpr(
    Fortran::semantics::SemanticsContext &semanticsContext, const T &expr) {
  return FoldExpr(
      semanticsContext.foldingContext(), AnalyzeExpr(semanticsContext, expr));
}

void AccAttributeVisitor::AddRoutineInfoToSymbol(
    Symbol &symbol, const parser::OpenACCRoutineConstruct &x) {
  if (symbol.has<SubprogramDetails>()) {
    Fortran::semantics::OpenACCRoutineInfo info;
    const auto &clauses = std::get<Fortran::parser::AccClauseList>(x.t);
    for (const Fortran::parser::AccClause &clause : clauses.v) {
      if (std::get_if<Fortran::parser::AccClause::Seq>(&clause.u)) {
        if (info.deviceTypeInfos().empty()) {
          info.set_isSeq();
        } else {
          info.deviceTypeInfos().back().set_isSeq();
        }
      } else if (const auto *gangClause =
                     std::get_if<Fortran::parser::AccClause::Gang>(&clause.u)) {
        if (info.deviceTypeInfos().empty()) {
          info.set_isGang();
        } else {
          info.deviceTypeInfos().back().set_isGang();
        }
        if (gangClause->v) {
          const Fortran::parser::AccGangArgList &x = *gangClause->v;
          for (const Fortran::parser::AccGangArg &gangArg : x.v) {
            if (const auto *dim =
                    std::get_if<Fortran::parser::AccGangArg::Dim>(&gangArg.u)) {
              if (const auto v{EvaluateInt64(context_, dim->v)}) {
                if (info.deviceTypeInfos().empty()) {
                  info.set_gangDim(*v);
                } else {
                  info.deviceTypeInfos().back().set_gangDim(*v);
                }
              }
            }
          }
        }
      } else if (std::get_if<Fortran::parser::AccClause::Vector>(&clause.u)) {
        if (info.deviceTypeInfos().empty()) {
          info.set_isVector();
        } else {
          info.deviceTypeInfos().back().set_isVector();
        }
      } else if (std::get_if<Fortran::parser::AccClause::Worker>(&clause.u)) {
        if (info.deviceTypeInfos().empty()) {
          info.set_isWorker();
        } else {
          info.deviceTypeInfos().back().set_isWorker();
        }
      } else if (std::get_if<Fortran::parser::AccClause::Nohost>(&clause.u)) {
        info.set_isNohost();
      } else if (const auto *bindClause =
                     std::get_if<Fortran::parser::AccClause::Bind>(&clause.u)) {
        if (const auto *name =
                std::get_if<Fortran::parser::Name>(&bindClause->v.u)) {
          if (Symbol *sym = ResolveFctName(*name)) {
            if (info.deviceTypeInfos().empty()) {
              info.set_bindName(sym->name().ToString());
            } else {
              info.deviceTypeInfos().back().set_bindName(
                  sym->name().ToString());
            }
          } else {
            context_.Say((*name).source,
                "No function or subroutine declared for '%s'"_err_en_US,
                (*name).source);
          }
        } else if (const auto charExpr =
                       std::get_if<Fortran::parser::ScalarDefaultCharExpr>(
                           &bindClause->v.u)) {
          auto *charConst =
              Fortran::parser::Unwrap<Fortran::parser::CharLiteralConstant>(
                  *charExpr);
          std::string str{std::get<std::string>(charConst->t)};
          std::stringstream bindName;
          bindName << "\"" << str << "\"";
          if (info.deviceTypeInfos().empty()) {
            info.set_bindName(bindName.str());
          } else {
            info.deviceTypeInfos().back().set_bindName(bindName.str());
          }
        }
      } else if (const auto *dType =
                     std::get_if<Fortran::parser::AccClause::DeviceType>(
                         &clause.u)) {
        const parser::AccDeviceTypeExprList &deviceTypeExprList = dType->v;
        OpenACCRoutineDeviceTypeInfo dtypeInfo;
        dtypeInfo.set_dType(deviceTypeExprList.v.front().v);
        info.add_deviceTypeInfo(dtypeInfo);
      }
    }
    symbol.get<SubprogramDetails>().add_openACCRoutineInfo(info);
  }
}

bool AccAttributeVisitor::Pre(const parser::OpenACCRoutineConstruct &x) {
  const auto &verbatim{std::get<parser::Verbatim>(x.t)};
  if (topScope_) {
    PushContext(
        verbatim.source, llvm::acc::Directive::ACCD_routine, *topScope_);
  } else {
    PushContext(verbatim.source, llvm::acc::Directive::ACCD_routine);
  }
  const auto &optName{std::get<std::optional<parser::Name>>(x.t)};
  if (optName) {
    if (Symbol *sym = ResolveFctName(*optName)) {
      Symbol &ultimate{sym->GetUltimate()};
      AddRoutineInfoToSymbol(ultimate, x);
    } else {
      context_.Say((*optName).source,
          "No function or subroutine declared for '%s'"_err_en_US,
          (*optName).source);
    }
  } else {
    if (currScope().symbol()) {
      AddRoutineInfoToSymbol(*currScope().symbol(), x);
    }
  }
  return true;
}

bool AccAttributeVisitor::Pre(const parser::AccBindClause &x) {
  if (const auto *name{std::get_if<parser::Name>(&x.u)}) {
    if (!ResolveFctName(*name)) {
      context_.Say(name->source,
          "No function or subroutine declared for '%s'"_err_en_US,
          name->source);
    }
  }
  return true;
}

bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
  const auto &beginBlockDir{std::get<parser::AccBeginCombinedDirective>(x.t)};
  const auto &combinedDir{
      std::get<parser::AccCombinedDirective>(beginBlockDir.t)};
  switch (combinedDir.v) {
  case llvm::acc::Directive::ACCD_kernels_loop:
  case llvm::acc::Directive::ACCD_parallel_loop:
  case llvm::acc::Directive::ACCD_serial_loop:
    PushContext(combinedDir.source, combinedDir.v);
    break;
  default:
    break;
  }
  const auto &clauseList{std::get<parser::AccClauseList>(beginBlockDir.t)};
  SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));
  const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
  CheckAssociatedLoop(*outer);
  ClearDataSharingAttributeObjects();
  return true;
}

static bool IsLastNameArray(const parser::Designator &designator) {
  const auto &name{GetLastName(designator)};
  const evaluate::DataRef dataRef{*(name.symbol)};
  return common::visit(
      common::visitors{
          [](const evaluate::SymbolRef &ref) {
            return ref->Rank() > 0 ||
                ref->GetType()->category() == DeclTypeSpec::Numeric;
          },
          [](const evaluate::ArrayRef &aref) {
            return aref.base().IsSymbol() ||
                aref.base().GetComponent().base().Rank() == 0;
          },
          [](const auto &) { return false; },
      },
      dataRef.u);
}

void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
    const parser::AccObjectList &objectList) {
  for (const auto &accObject : objectList.v) {
    common::visit(
        common::visitors{
            [&](const parser::Designator &designator) {
              if (!IsLastNameArray(designator)) {
                context_.Say(designator.source,
                    "Only array element or subarray are allowed in %s directive"_err_en_US,
                    parser::ToUpperCaseLetters(
                        llvm::acc::getOpenACCDirectiveName(
                            GetContext().directive)
                            .str()));
              }
            },
            [&](const auto &name) {
              context_.Say(name.source,
                  "Only array element or subarray are allowed in %s directive"_err_en_US,
                  parser::ToUpperCaseLetters(
                      llvm::acc::getOpenACCDirectiveName(GetContext().directive)
                          .str()));
            },
        },
        accObject.u);
  }
}

void AccAttributeVisitor::DoNotAllowAssumedSizedArray(
    const parser::AccObjectList &objectList) {
  for (const auto &accObject : objectList.v) {
    common::visit(
        common::visitors{
            [&](const parser::Designator &designator) {
              const auto &name{GetLastName(designator)};
              if (name.symbol && semantics::IsAssumedSizeArray(*name.symbol)) {
                context_.Say(designator.source,
                    "Assumed-size dummy arrays may not appear on the %s "
                    "directive"_err_en_US,
                    parser::ToUpperCaseLetters(
                        llvm::acc::getOpenACCDirectiveName(
                            GetContext().directive)
                            .str()));
              }
            },
            [&](const auto &name) {

            },
        },
        accObject.u);
  }
}

void AccAttributeVisitor::AllowOnlyVariable(const parser::AccObject &object) {
  common::visit(
      common::visitors{
          [&](const parser::Designator &designator) {
            const auto &name{GetLastName(designator)};
            if (name.symbol && !semantics::IsVariableName(*name.symbol) &&
                !semantics::IsNamedConstant(*name.symbol)) {
              context_.Say(designator.source,
                  "Only variables are allowed in data clauses on the %s "
                  "directive"_err_en_US,
                  parser::ToUpperCaseLetters(
                      llvm::acc::getOpenACCDirectiveName(GetContext().directive)
                          .str()));
            }
          },
          [&](const auto &name) {},
      },
      object.u);
}

bool AccAttributeVisitor::Pre(const parser::OpenACCCacheConstruct &x) {
  const auto &verbatim{std::get<parser::Verbatim>(x.t)};
  PushContext(verbatim.source, llvm::acc::Directive::ACCD_cache);
  ClearDataSharingAttributeObjects();

  const auto &objectListWithModifier =
      std::get<parser::AccObjectListWithModifier>(x.t);
  const auto &objectList =
      std::get<Fortran::parser::AccObjectList>(objectListWithModifier.t);

  // 2.10 Cache directive restriction: A var in a cache directive must be a
  // single array element or a simple subarray.
  AllowOnlyArrayAndSubArray(objectList);

  return true;
}

std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses(
    const parser::AccClauseList &x) {
  std::int64_t collapseLevel{0};
  for (const auto &clause : x.v) {
    if (const auto *collapseClause{
            std::get_if<parser::AccClause::Collapse>(&clause.u)}) {
      const parser::AccCollapseArg &arg = collapseClause->v;
      const auto &collapseValue{std::get<parser::ScalarIntConstantExpr>(arg.t)};
      if (const auto v{EvaluateInt64(context_, collapseValue)}) {
        collapseLevel = *v;
      }
    }
  }

  if (collapseLevel) {
    return collapseLevel;
  }
  return 1; // default is outermost loop
}

void AccAttributeVisitor::CheckAssociatedLoop(
    const parser::DoConstruct &outerDoConstruct) {
  std::int64_t level{GetContext().associatedLoopLevel};
  if (level <= 0) { // collapse value was negative or 0
    return;
  }

  const auto getNextDoConstruct =
      [this](const parser::Block &block,
          std::int64_t &level) -> const parser::DoConstruct * {
    for (const auto &entry : block) {
      if (const auto *doConstruct = GetDoConstructIf(entry)) {
        return doConstruct;
      } else if (parser::Unwrap<parser::CompilerDirective>(entry)) {
        // It is allowed to have a compiler directive associated with the loop.
        continue;
      } else if (const auto &accLoop{
                     parser::Unwrap<parser::OpenACCLoopConstruct>(entry)}) {
        if (level == 0)
          break;
        const auto &beginDir{
            std::get<parser::AccBeginLoopDirective>(accLoop->t)};
        context_.Say(beginDir.source,
            "LOOP directive not expected in COLLAPSE loop nest"_err_en_US);
        level = 0;
      } else {
        break;
      }
    }
    return nullptr;
  };

  auto checkExprHasSymbols = [&](llvm::SmallVector<Symbol *> &ivs,
                                 semantics::UnorderedSymbolSet &symbols) {
    for (auto iv : ivs) {
      if (symbols.count(*iv) != 0) {
        context_.Say(GetContext().directiveSource,
            "Trip count must be computable and invariant"_err_en_US);
      }
    }
  };

  Symbol::Flag flag = Symbol::Flag::AccPrivate;
  llvm::SmallVector<Symbol *> ivs;
  using Bounds = parser::LoopControl::Bounds;
  for (const parser::DoConstruct *loop{&outerDoConstruct}; loop && level > 0;) {
    // Go through all nested loops to ensure index variable exists.
    if (const parser::Name * ivName{GetLoopIndex(*loop)}) {
      if (auto *symbol{ResolveAcc(*ivName, flag, currScope())}) {
        if (auto &control{loop->GetLoopControl()}) {
          if (const Bounds * b{std::get_if<Bounds>(&control->u)}) {
            if (auto lowerExpr{semantics::AnalyzeExpr(context_, b->lower)}) {
              semantics::UnorderedSymbolSet lowerSyms =
                  evaluate::CollectSymbols(*lowerExpr);
              checkExprHasSymbols(ivs, lowerSyms);
            }
            if (auto upperExpr{semantics::AnalyzeExpr(context_, b->upper)}) {
              semantics::UnorderedSymbolSet upperSyms =
                  evaluate::CollectSymbols(*upperExpr);
              checkExprHasSymbols(ivs, upperSyms);
            }
          }
        }
        ivs.push_back(symbol);
      }
    }

    const auto &block{std::get<parser::Block>(loop->t)};
    --level;
    loop = getNextDoConstruct(block, level);
  }
  CHECK(level == 0);
}

void AccAttributeVisitor::EnsureAllocatableOrPointer(
    const llvm::acc::Clause clause, const parser::AccObjectList &objectList) {
  for (const auto &accObject : objectList.v) {
    common::visit(
        common::visitors{
            [&](const parser::Designator &designator) {
              const auto &lastName{GetLastName(designator)};
              if (!IsAllocatableOrObjectPointer(lastName.symbol)) {
                context_.Say(designator.source,
                    "Argument `%s` on the %s clause must be a variable or "
                    "array with the POINTER or ALLOCATABLE attribute"_err_en_US,
                    lastName.symbol->name(),
                    parser::ToUpperCaseLetters(
                        llvm::acc::getOpenACCClauseName(clause).str()));
              }
            },
            [&](const auto &name) {
              context_.Say(name.source,
                  "Argument on the %s clause must be a variable or "
                  "array with the POINTER or ALLOCATABLE attribute"_err_en_US,
                  parser::ToUpperCaseLetters(
                      llvm::acc::getOpenACCClauseName(clause).str()));
            },
        },
        accObject.u);
  }
}

bool AccAttributeVisitor::Pre(const parser::AccClause::Attach &x) {
  // Restriction - line 1708-1709
  EnsureAllocatableOrPointer(llvm::acc::Clause::ACCC_attach, x.v);
  return true;
}

bool AccAttributeVisitor::Pre(const parser::AccClause::Detach &x) {
  // Restriction - line 1715-1717
  EnsureAllocatableOrPointer(llvm::acc::Clause::ACCC_detach, x.v);
  return true;
}

void AccAttributeVisitor::Post(const parser::AccDefaultClause &x) {
  if (!dirContext_.empty()) {
    switch (x.v) {
    case llvm::acc::DefaultValue::ACC_Default_present:
      SetContextDefaultDSA(Symbol::Flag::AccPresent);
      break;
    case llvm::acc::DefaultValue::ACC_Default_none:
      SetContextDefaultDSA(Symbol::Flag::AccNone);
      break;
    }
  }
}

// For OpenACC constructs, check all the data-refs within the constructs
// and adjust the symbol for each Name if necessary
void AccAttributeVisitor::Post(const parser::Name &name) {
  auto *symbol{name.symbol};
  if (symbol && !dirContext_.empty() && GetContext().withinConstruct) {
    if (!symbol->owner().IsDerivedType() && !symbol->has<ProcEntityDetails>() &&
        !symbol->has<SubprogramDetails>() && !IsObjectWithDSA(*symbol)) {
      if (Symbol * found{currScope().FindSymbol(name.source)}) {
        if (symbol != found) {
          name.symbol = found; // adjust the symbol within region
        } else if (GetContext().defaultDSA == Symbol::Flag::AccNone) {
          // 2.5.14.
          context_.Say(name.source,
              "The DEFAULT(NONE) clause requires that '%s' must be listed in "
              "a data-mapping clause"_err_en_US,
              symbol->name());
        }
      }
    }
  } // within OpenACC construct
}

Symbol *AccAttributeVisitor::ResolveAccCommonBlockName(
    const parser::Name *name) {
  if (auto *prev{name
              ? GetContext().scope.parent().FindCommonBlock(name->source)
              : nullptr}) {
    name->symbol = prev;
    return prev;
  }
  // Check if the Common Block is declared in the current scope
  if (auto *commonBlockSymbol{
          name ? GetContext().scope.FindCommonBlock(name->source) : nullptr}) {
    name->symbol = commonBlockSymbol;
    return commonBlockSymbol;
  }
  return nullptr;
}

void AccAttributeVisitor::ResolveAccObjectList(
    const parser::AccObjectList &accObjectList, Symbol::Flag accFlag) {
  for (const auto &accObject : accObjectList.v) {
    AllowOnlyVariable(accObject);
    ResolveAccObject(accObject, accFlag);
  }
}

void AccAttributeVisitor::ResolveAccObject(
    const parser::AccObject &accObject, Symbol::Flag accFlag) {
  common::visit(
      common::visitors{
          [&](const parser::Designator &designator) {
            if (const auto *name{
                    semantics::getDesignatorNameIfDataRef(designator)}) {
              if (auto *symbol{ResolveAcc(*name, accFlag, currScope())}) {
                AddToContextObjectWithDSA(*symbol, accFlag);
                if (dataSharingAttributeFlags.test(accFlag)) {
                  CheckMultipleAppearances(*name, *symbol, accFlag);
                }
              }
            } else {
              // Array sections to be changed to substrings as needed
              if (AnalyzeExpr(context_, designator)) {
                if (std::holds_alternative<parser::Substring>(designator.u)) {
                  context_.Say(designator.source,
                      "Substrings are not allowed on OpenACC "
                      "directives or clauses"_err_en_US);
                }
              }
              // other checks, more TBD
            }
          },
          [&](const parser::Name &name) { // common block
            if (auto *symbol{ResolveAccCommonBlockName(&name)}) {
              CheckMultipleAppearances(
                  name, *symbol, Symbol::Flag::AccCommonBlock);
              for (auto &object : symbol->get<CommonBlockDetails>().objects()) {
                if (auto *resolvedObject{
                        ResolveAcc(*object, accFlag, currScope())}) {
                  AddToContextObjectWithDSA(*resolvedObject, accFlag);
                }
              }
            } else {
              context_.Say(name.source,
                  "COMMON block must be declared in the same scoping unit "
                  "in which the OpenACC directive or clause appears"_err_en_US);
            }
          },
      },
      accObject.u);
}

Symbol *AccAttributeVisitor::ResolveAcc(
    const parser::Name &name, Symbol::Flag accFlag, Scope &scope) {
  return DeclareOrMarkOtherAccessEntity(name, accFlag);
}

Symbol *AccAttributeVisitor::ResolveAcc(
    Symbol &symbol, Symbol::Flag accFlag, Scope &scope) {
  return DeclareOrMarkOtherAccessEntity(symbol, accFlag);
}

Symbol *AccAttributeVisitor::DeclareOrMarkOtherAccessEntity(
    const parser::Name &name, Symbol::Flag accFlag) {
  Symbol *prev{currScope().FindSymbol(name.source)};
  if (!name.symbol || !prev) {
    return nullptr;
  } else if (prev != name.symbol) {
    name.symbol = prev;
  }
  return DeclareOrMarkOtherAccessEntity(*prev, accFlag);
}

Symbol *AccAttributeVisitor::DeclareOrMarkOtherAccessEntity(
    Symbol &object, Symbol::Flag accFlag) {
  if (accFlagsRequireMark.test(accFlag)) {
    if (GetContext().directive == llvm::acc::ACCD_declare) {
      object.set(Symbol::Flag::AccDeclare);
      object.set(accFlag);
    }
  }
  return &object;
}

static bool WithMultipleAppearancesAccException(
    const Symbol &symbol, Symbol::Flag flag) {
  return false; // Place holder
}

void AccAttributeVisitor::CheckMultipleAppearances(
    const parser::Name &name, const Symbol &symbol, Symbol::Flag accFlag) {
  const auto *target{&symbol};
  if (HasDataSharingAttributeObject(*target) &&
      !WithMultipleAppearancesAccException(symbol, accFlag)) {
    context_.Say(name.source,
        "'%s' appears in more than one data-sharing clause "
        "on the same OpenACC directive"_err_en_US,
        name.ToString());
  } else {
    AddDataSharingAttributeObject(*target);
  }
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPBlockConstruct &x) {
  const auto &beginBlockDir{std::get<parser::OmpBeginBlockDirective>(x.t)};
  const auto &beginDir{std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
  switch (beginDir.v) {
  case llvm::omp::Directive::OMPD_masked:
  case llvm::omp::Directive::OMPD_parallel_masked:
  case llvm::omp::Directive::OMPD_master:
  case llvm::omp::Directive::OMPD_parallel_master:
  case llvm::omp::Directive::OMPD_ordered:
  case llvm::omp::Directive::OMPD_parallel:
  case llvm::omp::Directive::OMPD_scope:
  case llvm::omp::Directive::OMPD_single:
  case llvm::omp::Directive::OMPD_target:
  case llvm::omp::Directive::OMPD_target_data:
  case llvm::omp::Directive::OMPD_task:
  case llvm::omp::Directive::OMPD_taskgroup:
  case llvm::omp::Directive::OMPD_teams:
  case llvm::omp::Directive::OMPD_workshare:
  case llvm::omp::Directive::OMPD_parallel_workshare:
  case llvm::omp::Directive::OMPD_target_teams:
  case llvm::omp::Directive::OMPD_target_parallel:
    PushContext(beginDir.source, beginDir.v);
    break;
  default:
    // TODO others
    break;
  }
  if (beginDir.v == llvm::omp::Directive::OMPD_master ||
      beginDir.v == llvm::omp::Directive::OMPD_parallel_master)
    IssueNonConformanceWarning(beginDir.v, beginDir.source);
  ClearDataSharingAttributeObjects();
  ClearPrivateDataSharingAttributeObjects();
  ClearAllocateNames();
  return true;
}

void OmpAttributeVisitor::Post(const parser::OpenMPBlockConstruct &x) {
  const auto &beginBlockDir{std::get<parser::OmpBeginBlockDirective>(x.t)};
  const auto &beginDir{std::get<parser::OmpBlockDirective>(beginBlockDir.t)};
  switch (beginDir.v) {
  case llvm::omp::Directive::OMPD_masked:
  case llvm::omp::Directive::OMPD_master:
  case llvm::omp::Directive::OMPD_parallel_masked:
  case llvm::omp::Directive::OMPD_parallel_master:
  case llvm::omp::Directive::OMPD_parallel:
  case llvm::omp::Directive::OMPD_scope:
  case llvm::omp::Directive::OMPD_single:
  case llvm::omp::Directive::OMPD_target:
  case llvm::omp::Directive::OMPD_task:
  case llvm::omp::Directive::OMPD_teams:
  case llvm::omp::Directive::OMPD_parallel_workshare:
  case llvm::omp::Directive::OMPD_target_teams:
  case llvm::omp::Directive::OMPD_target_parallel: {
    bool hasPrivate;
    for (const auto *allocName : allocateNames_) {
      hasPrivate = false;
      for (auto privateObj : privateDataSharingAttributeObjects_) {
        const Symbol &symbolPrivate{*privateObj};
        if (allocName->source == symbolPrivate.name()) {
          hasPrivate = true;
          break;
        }
      }
      if (!hasPrivate) {
        context_.Say(allocName->source,
            "The ALLOCATE clause requires that '%s' must be listed in a "
            "private "
            "data-sharing attribute clause on the same directive"_err_en_US,
            allocName->ToString());
      }
    }
    break;
  }
  default:
    break;
  }
  PopContext();
}

bool OmpAttributeVisitor::Pre(
    const parser::OpenMPSimpleStandaloneConstruct &x) {
  const auto &standaloneDir{
      std::get<parser::OmpSimpleStandaloneDirective>(x.t)};
  switch (standaloneDir.v) {
  case llvm::omp::Directive::OMPD_barrier:
  case llvm::omp::Directive::OMPD_ordered:
  case llvm::omp::Directive::OMPD_scan:
  case llvm::omp::Directive::OMPD_target_enter_data:
  case llvm::omp::Directive::OMPD_target_exit_data:
  case llvm::omp::Directive::OMPD_target_update:
  case llvm::omp::Directive::OMPD_taskwait:
  case llvm::omp::Directive::OMPD_taskyield:
    PushContext(standaloneDir.source, standaloneDir.v);
    break;
  default:
    break;
  }
  ClearDataSharingAttributeObjects();
  return true;
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
  const auto &beginLoopDir{std::get<parser::OmpBeginLoopDirective>(x.t)};
  const auto &beginDir{std::get<parser::OmpLoopDirective>(beginLoopDir.t)};
  const auto &clauseList{std::get<parser::OmpClauseList>(beginLoopDir.t)};
  switch (beginDir.v) {
  case llvm::omp::Directive::OMPD_distribute:
  case llvm::omp::Directive::OMPD_distribute_parallel_do:
  case llvm::omp::Directive::OMPD_distribute_parallel_do_simd:
  case llvm::omp::Directive::OMPD_distribute_simd:
  case llvm::omp::Directive::OMPD_do:
  case llvm::omp::Directive::OMPD_do_simd:
  case llvm::omp::Directive::OMPD_loop:
  case llvm::omp::Directive::OMPD_masked_taskloop_simd:
  case llvm::omp::Directive::OMPD_masked_taskloop:
  case llvm::omp::Directive::OMPD_master_taskloop_simd:
  case llvm::omp::Directive::OMPD_master_taskloop:
  case llvm::omp::Directive::OMPD_parallel_do:
  case llvm::omp::Directive::OMPD_parallel_do_simd:
  case llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd:
  case llvm::omp::Directive::OMPD_parallel_masked_taskloop:
  case llvm::omp::Directive::OMPD_parallel_master_taskloop_simd:
  case llvm::omp::Directive::OMPD_parallel_master_taskloop:
  case llvm::omp::Directive::OMPD_simd:
  case llvm::omp::Directive::OMPD_target_loop:
  case llvm::omp::Directive::OMPD_target_parallel_do:
  case llvm::omp::Directive::OMPD_target_parallel_do_simd:
  case llvm::omp::Directive::OMPD_target_parallel_loop:
  case llvm::omp::Directive::OMPD_target_teams_distribute:
  case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do:
  case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
  case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
  case llvm::omp::Directive::OMPD_target_teams_loop:
  case llvm::omp::Directive::OMPD_target_simd:
  case llvm::omp::Directive::OMPD_taskloop:
  case llvm::omp::Directive::OMPD_taskloop_simd:
  case llvm::omp::Directive::OMPD_teams_distribute:
  case llvm::omp::Directive::OMPD_teams_distribute_parallel_do:
  case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd:
  case llvm::omp::Directive::OMPD_teams_distribute_simd:
  case llvm::omp::Directive::OMPD_teams_loop:
  case llvm::omp::Directive::OMPD_tile:
  case llvm::omp::Directive::OMPD_unroll:
    PushContext(beginDir.source, beginDir.v);
    break;
  default:
    break;
  }
  if (beginDir.v == llvm::omp::OMPD_master_taskloop ||
      beginDir.v == llvm::omp::OMPD_master_taskloop_simd ||
      beginDir.v == llvm::omp::OMPD_parallel_master_taskloop ||
      beginDir.v == llvm::omp::OMPD_parallel_master_taskloop_simd ||
      beginDir.v == llvm::omp::Directive::OMPD_target_loop)
    IssueNonConformanceWarning(beginDir.v, beginDir.source);
  ClearDataSharingAttributeObjects();
  SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));

  if (beginDir.v == llvm::omp::Directive::OMPD_do) {
    if (const auto &doConstruct{
            std::get<std::optional<parser::DoConstruct>>(x.t)}) {
      if (doConstruct.value().IsDoWhile()) {
        return true;
      }
    }
  }
  PrivatizeAssociatedLoopIndexAndCheckLoopLevel(x);
  ordCollapseLevel = GetAssociatedLoopLevelFromClauses(clauseList) + 1;
  return true;
}

void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct(
    const parser::Name &iv) {
  // Find the parallel or task generating construct enclosing the
  // sequential loop.
  auto targetIt{dirContext_.rbegin()};
  for (;; ++targetIt) {
    if (targetIt == dirContext_.rend()) {
      return;
    }
    if (llvm::omp::allParallelSet.test(targetIt->directive) ||
        llvm::omp::taskGeneratingSet.test(targetIt->directive)) {
      break;
    }
  }
  // If this symbol already has a data-sharing attribute then there is nothing
  // to do here.
  if (const Symbol * symbol{iv.symbol}) {
    for (auto symMap : targetIt->objectWithDSA) {
      if (symMap.first->name() == symbol->name()) {
        return;
      }
    }
  }
  // If this symbol is already Private or Firstprivate in the enclosing
  // OpenMP parallel or task then there is nothing to do here.
  if (auto *symbol{targetIt->scope.FindSymbol(iv.source)}) {
    if (symbol->owner() == targetIt->scope) {
      if (symbol->test(Symbol::Flag::OmpPrivate) ||
          symbol->test(Symbol::Flag::OmpFirstPrivate)) {
        return;
      }
    }
  }
  // Otherwise find the symbol and make it Private for the entire enclosing
  // parallel or task
  if (auto *symbol{ResolveOmp(iv, Symbol::Flag::OmpPrivate, targetIt->scope)}) {
    targetIt++;
    symbol->set(Symbol::Flag::OmpPreDetermined);
    iv.symbol = symbol; // adjust the symbol within region
    for (auto it{dirContext_.rbegin()}; it != targetIt; ++it) {
      AddToContextObjectWithDSA(*symbol, Symbol::Flag::OmpPrivate, *it);
    }
  }
}

// [OMP-4.5]2.15.1.1 Data-sharing Attribute Rules - Predetermined
//   - A loop iteration variable for a sequential loop in a parallel
//     or task generating construct is private in the innermost such
//     construct that encloses the loop
// Loop iteration variables are not well defined for DO WHILE loop.
// Use of DO CONCURRENT inside OpenMP construct is unspecified behavior
// till OpenMP-5.0 standard.
// In above both cases we skip the privatization of iteration variables.
bool OmpAttributeVisitor::Pre(const parser::DoConstruct &x) {
  if (!dirContext_.empty() && GetContext().withinConstruct) {
    llvm::SmallVector<const parser::Name *> ivs;
    if (x.IsDoNormal()) {
      const parser::Name *iv{GetLoopIndex(x)};
      if (iv && iv->symbol)
        ivs.push_back(iv);
    }
    ordCollapseLevel--;
    for (auto iv : ivs) {
      if (!iv->symbol->test(Symbol::Flag::OmpPreDetermined)) {
        ResolveSeqLoopIndexInParallelOrTaskConstruct(*iv);
      } else {
        // TODO: conflict checks with explicitly determined DSA
      }
      if (ordCollapseLevel) {
        if (const auto *details{iv->symbol->detailsIf<HostAssocDetails>()}) {
          const Symbol *tpSymbol = &details->symbol();
          if (tpSymbol->test(Symbol::Flag::OmpThreadprivate)) {
            context_.Say(iv->source,
                "Loop iteration variable %s is not allowed in THREADPRIVATE."_err_en_US,
                iv->ToString());
          }
        }
      }
    }
  }
  return true;
}

std::int64_t OmpAttributeVisitor::GetAssociatedLoopLevelFromClauses(
    const parser::OmpClauseList &x) {
  std::int64_t orderedLevel{0};
  std::int64_t collapseLevel{0};

  const parser::OmpClause *ordClause{nullptr};
  const parser::OmpClause *collClause{nullptr};

  for (const auto &clause : x.v) {
    if (const auto *orderedClause{
            std::get_if<parser::OmpClause::Ordered>(&clause.u)}) {
      if (const auto v{EvaluateInt64(context_, orderedClause->v)}) {
        orderedLevel = *v;
      }
      ordClause = &clause;
    }
    if (const auto *collapseClause{
            std::get_if<parser::OmpClause::Collapse>(&clause.u)}) {
      if (const auto v{EvaluateInt64(context_, collapseClause->v)}) {
        collapseLevel = *v;
      }
      collClause = &clause;
    }
  }

  if (orderedLevel && (!collapseLevel || orderedLevel >= collapseLevel)) {
    SetAssociatedClause(*ordClause);
    return orderedLevel;
  } else if (!orderedLevel && collapseLevel) {
    SetAssociatedClause(*collClause);
    return collapseLevel;
  } // orderedLevel < collapseLevel is an error handled in structural checks
  return 1; // default is outermost loop
}

// 2.15.1.1 Data-sharing Attribute Rules - Predetermined
//   - The loop iteration variable(s) in the associated do-loop(s) of a do,
//     parallel do, taskloop, or distribute construct is (are) private.
//   - The loop iteration variable in the associated do-loop of a simd construct
//     with just one associated do-loop is linear with a linear-step that is the
//     increment of the associated do-loop.
//   - The loop iteration variables in the associated do-loops of a simd
//     construct with multiple associated do-loops are lastprivate.
void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
    const parser::OpenMPLoopConstruct &x) {
  std::int64_t level{GetContext().associatedLoopLevel};
  if (level <= 0) {
    return;
  }
  Symbol::Flag ivDSA;
  if (!llvm::omp::allSimdSet.test(GetContext().directive)) {
    ivDSA = Symbol::Flag::OmpPrivate;
  } else if (level == 1) {
    ivDSA = Symbol::Flag::OmpLinear;
  } else {
    ivDSA = Symbol::Flag::OmpLastPrivate;
  }

  const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
  if (outer.has_value()) {
    for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; --level) {
      // go through all the nested do-loops and resolve index variables
      const parser::Name *iv{GetLoopIndex(*loop)};
      if (iv) {
        if (auto *symbol{ResolveOmp(*iv, ivDSA, currScope())}) {
          symbol->set(Symbol::Flag::OmpPreDetermined);
          iv->symbol = symbol; // adjust the symbol within region
          AddToContextObjectWithDSA(*symbol, ivDSA);
        }

        const auto &block{std::get<parser::Block>(loop->t)};
        const auto it{block.begin()};
        loop = it != block.end() ? GetDoConstructIf(*it) : nullptr;
      }
    }
    CheckAssocLoopLevel(level, GetAssociatedClause());
  } else {
    context_.Say(GetContext().directiveSource,
        "A DO loop must follow the %s directive"_err_en_US,
        parser::ToUpperCaseLetters(
            llvm::omp::getOpenMPDirectiveName(GetContext().directive).str()));
  }
}
void OmpAttributeVisitor::CheckAssocLoopLevel(
    std::int64_t level, const parser::OmpClause *clause) {
  if (clause && level != 0) {
    context_.Say(clause->source,
        "The value of the parameter in the COLLAPSE or ORDERED clause must"
        " not be larger than the number of nested loops"
        " following the construct."_err_en_US);
  }
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionsConstruct &x) {
  const auto &beginSectionsDir{
      std::get<parser::OmpBeginSectionsDirective>(x.t)};
  const auto &beginDir{
      std::get<parser::OmpSectionsDirective>(beginSectionsDir.t)};
  switch (beginDir.v) {
  case llvm::omp::Directive::OMPD_parallel_sections:
  case llvm::omp::Directive::OMPD_sections:
    PushContext(beginDir.source, beginDir.v);
    GetContext().withinConstruct = true;
    break;
  default:
    break;
  }
  ClearDataSharingAttributeObjects();
  return true;
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) {
  const auto &beginCriticalDir{std::get<parser::OmpCriticalDirective>(x.t)};
  const auto &endCriticalDir{std::get<parser::OmpEndCriticalDirective>(x.t)};
  PushContext(beginCriticalDir.source, llvm::omp::Directive::OMPD_critical);
  GetContext().withinConstruct = true;
  if (const auto &criticalName{
          std::get<std::optional<parser::Name>>(beginCriticalDir.t)}) {
    ResolveOmpName(*criticalName, Symbol::Flag::OmpCriticalLock);
  }
  if (const auto &endCriticalName{
          std::get<std::optional<parser::Name>>(endCriticalDir.t)}) {
    ResolveOmpName(*endCriticalName, Symbol::Flag::OmpCriticalLock);
  }
  return true;
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) {
  PushContext(x.source, llvm::omp::Directive::OMPD_declare_target);
  const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t)};
  if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
    ResolveOmpObjectList(*objectList, Symbol::Flag::OmpDeclareTarget);
  } else if (const auto *clauseList{
                 parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
    for (const auto &clause : clauseList->v) {
      if (const auto *toClause{std::get_if<parser::OmpClause::To>(&clause.u)}) {
        auto &objList{std::get<parser::OmpObjectList>(toClause->v.t)};
        ResolveOmpObjectList(objList, Symbol::Flag::OmpDeclareTarget);
      } else if (const auto *linkClause{
                     std::get_if<parser::OmpClause::Link>(&clause.u)}) {
        ResolveOmpObjectList(linkClause->v, Symbol::Flag::OmpDeclareTarget);
      } else if (const auto *enterClause{
                     std::get_if<parser::OmpClause::Enter>(&clause.u)}) {
        ResolveOmpObjectList(enterClause->v, Symbol::Flag::OmpDeclareTarget);
      }
    }
  }
  return true;
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareMapperConstruct &x) {
  PushContext(x.source, llvm::omp::Directive::OMPD_declare_mapper);
  return true;
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPThreadprivate &x) {
  PushContext(x.source, llvm::omp::Directive::OMPD_threadprivate);
  const auto &list{std::get<parser::OmpObjectList>(x.t)};
  ResolveOmpObjectList(list, Symbol::Flag::OmpThreadprivate);
  return true;
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclarativeAllocate &x) {
  PushContext(x.source, llvm::omp::Directive::OMPD_allocate);
  const auto &list{std::get<parser::OmpObjectList>(x.t)};
  ResolveOmpObjectList(list, Symbol::Flag::OmpDeclarativeAllocateDirective);
  return false;
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPDispatchConstruct &x) {
  PushContext(x.source, llvm::omp::Directive::OMPD_dispatch);
  return true;
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPExecutableAllocate &x) {
  PushContext(x.source, llvm::omp::Directive::OMPD_allocate);
  const auto &list{std::get<std::optional<parser::OmpObjectList>>(x.t)};
  if (list) {
    ResolveOmpObjectList(*list, Symbol::Flag::OmpExecutableAllocateDirective);
  }
  return true;
}

bool OmpAttributeVisitor::Pre(const parser::OpenMPAllocatorsConstruct &x) {
  PushContext(x.source, llvm::omp::Directive::OMPD_allocators);
  const auto &clauseList{std::get<parser::OmpClauseList>(x.t)};
  for (const auto &clause : clauseList.v) {
    if (const auto *allocClause{
            std::get_if<parser::OmpClause::Allocate>(&clause.u)}) {
      ResolveOmpObjectList(std::get<parser::OmpObjectList>(allocClause->v.t),
          Symbol::Flag::OmpExecutableAllocateDirective);
    }
  }
  return true;
}

void OmpAttributeVisitor::Post(const parser::OmpDefaultClause &x) {
  // The DEFAULT clause may also be used on METADIRECTIVE. In that case
  // there is nothing to do.
  using DataSharingAttribute = parser::OmpDefaultClause::DataSharingAttribute;
  if (auto *dsa{std::get_if<DataSharingAttribute>(&x.u)}) {
    if (!dirContext_.empty()) {
      switch (*dsa) {
      case DataSharingAttribute::Private:
        SetContextDefaultDSA(Symbol::Flag::OmpPrivate);
        break;
      case DataSharingAttribute::Firstprivate:
        SetContextDefaultDSA(Symbol::Flag::OmpFirstPrivate);
        break;
      case DataSharingAttribute::Shared:
        SetContextDefaultDSA(Symbol::Flag::OmpShared);
        break;
      case DataSharingAttribute::None:
        SetContextDefaultDSA(Symbol::Flag::OmpNone);
        break;
      }
    }
  }
}

bool OmpAttributeVisitor::IsNestedInDirective(llvm::omp::Directive directive) {
  if (dirContext_.size() >= 1) {
    for (std::size_t i = dirContext_.size() - 1; i > 0; --i) {
      if (dirContext_[i - 1].directive == directive) {
        return true;
      }
    }
  }
  return false;
}

void OmpAttributeVisitor::Post(const parser::OpenMPExecutableAllocate &x) {
  bool hasAllocator = false;
  // TODO: Investigate whether searching the clause list can be done with
  // parser::Unwrap instead of the following loop
  const auto &clauseList{std::get<parser::OmpClauseList>(x.t)};
  for (const auto &clause : clauseList.v) {
    if (std::get_if<parser::OmpClause::Allocator>(&clause.u)) {
      hasAllocator = true;
    }
  }

  if (IsNestedInDirective(llvm::omp::Directive::OMPD_target) && !hasAllocator) {
    // TODO: expand this check to exclude the case when a requires
    //       directive with the dynamic_allocators clause is present
    //       in the same compilation unit (OMP5.0 2.11.3).
    context_.Say(x.source,
        "ALLOCATE directives that appear in a TARGET region "
        "must specify an allocator clause"_err_en_US);
  }

  const auto &allocateStmt =
      std::get<parser::Statement<parser::AllocateStmt>>(x.t).statement;
  if (const auto &list{std::get<std::optional<parser::OmpObjectList>>(x.t)}) {
    CheckAllNamesInAllocateStmt(
        std::get<parser::Verbatim>(x.t).source, *list, allocateStmt);
  }
  if (const auto &subDirs{
          std::get<std::optional<std::list<parser::OpenMPDeclarativeAllocate>>>(
              x.t)}) {
    for (const auto &dalloc : *subDirs) {
      CheckAllNamesInAllocateStmt(std::get<parser::Verbatim>(dalloc.t).source,
          std::get<parser::OmpObjectList>(dalloc.t), allocateStmt);
    }
  }
  PopContext();
}

void OmpAttributeVisitor::Post(const parser::OpenMPAllocatorsConstruct &x) {
  const auto &dir{std::get<parser::Verbatim>(x.t)};
  const auto &clauseList{std::get<parser::OmpClauseList>(x.t)};
  for (const auto &clause : clauseList.v) {
    if (const auto *alloc{
            std::get_if<parser::OmpClause::Allocate>(&clause.u)}) {
      CheckAllNamesInAllocateStmt(dir.source,
          std::get<parser::OmpObjectList>(alloc->v.t),
          std::get<parser::Statement<parser::AllocateStmt>>(x.t).statement);

      auto &modifiers{OmpGetModifiers(alloc->v)};
      bool hasAllocator{
          OmpGetUniqueModifier<parser::OmpAllocatorSimpleModifier>(modifiers) ||
          OmpGetUniqueModifier<parser::OmpAllocatorComplexModifier>(modifiers)};

      // TODO: As with allocate directive, exclude the case when a requires
      //       directive with the dynamic_allocators clause is present in
      //       the same compilation unit (OMP5.0 2.11.3).
      if (IsNestedInDirective(llvm::omp::Directive::OMPD_target) &&
          !hasAllocator) {
        context_.Say(x.source,
            "ALLOCATORS directives that appear in a TARGET region "
            "must specify an allocator"_err_en_US);
      }
    }
  }
  PopContext();
}

static bool IsPrivatizable(const Symbol *sym) {
  auto *misc{sym->detailsIf<MiscDetails>()};
  return IsVariableName(*sym) && !IsProcedure(*sym) && !IsNamedConstant(*sym) &&
      ( // OpenMP 5.2, 5.1.1: Assumed-size arrays are shared
          !semantics::IsAssumedSizeArray(*sym) ||
          // If CrayPointer is among the DSA list then the
          // CrayPointee is Privatizable
          sym->test(Symbol::Flag::CrayPointee)) &&
      !sym->owner().IsDerivedType() &&
      sym->owner().kind() != Scope::Kind::ImpliedDos &&
      sym->owner().kind() != Scope::Kind::Forall &&
      !sym->detailsIf<semantics::AssocEntityDetails>() &&
      !sym->detailsIf<semantics::NamelistDetails>() &&
      (!misc ||
          (misc->kind() != MiscDetails::Kind::ComplexPartRe &&
              misc->kind() != MiscDetails::Kind::ComplexPartIm &&
              misc->kind() != MiscDetails::Kind::KindParamInquiry &&
              misc->kind() != MiscDetails::Kind::LenParamInquiry &&
              misc->kind() != MiscDetails::Kind::ConstructName));
}

void OmpAttributeVisitor::CreateImplicitSymbols(
    const Symbol *symbol, std::optional<Symbol::Flag> setFlag) {
  if (!IsPrivatizable(symbol)) {
    return;
  }

  // Implicitly determined DSAs
  // OMP 5.2 5.1.1 - Variables Referenced in a Construct
  Symbol *lastDeclSymbol = nullptr;
  std::optional<Symbol::Flag> prevDSA;
  for (int dirDepth{0}; dirDepth < (int)dirContext_.size(); ++dirDepth) {
    DirContext &dirContext = dirContext_[dirDepth];
    std::optional<Symbol::Flag> dsa;

    for (auto symMap : dirContext.objectWithDSA) {
      // if the `symbol` already has a data-sharing attribute
      if (symMap.first->name() == symbol->name()) {
        dsa = symMap.second;
        break;
      }
    }

    // When handling each implicit rule for a given symbol, one of the
    // following 3 actions may be taken:
    // 1. Declare a new private symbol.
    // 2. Create a new association symbol with no flags, that will represent
    //    a shared symbol in the current scope. Note that symbols without
    //    any private flags are considered as shared.
    // 3. Use the last declared private symbol, by inserting a new symbol
    //    in the scope being processed, associated with it.
    //    If no private symbol was declared previously, then no association
    //    is needed and the symbol from the enclosing scope will be
    //    inherited by the current one.
    //
    // Because of how symbols are collected in lowering, not inserting a new
    // symbol in the last case could lead to the conclusion that a symbol
    // from an enclosing construct was declared in the current construct,
    // which would result in wrong privatization code being generated.
    // Consider the following example:
    //
    // !$omp parallel default(private)              ! p1
    //   !$omp parallel default(private) shared(x)  ! p2
    //     x = 10
    //   !$omp end parallel
    // !$omp end parallel
    //
    // If a new x symbol was not inserted in the inner parallel construct
    // (p2), it would use the x symbol definition from the enclosing scope.
    // Then, when p2's default symbols were collected in lowering, the x
    // symbol from the outer parallel construct (p1) would be collected, as
    // it would have the private flag set.
    // This would make x appear to be defined in p2, causing it to be
    // privatized in p2 and its privatization in p1 to be skipped.
    auto makePrivateSymbol = [&](Symbol::Flag flag) {
      const Symbol *hostSymbol =
          lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate();
      lastDeclSymbol = DeclareNewPrivateAccessEntity(
          *hostSymbol, flag, context_.FindScope(dirContext.directiveSource));
      if (setFlag) {
        lastDeclSymbol->set(*setFlag);
      }
      return lastDeclSymbol;
    };
    auto makeSharedSymbol = [&](std::optional<Symbol::Flag> flag = {}) {
      const Symbol *hostSymbol =
          lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate();
      Symbol &assocSymbol = MakeAssocSymbol(symbol->name(), *hostSymbol,
          context_.FindScope(dirContext.directiveSource));
      if (flag) {
        assocSymbol.set(*flag);
      }
    };
    auto useLastDeclSymbol = [&]() {
      if (lastDeclSymbol) {
        makeSharedSymbol();
      }
    };

    bool taskGenDir = llvm::omp::taskGeneratingSet.test(dirContext.directive);
    bool targetDir = llvm::omp::allTargetSet.test(dirContext.directive);
    bool parallelDir = llvm::omp::allParallelSet.test(dirContext.directive);
    bool teamsDir = llvm::omp::allTeamsSet.test(dirContext.directive);

    if (dsa.has_value()) {
      if (dsa.value() == Symbol::Flag::OmpShared &&
          (parallelDir || taskGenDir || teamsDir)) {
        makeSharedSymbol(Symbol::Flag::OmpShared);
      }
      // Private symbols will have been declared already.
      prevDSA = dsa;
      continue;
    }

    if (dirContext.defaultDSA == Symbol::Flag::OmpPrivate ||
        dirContext.defaultDSA == Symbol::Flag::OmpFirstPrivate ||
        dirContext.defaultDSA == Symbol::Flag::OmpShared) {
      // 1) default
      // Allowed only with parallel, teams and task generating constructs.
      if (!parallelDir && !taskGenDir && !teamsDir) {
        return;
      }
      if (dirContext.defaultDSA != Symbol::Flag::OmpShared) {
        makePrivateSymbol(dirContext.defaultDSA);
      } else {
        makeSharedSymbol();
      }
      dsa = dirContext.defaultDSA;
    } else if (parallelDir) {
      // 2) parallel -> shared
      makeSharedSymbol();
      dsa = Symbol::Flag::OmpShared;
    } else if (!taskGenDir && !targetDir) {
      // 3) enclosing context
      useLastDeclSymbol();
      dsa = prevDSA;
    } else if (targetDir) {
      // TODO 4) not mapped target variable -> firstprivate
      dsa = prevDSA;
    } else if (taskGenDir) {
      // TODO 5) dummy arg in orphaned taskgen construct -> firstprivate
      if (prevDSA == Symbol::Flag::OmpShared) {
        // 6) shared in enclosing context -> shared
        makeSharedSymbol();
        dsa = Symbol::Flag::OmpShared;
      } else {
        // 7) firstprivate
        dsa = Symbol::Flag::OmpFirstPrivate;
        makePrivateSymbol(*dsa)->set(Symbol::Flag::OmpImplicit);
      }
    }
    prevDSA = dsa;
  }
}

// For OpenMP constructs, check all the data-refs within the constructs
// and adjust the symbol for each Name if necessary
void OmpAttributeVisitor::Post(const parser::Name &name) {
  auto *symbol{name.symbol};

  if (symbol && !dirContext_.empty() && GetContext().withinConstruct) {
    if (IsPrivatizable(symbol) && !IsObjectWithDSA(*symbol)) {
      // TODO: create a separate function to go through the rules for
      //       predetermined, explicitly determined, and implicitly
      //       determined data-sharing attributes (2.15.1.1).
      if (Symbol * found{currScope().FindSymbol(name.source)}) {
        if (symbol != found) {
          name.symbol = found; // adjust the symbol within region
        } else if (GetContext().defaultDSA == Symbol::Flag::OmpNone &&
            !symbol->test(Symbol::Flag::OmpThreadprivate) &&
            // Exclude indices of sequential loops that are privatised in
            // the scope of the parallel region, and not in this scope.
            // TODO: check whether this should be caught in IsObjectWithDSA
            !symbol->test(Symbol::Flag::OmpPrivate)) {
          if (symbol->test(Symbol::Flag::CrayPointee)) {
            std::string crayPtrName{
                semantics::GetCrayPointer(*symbol).name().ToString()};
            if (!IsObjectWithDSA(*currScope().FindSymbol(crayPtrName)))
              context_.Say(name.source,
                  "The DEFAULT(NONE) clause requires that the Cray Pointer '%s' must be listed in a data-sharing attribute clause"_err_en_US,
                  crayPtrName);
          } else {
            context_.Say(name.source,
                "The DEFAULT(NONE) clause requires that '%s' must be listed in a data-sharing attribute clause"_err_en_US,
                symbol->name());
          }
        }
      }
    }

    if (Symbol * found{currScope().FindSymbol(name.source)}) {
      if (found->test(semantics::Symbol::Flag::OmpThreadprivate))
        return;
    }

    CreateImplicitSymbols(symbol);
  } // within OpenMP construct
}

Symbol *OmpAttributeVisitor::ResolveName(const parser::Name *name) {
  if (auto *resolvedSymbol{
          name ? GetContext().scope.FindSymbol(name->source) : nullptr}) {
    name->symbol = resolvedSymbol;
    return resolvedSymbol;
  } else {
    return nullptr;
  }
}

void OmpAttributeVisitor::ResolveOmpName(
    const parser::Name &name, Symbol::Flag ompFlag) {
  if (ResolveName(&name)) {
    if (auto *resolvedSymbol{ResolveOmp(name, ompFlag, currScope())}) {
      if (dataSharingAttributeFlags.test(ompFlag)) {
        AddToContextObjectWithDSA(*resolvedSymbol, ompFlag);
      }
    }
  } else if (ompFlag == Symbol::Flag::OmpCriticalLock) {
    const auto pair{
        GetContext().scope.try_emplace(name.source, Attrs{}, UnknownDetails{})};
    CHECK(pair.second);
    name.symbol = &pair.first->second.get();
  }
}

void OmpAttributeVisitor::ResolveOmpNameList(
    const std::list<parser::Name> &nameList, Symbol::Flag ompFlag) {
  for (const auto &name : nameList) {
    ResolveOmpName(name, ompFlag);
  }
}

Symbol *OmpAttributeVisitor::ResolveOmpCommonBlockName(
    const parser::Name *name) {
  if (!name) {
    return nullptr;
  }
  if (auto *cb{GetProgramUnitOrBlockConstructContaining(GetContext().scope)
                   .FindCommonBlock(name->source)}) {
    name->symbol = cb;
    return cb;
  }
  return nullptr;
}

// Use this function over ResolveOmpName when an omp object's scope needs
// resolving, it's symbol flag isn't important and a simple check for resolution
// failure is desired. Using ResolveOmpName means needing to work with the
// context to check for failure, whereas here a pointer comparison is all that's
// needed.
Symbol *OmpAttributeVisitor::ResolveOmpObjectScope(const parser::Name *name) {

  // TODO: Investigate whether the following block can be replaced by, or
  // included in, the ResolveOmpName function
  if (auto *prev{name ? GetContext().scope.parent().FindSymbol(name->source)
                      : nullptr}) {
    name->symbol = prev;
    return nullptr;
  }

  // TODO: Investigate whether the following block can be replaced by, or
  // included in, the ResolveOmpName function
  if (auto *ompSymbol{
          name ? GetContext().scope.FindSymbol(name->source) : nullptr}) {
    name->symbol = ompSymbol;
    return ompSymbol;
  }
  return nullptr;
}

void OmpAttributeVisitor::ResolveOmpObjectList(
    const parser::OmpObjectList &ompObjectList, Symbol::Flag ompFlag) {
  for (const auto &ompObject : ompObjectList.v) {
    ResolveOmpObject(ompObject, ompFlag);
  }
}

void OmpAttributeVisitor::ResolveOmpObject(
    const parser::OmpObject &ompObject, Symbol::Flag ompFlag) {
  common::visit(
      common::visitors{
          [&](const parser::Designator &designator) {
            if (const auto *name{
                    semantics::getDesignatorNameIfDataRef(designator)}) {
              if (auto *symbol{ResolveOmp(*name, ompFlag, currScope())}) {
                auto checkExclusivelists =
                    [&](const Symbol *symbol1, Symbol::Flag firstOmpFlag,
                        const Symbol *symbol2, Symbol::Flag secondOmpFlag) {
                      if ((symbol1->test(firstOmpFlag) &&
                              symbol2->test(secondOmpFlag)) ||
                          (symbol1->test(secondOmpFlag) &&
                              symbol2->test(firstOmpFlag))) {
                        context_.Say(designator.source,
                            "Variable '%s' may not "
                            "appear on both %s and %s "
                            "clauses on a %s construct"_err_en_US,
                            symbol2->name(),
                            Symbol::OmpFlagToClauseName(firstOmpFlag),
                            Symbol::OmpFlagToClauseName(secondOmpFlag),
                            parser::ToUpperCaseLetters(
                                llvm::omp::getOpenMPDirectiveName(
                                    GetContext().directive)
                                    .str()));
                      }
                    };
                if (dataCopyingAttributeFlags.test(ompFlag)) {
                  CheckDataCopyingClause(*name, *symbol, ompFlag);
                } else {
                  AddToContextObjectWithDSA(*symbol, ompFlag);
                  if (dataSharingAttributeFlags.test(ompFlag)) {
                    CheckMultipleAppearances(*name, *symbol, ompFlag);
                  }
                  if (privateDataSharingAttributeFlags.test(ompFlag)) {
                    CheckObjectIsPrivatizable(*name, *symbol, ompFlag);
                  }

                  if (ompFlag == Symbol::Flag::OmpAllocate) {
                    AddAllocateName(name);
                  }
                }
                if (ompFlag == Symbol::Flag::OmpDeclarativeAllocateDirective &&
                    IsAllocatable(*symbol) &&
                    !IsNestedInDirective(llvm::omp::Directive::OMPD_allocate)) {
                  context_.Say(designator.source,
                      "List items specified in the ALLOCATE directive must not "
                      "have the ALLOCATABLE attribute unless the directive is "
                      "associated with an ALLOCATE statement"_err_en_US);
                }
                if ((ompFlag == Symbol::Flag::OmpDeclarativeAllocateDirective ||
                        ompFlag ==
                            Symbol::Flag::OmpExecutableAllocateDirective) &&
                    ResolveOmpObjectScope(name) == nullptr) {
                  context_.Say(designator.source, // 2.15.3
                      "List items must be declared in the same scoping unit "
                      "in which the %s directive appears"_err_en_US,
                      parser::ToUpperCaseLetters(
                          llvm::omp::getOpenMPDirectiveName(
                              GetContext().directive)
                              .str()));
                }
                if (ompFlag == Symbol::Flag::OmpReduction) {
                  const Symbol &ultimateSymbol{symbol->GetUltimate()};
                  // Using variables inside of a namelist in OpenMP reductions
                  // is allowed by the standard, but is not allowed for
                  // privatisation. This looks like an oversight. If the
                  // namelist is hoisted to a global, we cannot apply the
                  // mapping for the reduction variable: resulting in incorrect
                  // results. Disabling this hoisting could make some real
                  // production code go slower. See discussion in #109303
                  if (ultimateSymbol.test(Symbol::Flag::InNamelist)) {
                    context_.Say(name->source,
                        "Variable '%s' in NAMELIST cannot be in a REDUCTION clause"_err_en_US,
                        name->ToString());
                  }
                }
                if (ompFlag == Symbol::Flag::OmpInclusiveScan ||
                    ompFlag == Symbol::Flag::OmpExclusiveScan) {
                  if (!symbol->test(Symbol::Flag::OmpInScanReduction)) {
                    context_.Say(name->source,
                        "List item %s must appear in REDUCTION clause "
                        "with the INSCAN modifier of the parent "
                        "directive"_err_en_US,
                        name->ToString());
                  }
                }
                if (GetContext().directive ==
                    llvm::omp::Directive::OMPD_target_data) {
                  checkExclusivelists(symbol, Symbol::Flag::OmpUseDevicePtr,
                      symbol, Symbol::Flag::OmpUseDeviceAddr);
                }
                if (llvm::omp::allDistributeSet.test(GetContext().directive)) {
                  checkExclusivelists(symbol, Symbol::Flag::OmpFirstPrivate,
                      symbol, Symbol::Flag::OmpLastPrivate);
                }
                if (llvm::omp::allTargetSet.test(GetContext().directive)) {
                  checkExclusivelists(symbol, Symbol::Flag::OmpIsDevicePtr,
                      symbol, Symbol::Flag::OmpHasDeviceAddr);
                  const auto *hostAssocSym{symbol};
                  if (!(symbol->test(Symbol::Flag::OmpIsDevicePtr) ||
                          symbol->test(Symbol::Flag::OmpHasDeviceAddr))) {
                    if (const auto *details{
                            symbol->detailsIf<HostAssocDetails>()}) {
                      hostAssocSym = &details->symbol();
                    }
                  }
                  Symbol::Flag dataMappingAttributeFlags[] = {
                      Symbol::Flag::OmpMapTo, Symbol::Flag::OmpMapFrom,
                      Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapAlloc,
                      Symbol::Flag::OmpMapRelease, Symbol::Flag::OmpMapDelete,
                      Symbol::Flag::OmpIsDevicePtr,
                      Symbol::Flag::OmpHasDeviceAddr};

                  Symbol::Flag dataSharingAttributeFlags[] = {
                      Symbol::Flag::OmpPrivate, Symbol::Flag::OmpFirstPrivate,
                      Symbol::Flag::OmpLastPrivate, Symbol::Flag::OmpShared,
                      Symbol::Flag::OmpLinear};

                  // For OMP TARGET TEAMS directive some sharing attribute
                  // flags and mapping attribute flags can co-exist.
                  if (!(llvm::omp::allTeamsSet.test(GetContext().directive) ||
                          llvm::omp::allParallelSet.test(
                              GetContext().directive))) {
                    for (Symbol::Flag ompFlag1 : dataMappingAttributeFlags) {
                      for (Symbol::Flag ompFlag2 : dataSharingAttributeFlags) {
                        checkExclusivelists(
                            hostAssocSym, ompFlag1, symbol, ompFlag2);
                      }
                    }
                  }
                }
              }
            } else {
              // Array sections to be changed to substrings as needed
              if (AnalyzeExpr(context_, designator)) {
                if (std::holds_alternative<parser::Substring>(designator.u)) {
                  context_.Say(designator.source,
                      "Substrings are not allowed on OpenMP "
                      "directives or clauses"_err_en_US);
                }
              }
              // other checks, more TBD
            }
          },
          [&](const parser::Name &name) { // common block
            if (auto *symbol{ResolveOmpCommonBlockName(&name)}) {
              if (!dataCopyingAttributeFlags.test(ompFlag)) {
                CheckMultipleAppearances(
                    name, *symbol, Symbol::Flag::OmpCommonBlock);
              }
              // 2.15.3 When a named common block appears in a list, it has the
              // same meaning as if every explicit member of the common block
              // appeared in the list
              auto &details{symbol->get<CommonBlockDetails>()};
              unsigned index{0};
              for (auto &object : details.objects()) {
                if (auto *resolvedObject{
                        ResolveOmp(*object, ompFlag, currScope())}) {
                  if (dataCopyingAttributeFlags.test(ompFlag)) {
                    CheckDataCopyingClause(name, *resolvedObject, ompFlag);
                  } else {
                    AddToContextObjectWithDSA(*resolvedObject, ompFlag);
                  }
                  details.replace_object(*resolvedObject, index);
                }
                index++;
              }
            } else {
              context_.Say(name.source, // 2.15.3
                  "COMMON block must be declared in the same scoping unit "
                  "in which the OpenMP directive or clause appears"_err_en_US);
            }
          },
      },
      ompObject.u);
}

Symbol *OmpAttributeVisitor::ResolveOmp(
    const parser::Name &name, Symbol::Flag ompFlag, Scope &scope) {
  if (ompFlagsRequireNewSymbol.test(ompFlag)) {
    return DeclarePrivateAccessEntity(name, ompFlag, scope);
  } else {
    return DeclareOrMarkOtherAccessEntity(name, ompFlag);
  }
}

Symbol *OmpAttributeVisitor::ResolveOmp(
    Symbol &symbol, Symbol::Flag ompFlag, Scope &scope) {
  if (ompFlagsRequireNewSymbol.test(ompFlag)) {
    return DeclarePrivateAccessEntity(symbol, ompFlag, scope);
  } else {
    return DeclareOrMarkOtherAccessEntity(symbol, ompFlag);
  }
}

Symbol *OmpAttributeVisitor::DeclareOrMarkOtherAccessEntity(
    const parser::Name &name, Symbol::Flag ompFlag) {
  Symbol *prev{currScope().FindSymbol(name.source)};
  if (!name.symbol || !prev) {
    return nullptr;
  } else if (prev != name.symbol) {
    name.symbol = prev;
  }
  return DeclareOrMarkOtherAccessEntity(*prev, ompFlag);
}

Symbol *OmpAttributeVisitor::DeclareOrMarkOtherAccessEntity(
    Symbol &object, Symbol::Flag ompFlag) {
  if (ompFlagsRequireMark.test(ompFlag)) {
    object.set(ompFlag);
  }
  return &object;
}

static bool WithMultipleAppearancesOmpException(
    const Symbol &symbol, Symbol::Flag flag) {
  return (flag == Symbol::Flag::OmpFirstPrivate &&
             symbol.test(Symbol::Flag::OmpLastPrivate)) ||
      (flag == Symbol::Flag::OmpLastPrivate &&
          symbol.test(Symbol::Flag::OmpFirstPrivate));
}

void OmpAttributeVisitor::CheckMultipleAppearances(
    const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
  const auto *target{&symbol};
  if (ompFlagsRequireNewSymbol.test(ompFlag)) {
    if (const auto *details{symbol.detailsIf<HostAssocDetails>()}) {
      target = &details->symbol();
    }
  }
  if (HasDataSharingAttributeObject(target->GetUltimate()) &&
      !WithMultipleAppearancesOmpException(symbol, ompFlag)) {
    context_.Say(name.source,
        "'%s' appears in more than one data-sharing clause "
        "on the same OpenMP directive"_err_en_US,
        name.ToString());
  } else {
    AddDataSharingAttributeObject(target->GetUltimate());
    if (privateDataSharingAttributeFlags.test(ompFlag)) {
      AddPrivateDataSharingAttributeObjects(*target);
    }
  }
}

void ResolveAccParts(SemanticsContext &context, const parser::ProgramUnit &node,
    Scope *topScope) {
  if (context.IsEnabled(common::LanguageFeature::OpenACC)) {
    AccAttributeVisitor{context, topScope}.Walk(node);
  }
}

void ResolveOmpParts(
    SemanticsContext &context, const parser::ProgramUnit &node) {
  if (context.IsEnabled(common::LanguageFeature::OpenMP)) {
    OmpAttributeVisitor{context}.Walk(node);
    if (!context.AnyFatalError()) {
      // The data-sharing attribute of the loop iteration variable for a
      // sequential loop (2.15.1.1) can only be determined when visiting
      // the corresponding DoConstruct, a second walk is to adjust the
      // symbols for all the data-refs of that loop iteration variable
      // prior to the DoConstruct.
      OmpAttributeVisitor{context}.Walk(node);
    }
  }
}

void ResolveOmpTopLevelParts(
    SemanticsContext &context, const parser::Program &program) {
  if (!context.IsEnabled(common::LanguageFeature::OpenMP)) {
    return;
  }

  // Gather REQUIRES clauses from all non-module top-level program unit symbols,
  // combine them together ensuring compatibility and apply them to all these
  // program units. Modules are skipped because their REQUIRES clauses should be
  // propagated via USE statements instead.
  WithOmpDeclarative::RequiresFlags combinedFlags;
  std::optional<common::OmpAtomicDefaultMemOrderType> combinedMemOrder;

  // Function to go through non-module top level program units and extract
  // REQUIRES information to be processed by a function-like argument.
  auto processProgramUnits{[&](auto processFn) {
    for (const parser::ProgramUnit &unit : program.v) {
      if (!std::holds_alternative<common::Indirection<parser::Module>>(
              unit.u) &&
          !std::holds_alternative<common::Indirection<parser::Submodule>>(
              unit.u) &&
          !std::holds_alternative<
              common::Indirection<parser::CompilerDirective>>(unit.u)) {
        Symbol *symbol{common::visit(
            [&context](auto &x) {
              Scope *scope = GetScope(context, x.value());
              return scope ? scope->symbol() : nullptr;
            },
            unit.u)};
        // FIXME There is no symbol defined for MainProgram units in certain
        // circumstances, so REQUIRES information has no place to be stored in
        // these cases.
        if (!symbol) {
          continue;
        }
        common::visit(
            [&](auto &details) {
              if constexpr (std::is_convertible_v<decltype(&details),
                                WithOmpDeclarative *>) {
                processFn(*symbol, details);
              }
            },
            symbol->details());
      }
    }
  }};

  // Combine global REQUIRES information from all program units except modules
  // and submodules.
  processProgramUnits([&](Symbol &symbol, WithOmpDeclarative &details) {
    if (const WithOmpDeclarative::RequiresFlags *
        flags{details.ompRequires()}) {
      combinedFlags |= *flags;
    }
    if (const common::OmpAtomicDefaultMemOrderType *
        memOrder{details.ompAtomicDefaultMemOrder()}) {
      if (combinedMemOrder && *combinedMemOrder != *memOrder) {
        context.Say(symbol.scope()->sourceRange(),
            "Conflicting '%s' REQUIRES clauses found in compilation "
            "unit"_err_en_US,
            parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(
                llvm::omp::Clause::OMPC_atomic_default_mem_order)
                                           .str()));
      }
      combinedMemOrder = *memOrder;
    }
  });

  // Update all program units except modules and submodules with the combined
  // global REQUIRES information.
  processProgramUnits([&](Symbol &, WithOmpDeclarative &details) {
    if (combinedFlags.any()) {
      details.set_ompRequires(combinedFlags);
    }
    if (combinedMemOrder) {
      details.set_ompAtomicDefaultMemOrder(*combinedMemOrder);
    }
  });
}

static bool IsSymbolInCommonBlock(const Symbol &symbol) {
  // TODO Improve the performance of this predicate function.
  //      Going through all symbols sequentially, in all common blocks, can be
  //      slow when there are many symbols. A possible optimization is to add
  //      an OmpInCommonBlock flag to Symbol, to make it possible to quickly
  //      test if a given symbol is in a common block.
  for (const auto &cb : symbol.owner().commonBlocks()) {
    if (IsCommonBlockContaining(cb.second.get(), symbol)) {
      return true;
    }
  }
  return false;
}

static bool IsSymbolThreadprivate(const Symbol &symbol) {
  if (const auto *details{symbol.detailsIf<HostAssocDetails>()}) {
    return details->symbol().test(Symbol::Flag::OmpThreadprivate);
  }
  return symbol.test(Symbol::Flag::OmpThreadprivate);
}

static bool IsSymbolPrivate(const Symbol &symbol) {
  if (symbol.test(Symbol::Flag::OmpPrivate) ||
      symbol.test(Symbol::Flag::OmpFirstPrivate)) {
    return true;
  }
  // A symbol that has not gone through constructs that may privatize the
  // original symbol may be predetermined as private.
  // (OMP 5.2 5.1.1 - Variables Referenced in a Construct)
  if (symbol == symbol.GetUltimate()) {
    switch (symbol.owner().kind()) {
    case Scope::Kind::MainProgram:
    case Scope::Kind::Subprogram:
    case Scope::Kind::BlockConstruct:
      return !symbol.attrs().test(Attr::SAVE) &&
          !symbol.attrs().test(Attr::PARAMETER) && !IsAssumedShape(symbol) &&
          !IsSymbolInCommonBlock(symbol);
    default:
      return false;
    }
  }
  return false;
}

void OmpAttributeVisitor::CheckDataCopyingClause(
    const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
  if (ompFlag == Symbol::Flag::OmpCopyIn) {
    // List of items/objects that can appear in a 'copyin' clause must be
    // 'threadprivate'
    if (!IsSymbolThreadprivate(symbol)) {
      context_.Say(name.source,
          "Non-THREADPRIVATE object '%s' in COPYIN clause"_err_en_US,
          symbol.name());
    }
  } else if (ompFlag == Symbol::Flag::OmpCopyPrivate &&
      GetContext().directive == llvm::omp::Directive::OMPD_single) {
    // A list item that appears in a 'copyprivate' clause may not appear on a
    // 'private' or 'firstprivate' clause on a single construct
    if (IsObjectWithDSA(symbol) &&
        (symbol.test(Symbol::Flag::OmpPrivate) ||
            symbol.test(Symbol::Flag::OmpFirstPrivate))) {
      context_.Say(name.source,
          "COPYPRIVATE variable '%s' may not appear on a PRIVATE or "
          "FIRSTPRIVATE clause on a SINGLE construct"_err_en_US,
          symbol.name());
    } else if (!IsSymbolThreadprivate(symbol) && !IsSymbolPrivate(symbol)) {
      // List of items/objects that can appear in a 'copyprivate' clause must be
      // either 'private' or 'threadprivate' in enclosing context.
      context_.Say(name.source,
          "COPYPRIVATE variable '%s' is not PRIVATE or THREADPRIVATE in "
          "outer context"_err_en_US,
          symbol.name());
    }
  }
}

void OmpAttributeVisitor::CheckObjectIsPrivatizable(
    const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
  const auto &ultimateSymbol{symbol.GetUltimate()};
  llvm::StringRef clauseName{"PRIVATE"};
  if (ompFlag == Symbol::Flag::OmpFirstPrivate) {
    clauseName = "FIRSTPRIVATE";
  } else if (ompFlag == Symbol::Flag::OmpLastPrivate) {
    clauseName = "LASTPRIVATE";
  }

  if (ultimateSymbol.test(Symbol::Flag::InNamelist)) {
    context_.Say(name.source,
        "Variable '%s' in NAMELIST cannot be in a %s clause"_err_en_US,
        name.ToString(), clauseName.str());
  }

  if (ultimateSymbol.has<AssocEntityDetails>()) {
    context_.Say(name.source,
        "Variable '%s' in ASSOCIATE cannot be in a %s clause"_err_en_US,
        name.ToString(), clauseName.str());
  }

  if (stmtFunctionExprSymbols_.find(ultimateSymbol) !=
      stmtFunctionExprSymbols_.end()) {
    context_.Say(name.source,
        "Variable '%s' in statement function expression cannot be in a "
        "%s clause"_err_en_US,
        name.ToString(), clauseName.str());
  }
}

void OmpAttributeVisitor::CheckSourceLabel(const parser::Label &label) {
  // Get the context to check if the statement causing a jump to the 'label' is
  // in an enclosing OpenMP construct
  std::optional<DirContext> thisContext{GetContextIf()};
  sourceLabels_.emplace(
      label, std::make_pair(currentStatementSource_, thisContext));
  // Check if the statement with 'label' to which a jump is being introduced
  // has already been encountered
  auto it{targetLabels_.find(label)};
  if (it != targetLabels_.end()) {
    // Check if both the statement with 'label' and the statement that causes a
    // jump to the 'label' are in the same scope
    CheckLabelContext(currentStatementSource_, it->second.first, thisContext,
        it->second.second);
  }
}

// Check for invalid branch into or out of OpenMP structured blocks
void OmpAttributeVisitor::CheckLabelContext(const parser::CharBlock source,
    const parser::CharBlock target, std::optional<DirContext> sourceContext,
    std::optional<DirContext> targetContext) {
  if (targetContext &&
      (!sourceContext ||
          (sourceContext->scope != targetContext->scope &&
              !DoesScopeContain(
                  &targetContext->scope, sourceContext->scope)))) {
    context_
        .Say(source, "invalid branch into an OpenMP structured block"_err_en_US)
        .Attach(target, "In the enclosing %s directive branched into"_en_US,
            parser::ToUpperCaseLetters(
                llvm::omp::getOpenMPDirectiveName(targetContext->directive)
                    .str()));
  }
  if (sourceContext &&
      (!targetContext ||
          (sourceContext->scope != targetContext->scope &&
              !DoesScopeContain(
                  &sourceContext->scope, targetContext->scope)))) {
    context_
        .Say(source,
            "invalid branch leaving an OpenMP structured block"_err_en_US)
        .Attach(target, "Outside the enclosing %s directive"_en_US,
            parser::ToUpperCaseLetters(
                llvm::omp::getOpenMPDirectiveName(sourceContext->directive)
                    .str()));
  }
}

// Goes through the names in an OmpObjectList and checks if each name appears
// in the given allocate statement
void OmpAttributeVisitor::CheckAllNamesInAllocateStmt(
    const parser::CharBlock &source, const parser::OmpObjectList &ompObjectList,
    const parser::AllocateStmt &allocate) {
  for (const auto &obj : ompObjectList.v) {
    if (const auto *d{std::get_if<parser::Designator>(&obj.u)}) {
      if (const auto *ref{std::get_if<parser::DataRef>(&d->u)}) {
        if (const auto *n{std::get_if<parser::Name>(&ref->u)}) {
          CheckNameInAllocateStmt(source, *n, allocate);
        }
      }
    }
  }
}

void OmpAttributeVisitor::CheckNameInAllocateStmt(
    const parser::CharBlock &source, const parser::Name &name,
    const parser::AllocateStmt &allocate) {
  for (const auto &allocation :
      std::get<std::list<parser::Allocation>>(allocate.t)) {
    const auto &allocObj = std::get<parser::AllocateObject>(allocation.t);
    if (const auto *n{std::get_if<parser::Name>(&allocObj.u)}) {
      if (n->source == name.source) {
        return;
      }
    }
  }
  context_.Say(source,
      "Object '%s' in %s directive not "
      "found in corresponding ALLOCATE statement"_err_en_US,
      name.ToString(),
      parser::ToUpperCaseLetters(
          llvm::omp::getOpenMPDirectiveName(GetContext().directive).str()));
}

void OmpAttributeVisitor::AddOmpRequiresToScope(Scope &scope,
    WithOmpDeclarative::RequiresFlags flags,
    std::optional<common::OmpAtomicDefaultMemOrderType> memOrder) {
  Scope *scopeIter = &scope;
  do {
    if (Symbol * symbol{scopeIter->symbol()}) {
      common::visit(
          [&](auto &details) {
            // Store clauses information into the symbol for the parent and
            // enclosing modules, programs, functions and subroutines.
            if constexpr (std::is_convertible_v<decltype(&details),
                              WithOmpDeclarative *>) {
              if (flags.any()) {
                if (const WithOmpDeclarative::RequiresFlags *
                    otherFlags{details.ompRequires()}) {
                  flags |= *otherFlags;
                }
                details.set_ompRequires(flags);
              }
              if (memOrder) {
                if (details.has_ompAtomicDefaultMemOrder() &&
                    *details.ompAtomicDefaultMemOrder() != *memOrder) {
                  context_.Say(scopeIter->sourceRange(),
                      "Conflicting '%s' REQUIRES clauses found in compilation "
                      "unit"_err_en_US,
                      parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(
                          llvm::omp::Clause::OMPC_atomic_default_mem_order)
                                                     .str()));
                }
                details.set_ompAtomicDefaultMemOrder(*memOrder);
              }
            }
          },
          symbol->details());
    }
    scopeIter = &scopeIter->parent();
  } while (!scopeIter->IsGlobal());
}

void OmpAttributeVisitor::IssueNonConformanceWarning(
    llvm::omp::Directive D, parser::CharBlock source) {
  std::string warnStr;
  llvm::raw_string_ostream warnStrOS(warnStr);
  warnStrOS << "OpenMP directive "
            << parser::ToUpperCaseLetters(
                   llvm::omp::getOpenMPDirectiveName(D).str())
            << " has been deprecated";

  auto setAlternativeStr = [&warnStrOS](llvm::StringRef alt) {
    warnStrOS << ", please use " << alt << " instead.";
  };
  switch (D) {
  case llvm::omp::OMPD_master:
    setAlternativeStr("MASKED");
    break;
  case llvm::omp::OMPD_master_taskloop:
    setAlternativeStr("MASKED TASKLOOP");
    break;
  case llvm::omp::OMPD_master_taskloop_simd:
    setAlternativeStr("MASKED TASKLOOP SIMD");
    break;
  case llvm::omp::OMPD_parallel_master:
    setAlternativeStr("PARALLEL MASKED");
    break;
  case llvm::omp::OMPD_parallel_master_taskloop:
    setAlternativeStr("PARALLEL MASKED TASKLOOP");
    break;
  case llvm::omp::OMPD_parallel_master_taskloop_simd:
    setAlternativeStr("PARALLEL_MASKED TASKLOOP SIMD");
    break;
  case llvm::omp::OMPD_target_loop:
  default:;
  }
  context_.Warn(common::UsageWarning::OpenMPUsage, source, "%s"_warn_en_US,
      warnStrOS.str());
}
} // namespace Fortran::semantics
