//===-- lib/Semantics/check-acc-structure.cpp -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "check-acc-structure.h"
#include "resolve-names-utils.h"
#include "flang/Common/enum-set.h"
#include "flang/Evaluate/tools.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Parser/tools.h"
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include "flang/Semantics/type.h"
#include "flang/Support/Fortran.h"
#include "llvm/Support/AtomicOrdering.h"

#include <optional>

#define CHECK_SIMPLE_CLAUSE(X, Y) \
  void AccStructureChecker::Enter(const parser::AccClause::X &) { \
    CheckAllowed(llvm::acc::Clause::Y); \
  }

#define CHECK_REQ_SCALAR_INT_CONSTANT_CLAUSE(X, Y) \
  void AccStructureChecker::Enter(const parser::AccClause::X &c) { \
    CheckAllowed(llvm::acc::Clause::Y); \
    RequiresConstantPositiveParameter(llvm::acc::Clause::Y, c.v); \
  }

using ReductionOpsSet =
    Fortran::common::EnumSet<Fortran::parser::ReductionOperator::Operator,
        Fortran::parser::ReductionOperator::Operator_enumSize>;

static ReductionOpsSet reductionIntegerSet{
    Fortran::parser::ReductionOperator::Operator::Plus,
    Fortran::parser::ReductionOperator::Operator::Multiply,
    Fortran::parser::ReductionOperator::Operator::Max,
    Fortran::parser::ReductionOperator::Operator::Min,
    Fortran::parser::ReductionOperator::Operator::Iand,
    Fortran::parser::ReductionOperator::Operator::Ior,
    Fortran::parser::ReductionOperator::Operator::Ieor};

static ReductionOpsSet reductionRealSet{
    Fortran::parser::ReductionOperator::Operator::Plus,
    Fortran::parser::ReductionOperator::Operator::Multiply,
    Fortran::parser::ReductionOperator::Operator::Max,
    Fortran::parser::ReductionOperator::Operator::Min};

static ReductionOpsSet reductionComplexSet{
    Fortran::parser::ReductionOperator::Operator::Plus,
    Fortran::parser::ReductionOperator::Operator::Multiply};

static ReductionOpsSet reductionLogicalSet{
    Fortran::parser::ReductionOperator::Operator::And,
    Fortran::parser::ReductionOperator::Operator::Or,
    Fortran::parser::ReductionOperator::Operator::Eqv,
    Fortran::parser::ReductionOperator::Operator::Neqv};

namespace Fortran::semantics {

static constexpr inline AccClauseSet
    computeConstructOnlyAllowedAfterDeviceTypeClauses{
        llvm::acc::Clause::ACCC_async, llvm::acc::Clause::ACCC_wait,
        llvm::acc::Clause::ACCC_num_gangs, llvm::acc::Clause::ACCC_num_workers,
        llvm::acc::Clause::ACCC_vector_length};

static constexpr inline AccClauseSet loopOnlyAllowedAfterDeviceTypeClauses{
    llvm::acc::Clause::ACCC_auto, llvm::acc::Clause::ACCC_collapse,
    llvm::acc::Clause::ACCC_independent, llvm::acc::Clause::ACCC_gang,
    llvm::acc::Clause::ACCC_seq, llvm::acc::Clause::ACCC_tile,
    llvm::acc::Clause::ACCC_vector, llvm::acc::Clause::ACCC_worker};

static constexpr inline AccClauseSet updateOnlyAllowedAfterDeviceTypeClauses{
    llvm::acc::Clause::ACCC_async, llvm::acc::Clause::ACCC_wait};

static constexpr inline AccClauseSet routineOnlyAllowedAfterDeviceTypeClauses{
    llvm::acc::Clause::ACCC_bind, llvm::acc::Clause::ACCC_gang,
    llvm::acc::Clause::ACCC_vector, llvm::acc::Clause::ACCC_worker,
    llvm::acc::Clause::ACCC_seq};

static constexpr inline AccClauseSet routineMutuallyExclusiveClauses{
    llvm::acc::Clause::ACCC_gang, llvm::acc::Clause::ACCC_worker,
    llvm::acc::Clause::ACCC_vector, llvm::acc::Clause::ACCC_seq};

bool AccStructureChecker::CheckAllowedModifier(llvm::acc::Clause clause) {
  if (GetContext().directive == llvm::acc::ACCD_enter_data ||
      GetContext().directive == llvm::acc::ACCD_exit_data) {
    context_.Say(GetContext().clauseSource,
        "Modifier is not allowed for the %s clause "
        "on the %s directive"_err_en_US,
        parser::ToUpperCaseLetters(getClauseName(clause).str()),
        ContextDirectiveAsFortran());
    return true;
  }
  return false;
}

bool AccStructureChecker::IsComputeConstruct(
    llvm::acc::Directive directive) const {
  return directive == llvm::acc::ACCD_parallel ||
      directive == llvm::acc::ACCD_parallel_loop ||
      directive == llvm::acc::ACCD_serial ||
      directive == llvm::acc::ACCD_serial_loop ||
      directive == llvm::acc::ACCD_kernels ||
      directive == llvm::acc::ACCD_kernels_loop;
}

bool AccStructureChecker::IsLoopConstruct(
    llvm::acc::Directive directive) const {
  return directive == llvm::acc::Directive::ACCD_loop ||
      directive == llvm::acc::ACCD_parallel_loop ||
      directive == llvm::acc::ACCD_serial_loop ||
      directive == llvm::acc::ACCD_kernels_loop;
}

std::optional<llvm::acc::Directive>
AccStructureChecker::getParentComputeConstruct() const {
  // Check all nested context skipping the first one.
  for (std::size_t i = dirContext_.size() - 1; i > 0; --i)
    if (IsComputeConstruct(dirContext_[i - 1].directive))
      return dirContext_[i - 1].directive;
  return std::nullopt;
}

bool AccStructureChecker::IsInsideComputeConstruct() const {
  return getParentComputeConstruct().has_value();
}

void AccStructureChecker::CheckNotInComputeConstruct() {
  if (IsInsideComputeConstruct()) {
    context_.Say(GetContext().directiveSource,
        "Directive %s may not be called within a compute region"_err_en_US,
        ContextDirectiveAsFortran());
  }
}

bool AccStructureChecker::IsInsideKernelsConstruct() const {
  if (auto directive = getParentComputeConstruct())
    if (*directive == llvm::acc::ACCD_kernels ||
        *directive == llvm::acc::ACCD_kernels_loop)
      return true;
  return false;
}

void AccStructureChecker::Enter(const parser::AccClause &x) {
  SetContextClause(x);
}

void AccStructureChecker::Leave(const parser::AccClauseList &) {}

void AccStructureChecker::Enter(const parser::OpenACCBlockConstruct &x) {
  const auto &beginBlockDir{std::get<parser::AccBeginBlockDirective>(x.t)};
  const auto &endBlockDir{std::get<parser::AccEndBlockDirective>(x.t)};
  const auto &beginAccBlockDir{
      std::get<parser::AccBlockDirective>(beginBlockDir.t)};

  CheckMatching(beginAccBlockDir, endBlockDir.v);
  PushContextAndClauseSets(beginAccBlockDir.source, beginAccBlockDir.v);
}

void AccStructureChecker::Leave(const parser::OpenACCBlockConstruct &x) {
  const auto &beginBlockDir{std::get<parser::AccBeginBlockDirective>(x.t)};
  const auto &blockDir{std::get<parser::AccBlockDirective>(beginBlockDir.t)};
  const parser::Block &block{std::get<parser::Block>(x.t)};
  switch (blockDir.v) {
  case llvm::acc::Directive::ACCD_kernels:
  case llvm::acc::Directive::ACCD_parallel:
  case llvm::acc::Directive::ACCD_serial:
    // Restriction - line 1004-1005
    CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
        computeConstructOnlyAllowedAfterDeviceTypeClauses);
    // Restriction - line 1001
    CheckNoBranching(block, GetContext().directive, blockDir.source);
    break;
  case llvm::acc::Directive::ACCD_data:
    // Restriction - 2.6.5 pt 1
    // Only a warning is emitted here for portability reason.
    CheckRequireAtLeastOneOf(/*warnInsteadOfError=*/true);
    // Restriction is not formally in the specification but all compilers emit
    // an error and it is likely to be omitted from the spec.
    CheckNoBranching(block, GetContext().directive, blockDir.source);
    break;
  case llvm::acc::Directive::ACCD_host_data:
    // Restriction - line 1746
    CheckRequireAtLeastOneOf();
    break;
  default:
    break;
  }
  dirContext_.pop_back();
}

void AccStructureChecker::Enter(
    const parser::OpenACCStandaloneDeclarativeConstruct &x) {
  const auto &declarativeDir{std::get<parser::AccDeclarativeDirective>(x.t)};
  PushContextAndClauseSets(declarativeDir.source, declarativeDir.v);
}

void AccStructureChecker::Leave(
    const parser::OpenACCStandaloneDeclarativeConstruct &x) {
  // Restriction - line 2409
  CheckAtLeastOneClause();

  // Restriction - line 2417-2418 - In a Fortran module declaration section,
  // only create, copyin, device_resident, and link clauses are allowed.
  const auto &declarativeDir{std::get<parser::AccDeclarativeDirective>(x.t)};
  const auto &scope{context_.FindScope(declarativeDir.source)};
  const Scope &containingScope{GetProgramUnitContaining(scope)};
  if (containingScope.kind() == Scope::Kind::Module) {
    for (auto cl : GetContext().actualClauses) {
      if (cl != llvm::acc::Clause::ACCC_create &&
          cl != llvm::acc::Clause::ACCC_copyin &&
          cl != llvm::acc::Clause::ACCC_device_resident &&
          cl != llvm::acc::Clause::ACCC_link) {
        context_.Say(GetContext().directiveSource,
            "%s clause is not allowed on the %s directive in module "
            "declaration "
            "section"_err_en_US,
            parser::ToUpperCaseLetters(
                llvm::acc::getOpenACCClauseName(cl).str()),
            ContextDirectiveAsFortran());
      }
    }
  }
  dirContext_.pop_back();
}

void AccStructureChecker::Enter(const parser::OpenACCCombinedConstruct &x) {
  const auto &beginCombinedDir{
      std::get<parser::AccBeginCombinedDirective>(x.t)};
  const auto &combinedDir{
      std::get<parser::AccCombinedDirective>(beginCombinedDir.t)};

  // check matching, End directive is optional
  if (const auto &endCombinedDir{
          std::get<std::optional<parser::AccEndCombinedDirective>>(x.t)}) {
    CheckMatching<parser::AccCombinedDirective>(combinedDir, endCombinedDir->v);
  }

  PushContextAndClauseSets(combinedDir.source, combinedDir.v);
}

void AccStructureChecker::Leave(const parser::OpenACCCombinedConstruct &x) {
  const auto &beginBlockDir{std::get<parser::AccBeginCombinedDirective>(x.t)};
  const auto &combinedDir{
      std::get<parser::AccCombinedDirective>(beginBlockDir.t)};
  auto &doCons{std::get<std::optional<parser::DoConstruct>>(x.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:
    // Restriction - line 1004-1005
    CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
        computeConstructOnlyAllowedAfterDeviceTypeClauses |
            loopOnlyAllowedAfterDeviceTypeClauses);
    if (doCons) {
      const parser::Block &block{std::get<parser::Block>(doCons->t)};
      CheckNoBranching(block, GetContext().directive, beginBlockDir.source);
    }
    break;
  default:
    break;
  }
  dirContext_.pop_back();
}

std::optional<std::int64_t> AccStructureChecker::getGangDimensionSize(
    DirectiveContext &dirContext) {
  for (auto it : dirContext.clauseInfo) {
    const auto *clause{it.second};
    if (const auto *gangClause{
            std::get_if<parser::AccClause::Gang>(&clause->u)})
      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)})
              return *v;
      }
  }
  return std::nullopt;
}

void AccStructureChecker::CheckNotInSameOrSubLevelLoopConstruct() {
  for (std::size_t i = dirContext_.size() - 1; i > 0; --i) {
    auto &parent{dirContext_[i - 1]};
    if (IsLoopConstruct(parent.directive)) {
      for (auto parentClause : parent.actualClauses) {
        for (auto cl : GetContext().actualClauses) {
          bool invalid{false};
          if (parentClause == llvm::acc::Clause::ACCC_gang &&
              cl == llvm::acc::Clause::ACCC_gang) {
            if (IsInsideKernelsConstruct()) {
              context_.Say(GetContext().clauseSource,
                  "Nested GANG loops are not allowed in the region of a KERNELS construct"_err_en_US);
            } else {
              auto parentDim = getGangDimensionSize(parent);
              auto currentDim = getGangDimensionSize(GetContext());
              std::int64_t parentDimNum = 1, currentDimNum = 1;
              if (parentDim)
                parentDimNum = *parentDim;
              if (currentDim)
                currentDimNum = *currentDim;
              if (parentDimNum <= currentDimNum) {
                std::string parentDimStr, currentDimStr;
                if (parentDim)
                  parentDimStr = "(dim:" + std::to_string(parentDimNum) + ")";
                if (currentDim)
                  currentDimStr = "(dim:" + std::to_string(currentDimNum) + ")";
                context_.Say(GetContext().clauseSource,
                    "%s%s clause is not allowed in the region of a loop with the %s%s clause"_err_en_US,
                    parser::ToUpperCaseLetters(
                        llvm::acc::getOpenACCClauseName(cl).str()),
                    currentDimStr,
                    parser::ToUpperCaseLetters(
                        llvm::acc::getOpenACCClauseName(parentClause).str()),
                    parentDimStr);
                continue;
              }
            }
          } else if (parentClause == llvm::acc::Clause::ACCC_worker &&
              (cl == llvm::acc::Clause::ACCC_gang ||
                  cl == llvm::acc::Clause::ACCC_worker)) {
            invalid = true;
          } else if (parentClause == llvm::acc::Clause::ACCC_vector &&
              (cl == llvm::acc::Clause::ACCC_gang ||
                  cl == llvm::acc::Clause::ACCC_worker ||
                  cl == llvm::acc::Clause::ACCC_vector)) {
            invalid = true;
          }
          if (invalid)
            context_.Say(GetContext().clauseSource,
                "%s clause is not allowed in the region of a loop with the %s clause"_err_en_US,
                parser::ToUpperCaseLetters(
                    llvm::acc::getOpenACCClauseName(cl).str()),
                parser::ToUpperCaseLetters(
                    llvm::acc::getOpenACCClauseName(parentClause).str()));
        }
      }
    }
    if (IsComputeConstruct(parent.directive))
      break;
  }
}

void AccStructureChecker::Enter(const parser::CallStmt &call) {
  if (dirContext_.empty() || !call.typedCall) {
    return;
  }
  const Symbol *sym{call.typedCall->proc().GetSymbol()};
  if (!sym) {
    return;
  }
  const Symbol &ult{sym->GetUltimate()};
  const auto *subp{ult.detailsIf<SubprogramDetails>()};
  if (!subp || subp->openACCRoutineInfos().empty()) {
    return;
  }
  std::string routineParDim;
  unsigned routineGangDim = 0;
  for (const OpenACCRoutineInfo &ri : subp->openACCRoutineInfos()) {
    if (ri.isGang()) {
      if (unsigned gangDim = ri.gangDim()) {
        routineGangDim = gangDim;
        routineParDim = "GANG(" + std::to_string(gangDim) + ")";
      } else {
        routineGangDim = 1;
        routineParDim = "GANG";
      }
    } else if (ri.isWorker()) {
      routineParDim = "WORKER";
    } else if (ri.isVector()) {
      routineParDim = "VECTOR";
    } else if (ri.isSeq()) {
      routineParDim = "SEQ";
    }
  }

  DirectiveContext &inner{dirContext_.back()};
  for (llvm::acc::Clause cl : inner.actualClauses) {
    if (cl == llvm::acc::Clause::ACCC_vector) {
      if (!routineParDim.empty() && routineParDim != "SEQ") {
        context_.Say(GetContext().clauseSource,
            "Calling %s routine inside VECTOR loop is not allowed"_err_en_US,
            routineParDim);
      }
    }
    if (cl == llvm::acc::Clause::ACCC_worker) {
      if (!routineParDim.empty() &&
          (routineParDim != "SEQ" && routineParDim != "VECTOR")) {
        context_.Say(GetContext().clauseSource,
            "Calling %s routine inside WORKER loop is not allowed"_err_en_US,
            routineParDim);
      }
    }
    if (cl == llvm::acc::Clause::ACCC_gang) {
      const std::optional<std::int64_t> loopGangDim{
          getGangDimensionSize(inner)};
      const std::int64_t loopDimNum{loopGangDim.value_or(1)};
      if (routineGangDim && routineGangDim >= loopDimNum) {
        if (loopGangDim) {
          context_.Say(GetContext().clauseSource,
              "Calling %s routine inside GANG(%s) loop is not allowed"_err_en_US,
              routineParDim, std::to_string(*loopGangDim));
        } else {
          context_.Say(GetContext().clauseSource,
              "Calling %s routine inside GANG loop is not allowed"_err_en_US,
              routineParDim);
        }
      }
    }
  }
}

void AccStructureChecker::Enter(const parser::OpenACCLoopConstruct &x) {
  const auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)};
  const auto &loopDir{std::get<parser::AccLoopDirective>(beginDir.t)};
  PushContextAndClauseSets(loopDir.source, loopDir.v);
}

void AccStructureChecker::Leave(const parser::OpenACCLoopConstruct &x) {
  const auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)};
  const auto &loopDir{std::get<parser::AccLoopDirective>(beginDir.t)};
  if (loopDir.v == llvm::acc::Directive::ACCD_loop) {
    // Restriction - line 1818-1819
    CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
        loopOnlyAllowedAfterDeviceTypeClauses);
    // Restriction - line 1834
    CheckNotAllowedIfClause(llvm::acc::Clause::ACCC_seq,
        {llvm::acc::Clause::ACCC_gang, llvm::acc::Clause::ACCC_vector,
            llvm::acc::Clause::ACCC_worker});
    // Restriction - 2.9.2, 2.9.3, 2.9.4
    CheckNotInSameOrSubLevelLoopConstruct();
  }
  dirContext_.pop_back();
}

void AccStructureChecker::Enter(const parser::OpenACCStandaloneConstruct &x) {
  const auto &standaloneDir{std::get<parser::AccStandaloneDirective>(x.t)};
  PushContextAndClauseSets(standaloneDir.source, standaloneDir.v);
}

void AccStructureChecker::Leave(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:
    // Restriction - line 1310-1311 (ENTER DATA)
    // Restriction - line 1312-1313 (EXIT DATA)
    CheckRequireAtLeastOneOf();
    break;
  case llvm::acc::Directive::ACCD_set:
    // Restriction - line 2610
    CheckRequireAtLeastOneOf();
    // Restriction - line 2602
    CheckNotInComputeConstruct();
    break;
  case llvm::acc::Directive::ACCD_update:
    // Restriction - line 2636
    CheckRequireAtLeastOneOf();
    // Restriction - line 2669
    CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
        updateOnlyAllowedAfterDeviceTypeClauses);
    break;
  case llvm::acc::Directive::ACCD_init:
  case llvm::acc::Directive::ACCD_shutdown:
    // Restriction - line 2525 (INIT)
    // Restriction - line 2561 (SHUTDOWN)
    CheckNotInComputeConstruct();
    break;
  default:
    break;
  }
  dirContext_.pop_back();
}

void AccStructureChecker::Enter(const parser::OpenACCRoutineConstruct &x) {
  PushContextAndClauseSets(x.source, llvm::acc::Directive::ACCD_routine);
  const auto &optName{std::get<std::optional<parser::Name>>(x.t)};
  if (!optName) {
    const auto &verbatim{std::get<parser::Verbatim>(x.t)};
    const auto &scope{context_.FindScope(verbatim.source)};
    const Scope &containingScope{GetProgramUnitContaining(scope)};
    if (containingScope.kind() == Scope::Kind::Module) {
      context_.Say(GetContext().directiveSource,
          "ROUTINE directive without name must appear within the specification "
          "part of a subroutine or function definition, or within an interface "
          "body for a subroutine or function in an interface block"_err_en_US);
    }
  }
}
void AccStructureChecker::Leave(const parser::OpenACCRoutineConstruct &) {
  // Restriction - line 2790
  CheckRequireAtLeastOneOf();
  // Restriction - line 2788-2789
  CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
      routineOnlyAllowedAfterDeviceTypeClauses);
  dirContext_.pop_back();
}

void AccStructureChecker::Enter(const parser::OpenACCWaitConstruct &x) {
  const auto &verbatim{std::get<parser::Verbatim>(x.t)};
  PushContextAndClauseSets(verbatim.source, llvm::acc::Directive::ACCD_wait);
}
void AccStructureChecker::Leave(const parser::OpenACCWaitConstruct &x) {
  dirContext_.pop_back();
}

void AccStructureChecker::Enter(const parser::OpenACCAtomicConstruct &x) {
  PushContextAndClauseSets(x.source, llvm::acc::Directive::ACCD_atomic);
}
void AccStructureChecker::Leave(const parser::OpenACCAtomicConstruct &x) {
  dirContext_.pop_back();
}

void AccStructureChecker::CheckAtomicStmt(
    const parser::AssignmentStmt &assign, const std::string &construct) {
  const auto &var{std::get<parser::Variable>(assign.t)};
  const auto &expr{std::get<parser::Expr>(assign.t)};
  const auto *rhs{GetExpr(context_, expr)};
  const auto *lhs{GetExpr(context_, var)};

  if (lhs) {
    if (lhs->Rank() != 0) {
      context_.Say(expr.source,
          "LHS of atomic %s statement must be scalar"_err_en_US, construct);
    }
    // TODO: Check if lhs is intrinsic type.
  }
  if (rhs) {
    if (rhs->Rank() != 0) {
      context_.Say(var.GetSource(),
          "RHS of atomic %s statement must be scalar"_err_en_US, construct);
    }
    // TODO: Check if rhs is intrinsic type.
  }
}

static constexpr evaluate::operation::OperatorSet validAccAtomicUpdateOperators{
    evaluate::operation::Operator::Add, evaluate::operation::Operator::Mul,
    evaluate::operation::Operator::Sub, evaluate::operation::Operator::Div,
    evaluate::operation::Operator::And, evaluate::operation::Operator::Or,
    evaluate::operation::Operator::Eqv, evaluate::operation::Operator::Neqv,
    evaluate::operation::Operator::Max, evaluate::operation::Operator::Min};

static bool IsValidAtomicUpdateOperation(
    const evaluate::operation::Operator &op) {
  return validAccAtomicUpdateOperators.test(op);
}

// Couldn't reproduce this behavior with evaluate::UnwrapConvertedExpr which
// is similar but only works within a single type category.
static SomeExpr GetExprModuloConversion(const SomeExpr &expr) {
  const auto [op, args]{evaluate::GetTopLevelOperation(expr)};
  // Check: if it is a conversion then it must have at least one argument.
  CHECK(((op != evaluate::operation::Operator::Convert &&
             op != evaluate::operation::Operator::Resize) ||
            args.size() >= 1) &&
      "Invalid conversion operation");
  if ((op == evaluate::operation::Operator::Convert ||
          op == evaluate::operation::Operator::Resize) &&
      args.size() >= 1) {
    return args[0];
  }
  return expr;
}

void AccStructureChecker::CheckAtomicUpdateStmt(
    const parser::AssignmentStmt &assign, const SomeExpr &updateVar,
    const SomeExpr *captureVar) {
  CheckAtomicStmt(assign, "update");
  const auto &expr{std::get<parser::Expr>(assign.t)};
  const auto *rhs{GetExpr(context_, expr)};
  if (rhs) {
    const auto [op, args]{
        evaluate::GetTopLevelOperation(GetExprModuloConversion(*rhs))};
    if (!IsValidAtomicUpdateOperation(op)) {
      context_.Say(expr.source,
          "Invalid atomic update operation, can only use: *, +, -, *, /, and, or, eqv, neqv, max, min, iand, ior, ieor"_err_en_US);
    } else {
      bool foundUpdateVar{false};
      for (const auto &arg : args) {
        if (updateVar == GetExprModuloConversion(arg)) {
          if (foundUpdateVar) {
            context_.Say(expr.source,
                "The updated variable, %s, cannot appear more than once in the atomic update operation"_err_en_US,
                updateVar.AsFortran());
          } else {
            foundUpdateVar = true;
          }
        } else if (evaluate::IsVarSubexpressionOf(updateVar, arg)) {
          // TODO: Get the source location of arg and point to the individual
          // argument.
          context_.Say(expr.source,
              "Arguments to the atomic update operation cannot reference the updated variable, %s, as a subexpression"_err_en_US,
              updateVar.AsFortran());
        }
      }
      if (!foundUpdateVar) {
        context_.Say(expr.source,
            "The RHS of this atomic update statement must reference the updated variable: %s"_err_en_US,
            updateVar.AsFortran());
      }
    }
  }
}

void AccStructureChecker::CheckAtomicWriteStmt(
    const parser::AssignmentStmt &assign, const SomeExpr &updateVar,
    const SomeExpr *captureVar) {
  CheckAtomicStmt(assign, "write");
  const auto &expr{std::get<parser::Expr>(assign.t)};
  const auto *rhs{GetExpr(context_, expr)};
  if (rhs) {
    if (evaluate::IsVarSubexpressionOf(updateVar, *rhs)) {
      context_.Say(expr.source,
          "The RHS of this atomic write statement cannot reference the atomic variable: %s"_err_en_US,
          updateVar.AsFortran());
    }
  }
}

void AccStructureChecker::CheckAtomicCaptureStmt(
    const parser::AssignmentStmt &assign, const SomeExpr *updateVar,
    const SomeExpr &captureVar) {
  CheckAtomicStmt(assign, "capture");
}

void AccStructureChecker::Enter(const parser::AccAtomicCapture &capture) {
  const Fortran::parser::AssignmentStmt &stmt1{
      std::get<Fortran::parser::AccAtomicCapture::Stmt1>(capture.t)
          .v.statement};
  const Fortran::parser::AssignmentStmt &stmt2{
      std::get<Fortran::parser::AccAtomicCapture::Stmt2>(capture.t)
          .v.statement};
  const auto &var1{std::get<parser::Variable>(stmt1.t)};
  const auto &var2{std::get<parser::Variable>(stmt2.t)};
  const auto *lhs1{GetExpr(context_, var1)};
  const auto *lhs2{GetExpr(context_, var2)};
  if (!lhs1 || !lhs2) {
    // Not enough information to check.
    return;
  }
  if (*lhs1 == *lhs2) {
    context_.Say(std::get<parser::Verbatim>(capture.t).source,
        "The variables assigned in this atomic capture construct must be distinct"_err_en_US);
    return;
  }
  const auto &expr1{std::get<parser::Expr>(stmt1.t)};
  const auto &expr2{std::get<parser::Expr>(stmt2.t)};
  const auto *rhs1{GetExpr(context_, expr1)};
  const auto *rhs2{GetExpr(context_, expr2)};
  if (!rhs1 || !rhs2) {
    return;
  }
  bool stmt1CapturesLhs2{*lhs2 == GetExprModuloConversion(*rhs1)};
  bool stmt2CapturesLhs1{*lhs1 == GetExprModuloConversion(*rhs2)};
  if (stmt1CapturesLhs2 && !stmt2CapturesLhs1) {
    if (*lhs2 == GetExprModuloConversion(*rhs2)) {
      // a = b; b = b: Doesn't fit the spec.
      context_.Say(std::get<parser::Verbatim>(capture.t).source,
          "The assignments in this atomic capture construct do not update a variable and capture either its initial or final value"_err_en_US);
      // TODO: Add attatchment that a = b seems to be a capture,
      // but b = b is not a valid update or write.
    } else if (evaluate::IsVarSubexpressionOf(*lhs2, *rhs2)) {
      // Take v = x; x = <expr w/ x> as capture; update
      const auto &updateVar{*lhs2};
      const auto &captureVar{*lhs1};
      CheckAtomicCaptureStmt(stmt1, &updateVar, captureVar);
      CheckAtomicUpdateStmt(stmt2, updateVar, &captureVar);
    } else {
      // Take v = x; x = <expr w/o x> as capture; write
      const auto &updateVar{*lhs2};
      const auto &captureVar{*lhs1};
      CheckAtomicCaptureStmt(stmt1, &updateVar, captureVar);
      CheckAtomicWriteStmt(stmt2, updateVar, &captureVar);
    }
  } else if (stmt2CapturesLhs1 && !stmt1CapturesLhs2) {
    if (*lhs1 == GetExprModuloConversion(*rhs1)) {
      // Error a = a; b = a;
      context_.Say(var1.GetSource(),
          "The first assignment in this atomic capture construct doesn't perform a valid update"_err_en_US);
      // Add attatchment that a = a is not considered an update,
      // but b = a seems to be a capture.
    } else {
      // Take x = <expr>; v = x: as update; capture
      const auto &updateVar{*lhs1};
      const auto &captureVar{*lhs2};
      CheckAtomicUpdateStmt(stmt1, updateVar, &captureVar);
      CheckAtomicCaptureStmt(stmt2, &updateVar, captureVar);
    }
  } else if (stmt1CapturesLhs2 && stmt2CapturesLhs1) {
    // x1 = x2; x2 = x1; Doesn't fit the spec.
    context_.Say(std::get<parser::Verbatim>(capture.t).source,
        "The assignments in this atomic capture construct do not update a variable and capture either its initial or final value"_err_en_US);
    // TODO: Add attatchment that both assignments seem to be captures.
  } else { // !stmt1CapturesLhs2 && !stmt2CapturesLhs1
    // a = <expr != b>; b = <expr != a>; Doesn't fit the spec
    context_.Say(std::get<parser::Verbatim>(capture.t).source,
        "The assignments in this atomic capture construct do not update a variable and capture either its initial or final value"_err_en_US);
    // TODO: Add attatchment that neither assignment seems to be a capture.
  }
}

void AccStructureChecker::Enter(const parser::AccAtomicUpdate &x) {
  const auto &assign{
      std::get<parser::Statement<parser::AssignmentStmt>>(x.t).statement};
  const auto &var{std::get<parser::Variable>(assign.t)};
  if (const auto *updateVar{GetExpr(context_, var)}) {
    CheckAtomicUpdateStmt(assign, *updateVar, /*captureVar=*/nullptr);
  }
}

void AccStructureChecker::Enter(const parser::AccAtomicWrite &x) {
  const auto &assign{
      std::get<parser::Statement<parser::AssignmentStmt>>(x.t).statement};
  const auto &var{std::get<parser::Variable>(assign.t)};
  if (const auto *updateVar{GetExpr(context_, var)}) {
    CheckAtomicWriteStmt(assign, *updateVar, /*captureVar=*/nullptr);
  }
}

void AccStructureChecker::Enter(const parser::AccAtomicRead &x) {
  const auto &assign{
      std::get<parser::Statement<parser::AssignmentStmt>>(x.t).statement};
  const auto &var{std::get<parser::Variable>(assign.t)};
  if (const auto *captureVar{GetExpr(context_, var)}) {
    CheckAtomicCaptureStmt(assign, /*updateVar=*/nullptr, *captureVar);
  }
}

void AccStructureChecker::Enter(const parser::OpenACCCacheConstruct &x) {
  const auto &verbatim = std::get<parser::Verbatim>(x.t);
  PushContextAndClauseSets(verbatim.source, llvm::acc::Directive::ACCD_cache);
  SetContextDirectiveSource(verbatim.source);
  // Check cache directive array section constraints
  const auto &objectListWithModifier =
      std::get<parser::AccObjectListWithModifier>(x.t);
  const auto &objectList =
      std::get<parser::AccObjectList>(objectListWithModifier.t);

  for (const auto &accObject : objectList.v) {
    common::visit(
        common::visitors{
            [&](const parser::Designator &designator) {
              if (const auto *dataRef =
                      std::get_if<parser::DataRef>(&designator.u)) {
                if (const auto *arrayElem =
                        std::get_if<common::Indirection<parser::ArrayElement>>(
                            &dataRef->u)) {
                  for (const auto &subscript :
                      arrayElem->value().Subscripts()) {
                    if (const auto *triplet =
                            std::get_if<parser::SubscriptTriplet>(
                                &subscript.u)) {
                      const auto &stride{std::get<2>(triplet->t)};
                      if (stride) {
                        if (auto strideVal{GetIntValue(*stride)}) {
                          if (*strideVal != 1) {
                            context_.Say(designator.source,
                                "The CACHE directive does not support strided array sections"_err_en_US);
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            [&](const parser::Name &) {
              // Common block names are not expected in cache directive
            }},
        accObject.u);
  }
}
void AccStructureChecker::Leave(const parser::OpenACCCacheConstruct &x) {
  dirContext_.pop_back();
}

// Clause checkers
CHECK_SIMPLE_CLAUSE(Auto, ACCC_auto)
CHECK_SIMPLE_CLAUSE(Attach, ACCC_attach)
CHECK_SIMPLE_CLAUSE(Bind, ACCC_bind)
CHECK_SIMPLE_CLAUSE(Capture, ACCC_capture)
CHECK_SIMPLE_CLAUSE(Default, ACCC_default)
CHECK_SIMPLE_CLAUSE(DefaultAsync, ACCC_default_async)
CHECK_SIMPLE_CLAUSE(Delete, ACCC_delete)
CHECK_SIMPLE_CLAUSE(Detach, ACCC_detach)
CHECK_SIMPLE_CLAUSE(Device, ACCC_device)
CHECK_SIMPLE_CLAUSE(DeviceNum, ACCC_device_num)
CHECK_SIMPLE_CLAUSE(Finalize, ACCC_finalize)
CHECK_SIMPLE_CLAUSE(Firstprivate, ACCC_firstprivate)
CHECK_SIMPLE_CLAUSE(Host, ACCC_host)
CHECK_SIMPLE_CLAUSE(IfPresent, ACCC_if_present)
CHECK_SIMPLE_CLAUSE(Independent, ACCC_independent)
CHECK_SIMPLE_CLAUSE(NoCreate, ACCC_no_create)
CHECK_SIMPLE_CLAUSE(Nohost, ACCC_nohost)
CHECK_SIMPLE_CLAUSE(Private, ACCC_private)
CHECK_SIMPLE_CLAUSE(Read, ACCC_read)
CHECK_SIMPLE_CLAUSE(UseDevice, ACCC_use_device)
CHECK_SIMPLE_CLAUSE(Wait, ACCC_wait)
CHECK_SIMPLE_CLAUSE(Write, ACCC_write)
CHECK_SIMPLE_CLAUSE(Unknown, ACCC_unknown)

void AccStructureChecker::CheckMultipleOccurrenceInDeclare(
    const parser::AccObjectList &list, llvm::acc::Clause clause) {
  if (GetContext().directive != llvm::acc::Directive::ACCD_declare)
    return;
  for (const auto &object : list.v) {
    common::visit(
        common::visitors{
            [&](const parser::Designator &designator) {
              if (const auto *name =
                      parser::GetDesignatorNameIfDataRef(designator)) {
                if (declareSymbols.contains(&name->symbol->GetUltimate())) {
                  if (declareSymbols[&name->symbol->GetUltimate()] == clause) {
                    context_.Warn(common::UsageWarning::OpenAccUsage,
                        GetContext().clauseSource,
                        "'%s' in the %s clause is already present in the same clause in this module"_warn_en_US,
                        name->symbol->name(),
                        parser::ToUpperCaseLetters(
                            llvm::acc::getOpenACCClauseName(clause).str()));
                  } else {
                    context_.Say(GetContext().clauseSource,
                        "'%s' in the %s clause is already present in another "
                        "%s clause in this module"_err_en_US,
                        name->symbol->name(),
                        parser::ToUpperCaseLetters(
                            llvm::acc::getOpenACCClauseName(clause).str()),
                        parser::ToUpperCaseLetters(
                            llvm::acc::getOpenACCClauseName(
                                declareSymbols[&name->symbol->GetUltimate()])
                                .str()));
                  }
                }
                declareSymbols.insert({&name->symbol->GetUltimate(), clause});
              }
            },
            [&](const parser::Name &name) {
              // TODO: check common block
            }},
        object.u);
  }
}

void AccStructureChecker::CheckMultipleOccurrenceInDeclare(
    const parser::AccObjectListWithModifier &list, llvm::acc::Clause clause) {
  const auto &objectList = std::get<Fortran::parser::AccObjectList>(list.t);
  CheckMultipleOccurrenceInDeclare(objectList, clause);
}

void AccStructureChecker::Enter(const parser::AccClause::Async &c) {
  llvm::acc::Clause crtClause = llvm::acc::Clause::ACCC_async;
  CheckAllowed(crtClause);
  CheckAllowedOncePerGroup(crtClause, llvm::acc::Clause::ACCC_device_type);
}

void AccStructureChecker::Enter(const parser::AccClause::Create &c) {
  CheckAllowed(llvm::acc::Clause::ACCC_create);
  const auto &modifierClause{c.v};
  if (const auto &modifier{
          std::get<std::optional<parser::AccDataModifier>>(modifierClause.t)}) {
    if (modifier->v != parser::AccDataModifier::Modifier::Zero) {
      context_.Say(GetContext().clauseSource,
          "Only the ZERO modifier is allowed for the %s clause "
          "on the %s directive"_err_en_US,
          parser::ToUpperCaseLetters(
              llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_create)
                  .str()),
          ContextDirectiveAsFortran());
    }
    if (GetContext().directive == llvm::acc::Directive::ACCD_declare) {
      context_.Say(GetContext().clauseSource,
          "The ZERO modifier is not allowed for the %s clause "
          "on the %s directive"_err_en_US,
          parser::ToUpperCaseLetters(
              llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_create)
                  .str()),
          ContextDirectiveAsFortran());
    }
  }
  CheckMultipleOccurrenceInDeclare(
      modifierClause, llvm::acc::Clause::ACCC_create);
}

void AccStructureChecker::Enter(const parser::AccClause::Copyin &c) {
  CheckAllowed(llvm::acc::Clause::ACCC_copyin);
  const auto &modifierClause{c.v};
  if (const auto &modifier{
          std::get<std::optional<parser::AccDataModifier>>(modifierClause.t)}) {
    if (CheckAllowedModifier(llvm::acc::Clause::ACCC_copyin)) {
      return;
    }
    if (modifier->v != parser::AccDataModifier::Modifier::ReadOnly) {
      context_.Say(GetContext().clauseSource,
          "Only the READONLY modifier is allowed for the %s clause "
          "on the %s directive"_err_en_US,
          parser::ToUpperCaseLetters(
              llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_copyin)
                  .str()),
          ContextDirectiveAsFortran());
    }
  }
  CheckMultipleOccurrenceInDeclare(
      modifierClause, llvm::acc::Clause::ACCC_copyin);
}

void AccStructureChecker::Enter(const parser::AccClause::Copyout &c) {
  CheckAllowed(llvm::acc::Clause::ACCC_copyout);
  const auto &modifierClause{c.v};
  if (const auto &modifier{
          std::get<std::optional<parser::AccDataModifier>>(modifierClause.t)}) {
    if (CheckAllowedModifier(llvm::acc::Clause::ACCC_copyout)) {
      return;
    }
    if (modifier->v != parser::AccDataModifier::Modifier::Zero) {
      context_.Say(GetContext().clauseSource,
          "Only the ZERO modifier is allowed for the %s clause "
          "on the %s directive"_err_en_US,
          parser::ToUpperCaseLetters(
              llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_copyout)
                  .str()),
          ContextDirectiveAsFortran());
    }
    if (GetContext().directive == llvm::acc::Directive::ACCD_declare) {
      context_.Say(GetContext().clauseSource,
          "The ZERO modifier is not allowed for the %s clause "
          "on the %s directive"_err_en_US,
          parser::ToUpperCaseLetters(
              llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_copyout)
                  .str()),
          ContextDirectiveAsFortran());
    }
  }
  CheckMultipleOccurrenceInDeclare(
      modifierClause, llvm::acc::Clause::ACCC_copyout);
}

void AccStructureChecker::Enter(const parser::AccClause::DeviceType &d) {
  CheckAllowed(llvm::acc::Clause::ACCC_device_type);
  if (GetContext().directive == llvm::acc::Directive::ACCD_set &&
      d.v.v.size() > 1) {
    context_.Say(GetContext().clauseSource,
        "The %s clause on the %s directive accepts only one value"_err_en_US,
        parser::ToUpperCaseLetters(
            llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_device_type)
                .str()),
        ContextDirectiveAsFortran());
  }
  ResetCrtGroup();
}

void AccStructureChecker::Enter(const parser::AccClause::Seq &g) {
  llvm::acc::Clause crtClause = llvm::acc::Clause::ACCC_seq;
  if (GetContext().directive == llvm::acc::Directive::ACCD_routine) {
    CheckMutuallyExclusivePerGroup(crtClause,
        llvm::acc::Clause::ACCC_device_type, routineMutuallyExclusiveClauses);
  }
  CheckAllowed(crtClause);
}

void AccStructureChecker::Enter(const parser::AccClause::Vector &g) {
  llvm::acc::Clause crtClause = llvm::acc::Clause::ACCC_vector;
  if (GetContext().directive == llvm::acc::Directive::ACCD_routine) {
    CheckMutuallyExclusivePerGroup(crtClause,
        llvm::acc::Clause::ACCC_device_type, routineMutuallyExclusiveClauses);
  }
  CheckAllowed(crtClause);
  if (GetContext().directive != llvm::acc::Directive::ACCD_routine) {
    CheckAllowedOncePerGroup(crtClause, llvm::acc::Clause::ACCC_device_type);
  }
}

void AccStructureChecker::Enter(const parser::AccClause::Worker &g) {
  llvm::acc::Clause crtClause = llvm::acc::Clause::ACCC_worker;
  if (GetContext().directive == llvm::acc::Directive::ACCD_routine) {
    CheckMutuallyExclusivePerGroup(crtClause,
        llvm::acc::Clause::ACCC_device_type, routineMutuallyExclusiveClauses);
  }
  CheckAllowed(crtClause);
  if (GetContext().directive != llvm::acc::Directive::ACCD_routine) {
    CheckAllowedOncePerGroup(crtClause, llvm::acc::Clause::ACCC_device_type);
  }
}

void AccStructureChecker::Enter(const parser::AccClause::Tile &g) {
  CheckAllowed(llvm::acc::Clause::ACCC_tile);
  CheckAllowedOncePerGroup(
      llvm::acc::Clause::ACCC_tile, llvm::acc::Clause::ACCC_device_type);
}

void AccStructureChecker::Enter(const parser::AccClause::Gang &g) {
  llvm::acc::Clause crtClause = llvm::acc::Clause::ACCC_gang;
  if (GetContext().directive == llvm::acc::Directive::ACCD_routine) {
    CheckMutuallyExclusivePerGroup(crtClause,
        llvm::acc::Clause::ACCC_device_type, routineMutuallyExclusiveClauses);
  }
  CheckAllowed(crtClause);
  if (GetContext().directive != llvm::acc::Directive::ACCD_routine) {
    CheckAllowedOncePerGroup(crtClause, llvm::acc::Clause::ACCC_device_type);
  }

  if (g.v) {
    bool hasNum = false;
    bool hasDim = false;
    bool hasStatic = false;
    const Fortran::parser::AccGangArgList &x = *g.v;
    for (const Fortran::parser::AccGangArg &gangArg : x.v) {
      if (std::get_if<Fortran::parser::AccGangArg::Num>(&gangArg.u)) {
        hasNum = true;
      } else if (std::get_if<Fortran::parser::AccGangArg::Dim>(&gangArg.u)) {
        hasDim = true;
      } else if (std::get_if<Fortran::parser::AccGangArg::Static>(&gangArg.u)) {
        hasStatic = true;
      }
    }

    if (GetContext().directive == llvm::acc::Directive::ACCD_routine &&
        (hasStatic || hasNum)) {
      context_.Say(GetContext().clauseSource,
          "Only the dim argument is allowed on the %s clause on the %s directive"_err_en_US,
          parser::ToUpperCaseLetters(
              llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_gang)
                  .str()),
          ContextDirectiveAsFortran());
    }

    if (hasDim && hasNum) {
      context_.Say(GetContext().clauseSource,
          "The num argument is not allowed when dim is specified"_err_en_US);
    }
  }
}

void AccStructureChecker::Enter(const parser::AccClause::NumGangs &n) {
  CheckAllowed(llvm::acc::Clause::ACCC_num_gangs,
      /*warnInsteadOfError=*/GetContext().directive ==
              llvm::acc::Directive::ACCD_serial ||
          GetContext().directive == llvm::acc::Directive::ACCD_serial_loop);
  CheckAllowedOncePerGroup(
      llvm::acc::Clause::ACCC_num_gangs, llvm::acc::Clause::ACCC_device_type);

  if (n.v.size() > 3)
    context_.Say(GetContext().clauseSource,
        "NUM_GANGS clause accepts a maximum of 3 arguments"_err_en_US);
}

void AccStructureChecker::Enter(const parser::AccClause::NumWorkers &n) {
  CheckAllowed(llvm::acc::Clause::ACCC_num_workers,
      /*warnInsteadOfError=*/GetContext().directive ==
              llvm::acc::Directive::ACCD_serial ||
          GetContext().directive == llvm::acc::Directive::ACCD_serial_loop);
  CheckAllowedOncePerGroup(
      llvm::acc::Clause::ACCC_num_workers, llvm::acc::Clause::ACCC_device_type);
}

void AccStructureChecker::Enter(const parser::AccClause::VectorLength &n) {
  CheckAllowed(llvm::acc::Clause::ACCC_vector_length,
      /*warnInsteadOfError=*/GetContext().directive ==
              llvm::acc::Directive::ACCD_serial ||
          GetContext().directive == llvm::acc::Directive::ACCD_serial_loop);
  CheckAllowedOncePerGroup(llvm::acc::Clause::ACCC_vector_length,
      llvm::acc::Clause::ACCC_device_type);
}

void AccStructureChecker::Enter(const parser::AccClause::Reduction &reduction) {
  CheckAllowed(llvm::acc::Clause::ACCC_reduction);

  // From OpenACC 3.3
  // At a minimum, the supported data types include Fortran logical as well as
  // the numerical data types (e.g. integer, real, double precision, complex).
  // However, for each reduction operator, the supported data types include only
  // the types permitted as operands to the corresponding operator in the base
  // language where (1) for max and min, the corresponding operator is less-than
  // and (2) for other operators, the operands and the result are the same type.
  //
  // The following check that the reduction operator is supported with the given
  // type.
  const parser::AccObjectListWithReduction &list{reduction.v};
  const auto &op{std::get<parser::ReductionOperator>(list.t)};
  const auto &objects{std::get<parser::AccObjectList>(list.t)};

  for (const auto &object : objects.v) {
    common::visit(
        common::visitors{
            [&](const parser::Designator &designator) {
              if (const auto *name =
                      parser::GetDesignatorNameIfDataRef(designator)) {
                if (name->symbol) {
                  if (const auto *type{name->symbol->GetType()}) {
                    if (type->IsNumeric(TypeCategory::Integer) &&
                        !reductionIntegerSet.test(op.v)) {
                      context_.Say(GetContext().clauseSource,
                          "reduction operator not supported for integer type"_err_en_US);
                    } else if (type->IsNumeric(TypeCategory::Real) &&
                        !reductionRealSet.test(op.v)) {
                      context_.Say(GetContext().clauseSource,
                          "reduction operator not supported for real type"_err_en_US);
                    } else if (type->IsNumeric(TypeCategory::Complex) &&
                        !reductionComplexSet.test(op.v)) {
                      context_.Say(GetContext().clauseSource,
                          "reduction operator not supported for complex type"_err_en_US);
                    } else if (type->category() ==
                            Fortran::semantics::DeclTypeSpec::Category::
                                Logical &&
                        !reductionLogicalSet.test(op.v)) {
                      context_.Say(GetContext().clauseSource,
                          "reduction operator not supported for logical type"_err_en_US);
                    }
                  }
                  // TODO: check composite type.
                }
              }
            },
            [&](const Fortran::parser::Name &name) {
              // TODO: check common block
            }},
        object.u);
  }
}

void AccStructureChecker::Enter(const parser::AccClause::Self &x) {
  CheckAllowed(llvm::acc::Clause::ACCC_self);
  const std::optional<parser::AccSelfClause> &accSelfClause = x.v;
  if (GetContext().directive == llvm::acc::Directive::ACCD_update &&
      ((accSelfClause &&
           std::holds_alternative<std::optional<parser::ScalarLogicalExpr>>(
               (*accSelfClause).u)) ||
          !accSelfClause)) {
    context_.Say(GetContext().clauseSource,
        "SELF clause on the %s directive must have a var-list"_err_en_US,
        ContextDirectiveAsFortran());
  } else if (GetContext().directive != llvm::acc::Directive::ACCD_update &&
      accSelfClause &&
      std::holds_alternative<parser::AccObjectList>((*accSelfClause).u)) {
    const auto &accObjectList =
        std::get<parser::AccObjectList>((*accSelfClause).u);
    if (accObjectList.v.size() != 1) {
      context_.Say(GetContext().clauseSource,
          "SELF clause on the %s directive only accepts optional scalar logical"
          " expression"_err_en_US,
          ContextDirectiveAsFortran());
    }
  }
}

void AccStructureChecker::Enter(const parser::AccClause::Collapse &x) {
  CheckAllowed(llvm::acc::Clause::ACCC_collapse);
  CheckAllowedOncePerGroup(
      llvm::acc::Clause::ACCC_collapse, llvm::acc::Clause::ACCC_device_type);
  const parser::AccCollapseArg &accCollapseArg = x.v;
  const auto &collapseValue{
      std::get<parser::ScalarIntConstantExpr>(accCollapseArg.t)};
  RequiresConstantPositiveParameter(
      llvm::acc::Clause::ACCC_collapse, collapseValue);
}

void AccStructureChecker::Enter(const parser::AccClause::Present &x) {
  CheckAllowed(llvm::acc::Clause::ACCC_present);
  CheckMultipleOccurrenceInDeclare(x.v, llvm::acc::Clause::ACCC_present);
}

void AccStructureChecker::Enter(const parser::AccClause::Copy &x) {
  CheckAllowed(llvm::acc::Clause::ACCC_copy);
  CheckMultipleOccurrenceInDeclare(x.v, llvm::acc::Clause::ACCC_copy);
}

void AccStructureChecker::Enter(const parser::AccClause::Deviceptr &x) {
  CheckAllowed(llvm::acc::Clause::ACCC_deviceptr);
  CheckMultipleOccurrenceInDeclare(x.v, llvm::acc::Clause::ACCC_deviceptr);
}

void AccStructureChecker::Enter(const parser::AccClause::DeviceResident &x) {
  CheckAllowed(llvm::acc::Clause::ACCC_device_resident);
  CheckMultipleOccurrenceInDeclare(
      x.v, llvm::acc::Clause::ACCC_device_resident);
}

void AccStructureChecker::Enter(const parser::AccClause::Link &x) {
  CheckAllowed(llvm::acc::Clause::ACCC_link);
  CheckMultipleOccurrenceInDeclare(x.v, llvm::acc::Clause::ACCC_link);
}

void AccStructureChecker::Enter(const parser::AccClause::Shortloop &x) {
  if (CheckAllowed(llvm::acc::Clause::ACCC_shortloop)) {
    context_.Warn(common::UsageWarning::OpenAccUsage, GetContext().clauseSource,
        "Non-standard shortloop clause ignored"_warn_en_US);
  }
}

void AccStructureChecker::Enter(const parser::AccClause::If &x) {
  CheckAllowed(llvm::acc::Clause::ACCC_if);
  if (const auto *expr{GetExpr(x.v)}) {
    if (auto type{expr->GetType()}) {
      if (type->category() == TypeCategory::Integer ||
          type->category() == TypeCategory::Logical) {
        return; // LOGICAL and INTEGER type supported for the if clause.
      }
    }
  }
  context_.Say(
      GetContext().clauseSource, "Must have LOGICAL or INTEGER type"_err_en_US);
}

void AccStructureChecker::Enter(const parser::OpenACCEndConstruct &x) {
  context_.Warn(common::UsageWarning::OpenAccUsage, x.source,
      "Misplaced OpenACC end directive"_warn_en_US);
}

void AccStructureChecker::Enter(const parser::Module &) {
  declareSymbols.clear();
}

void AccStructureChecker::Enter(const parser::FunctionSubprogram &x) {
  declareSymbols.clear();
}

void AccStructureChecker::Enter(const parser::SubroutineSubprogram &) {
  declareSymbols.clear();
}

void AccStructureChecker::Enter(const parser::SeparateModuleSubprogram &) {
  declareSymbols.clear();
}

void AccStructureChecker::Enter(const parser::DoConstruct &) {
  ++loopNestLevel;
}

void AccStructureChecker::Leave(const parser::DoConstruct &) {
  --loopNestLevel;
}

llvm::StringRef AccStructureChecker::getDirectiveName(
    llvm::acc::Directive directive) {
  return llvm::acc::getOpenACCDirectiveName(directive);
}

llvm::StringRef AccStructureChecker::getClauseName(llvm::acc::Clause clause) {
  return llvm::acc::getOpenACCClauseName(clause);
}

} // namespace Fortran::semantics
