//== SemaOpenACCAtomic.cpp - Semantic Analysis for OpenACC Atomic Construct===//
//
// 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
//
//===----------------------------------------------------------------------===//
/// \file
/// This file implements semantic analysis for the OpenACC atomic construct.
///
//===----------------------------------------------------------------------===//

#include "clang/AST/ExprCXX.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Sema/SemaOpenACC.h"

#include <optional>
#include <variant>

using namespace clang;

namespace {

class AtomicOperandChecker {
  SemaOpenACC &SemaRef;
  OpenACCAtomicKind AtKind;
  SourceLocation AtomicDirLoc;
  StmtResult AssocStmt;

  // Do a diagnostic, which sets the correct error, then displays passed note.
  bool DiagnoseInvalidAtomic(SourceLocation Loc, PartialDiagnostic NoteDiag) {
    SemaRef.Diag(AtomicDirLoc, diag::err_acc_invalid_atomic)
        << (AtKind != OpenACCAtomicKind::None) << AtKind;
    SemaRef.Diag(Loc, NoteDiag);
    return true;
  }

  // Create a replacement recovery expr in case we find an error here.  This
  // allows us to ignore this during template instantiation so we only get a
  // single error.
  StmtResult getRecoveryExpr() {
    if (!AssocStmt.isUsable())
      return AssocStmt;

    if (!SemaRef.getASTContext().getLangOpts().RecoveryAST)
      return StmtError();

    Expr *E = dyn_cast<Expr>(AssocStmt.get());
    QualType T = E ? E->getType() : SemaRef.getASTContext().DependentTy;

    return RecoveryExpr::Create(SemaRef.getASTContext(), T,
                                AssocStmt.get()->getBeginLoc(),
                                AssocStmt.get()->getEndLoc(),
                                E ? ArrayRef<Expr *>{E} : ArrayRef<Expr *>{});
  }

  // OpenACC 3.3 2.12: 'expr' is an expression with scalar type.
  bool CheckOperandExpr(const Expr *E, PartialDiagnostic PD) {
    QualType ExprTy = E->getType();

    // Scalar allowed, plus we allow instantiation dependent to support
    // templates.
    if (ExprTy->isInstantiationDependentType() || ExprTy->isScalarType())
      return false;

    return DiagnoseInvalidAtomic(E->getExprLoc(),
                                 PD << diag::OACCLValScalar::Scalar << ExprTy);
  }

  // OpenACC 3.3 2.12: 'x' and 'v' (as applicable) are boht l-value expressoins
  // with scalar type.
  bool CheckOperandVariable(const Expr *E, PartialDiagnostic PD) {
    if (CheckOperandExpr(E, PD))
      return true;

    if (E->isLValue())
      return false;

    return DiagnoseInvalidAtomic(E->getExprLoc(),
                                 PD << diag::OACCLValScalar::LVal);
  }

  Expr *RequireExpr(Stmt *Stmt, PartialDiagnostic ExpectedNote) {
    if (Expr *E = dyn_cast<Expr>(Stmt))
      return E->IgnoreImpCasts();

    DiagnoseInvalidAtomic(Stmt->getBeginLoc(), ExpectedNote);
    return nullptr;
  }

  // A struct to hold the return the inner components of any operands, which
  // allows for compound checking.
  struct BinaryOpInfo {
    const Expr *FoundExpr = nullptr;
    const Expr *LHS = nullptr;
    const Expr *RHS = nullptr;
    BinaryOperatorKind Operator;
  };

  struct UnaryOpInfo {
    const Expr *FoundExpr = nullptr;
    const Expr *SubExpr = nullptr;
    UnaryOperatorKind Operator;

    bool IsIncrementOp() {
      return Operator == UO_PostInc || Operator == UO_PreInc;
    }
  };

  std::optional<UnaryOpInfo> GetUnaryOperatorInfo(const Expr *E) {
    // If this is a simple unary operator, just return its details.
    if (const auto *UO = dyn_cast<UnaryOperator>(E))
      return UnaryOpInfo{UO, UO->getSubExpr()->IgnoreImpCasts(),
                         UO->getOpcode()};

    // This might be an overloaded operator or a dependent context, so make sure
    // we can get as many details out of this as we can.
    if (const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(E)) {
      UnaryOpInfo Inf;
      Inf.FoundExpr = OpCall;

      switch (OpCall->getOperator()) {
      default:
        return std::nullopt;
      case OO_PlusPlus:
        Inf.Operator = OpCall->getNumArgs() == 1 ? UO_PreInc : UO_PostInc;
        break;
      case OO_MinusMinus:
        Inf.Operator = OpCall->getNumArgs() == 1 ? UO_PreDec : UO_PostDec;
        break;
      case OO_Amp:
        Inf.Operator = UO_AddrOf;
        break;
      case OO_Star:
        Inf.Operator = UO_Deref;
        break;
      case OO_Plus:
        Inf.Operator = UO_Plus;
        break;
      case OO_Minus:
        Inf.Operator = UO_Minus;
        break;
      case OO_Tilde:
        Inf.Operator = UO_Not;
        break;
      case OO_Exclaim:
        Inf.Operator = UO_LNot;
        break;
      case OO_Coawait:
        Inf.Operator = UO_Coawait;
        break;
      }

      // Some of the above can be both binary and unary operations, so make sure
      // we get the right one.
      if (Inf.Operator != UO_PostInc && Inf.Operator != UO_PostDec &&
          OpCall->getNumArgs() != 1)
        return std::nullopt;

      Inf.SubExpr = OpCall->getArg(0);
      return Inf;
    }
    return std::nullopt;
  }

  // Get a normalized version of a binary operator.
  std::optional<BinaryOpInfo> GetBinaryOperatorInfo(const Expr *E) {
    if (const auto *BO = dyn_cast<BinaryOperator>(E))
      return BinaryOpInfo{BO, BO->getLHS()->IgnoreImpCasts(),
                          BO->getRHS()->IgnoreImpCasts(), BO->getOpcode()};

    // In case this is an operator-call, which allows us to support overloaded
    // operators and dependent expression.
    if (const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(E)) {
      BinaryOpInfo Inf;
      Inf.FoundExpr = OpCall;

      switch (OpCall->getOperator()) {
      default:
        return std::nullopt;
      case OO_Plus:
        Inf.Operator = BO_Add;
        break;
      case OO_Minus:
        Inf.Operator = BO_Sub;
        break;
      case OO_Star:
        Inf.Operator = BO_Mul;
        break;
      case OO_Slash:
        Inf.Operator = BO_Div;
        break;
      case OO_Percent:
        Inf.Operator = BO_Rem;
        break;
      case OO_Caret:
        Inf.Operator = BO_Xor;
        break;
      case OO_Amp:
        Inf.Operator = BO_And;
        break;
      case OO_Pipe:
        Inf.Operator = BO_Or;
        break;
      case OO_Equal:
        Inf.Operator = BO_Assign;
        break;
      case OO_Spaceship:
        Inf.Operator = BO_Cmp;
        break;
      case OO_Less:
        Inf.Operator = BO_LT;
        break;
      case OO_Greater:
        Inf.Operator = BO_GT;
        break;
      case OO_PlusEqual:
        Inf.Operator = BO_AddAssign;
        break;
      case OO_MinusEqual:
        Inf.Operator = BO_SubAssign;
        break;
      case OO_StarEqual:
        Inf.Operator = BO_MulAssign;
        break;
      case OO_SlashEqual:
        Inf.Operator = BO_DivAssign;
        break;
      case OO_PercentEqual:
        Inf.Operator = BO_RemAssign;
        break;
      case OO_CaretEqual:
        Inf.Operator = BO_XorAssign;
        break;
      case OO_AmpEqual:
        Inf.Operator = BO_AndAssign;
        break;
      case OO_PipeEqual:
        Inf.Operator = BO_OrAssign;
        break;
      case OO_LessLess:
        Inf.Operator = BO_Shl;
        break;
      case OO_GreaterGreater:
        Inf.Operator = BO_Shr;
        break;
      case OO_LessLessEqual:
        Inf.Operator = BO_ShlAssign;
        break;
      case OO_GreaterGreaterEqual:
        Inf.Operator = BO_ShrAssign;
        break;
      case OO_EqualEqual:
        Inf.Operator = BO_EQ;
        break;
      case OO_ExclaimEqual:
        Inf.Operator = BO_NE;
        break;
      case OO_LessEqual:
        Inf.Operator = BO_LE;
        break;
      case OO_GreaterEqual:
        Inf.Operator = BO_GE;
        break;
      case OO_AmpAmp:
        Inf.Operator = BO_LAnd;
        break;
      case OO_PipePipe:
        Inf.Operator = BO_LOr;
        break;
      case OO_Comma:
        Inf.Operator = BO_Comma;
        break;
      case OO_ArrowStar:
        Inf.Operator = BO_PtrMemI;
        break;
      }

      // This isn't a binary operator unless there are two arguments.
      if (OpCall->getNumArgs() != 2)
        return std::nullopt;

      // Callee is the call-operator, so we only need to extract the two
      // arguments here.
      Inf.LHS = OpCall->getArg(0)->IgnoreImpCasts();
      Inf.RHS = OpCall->getArg(1)->IgnoreImpCasts();
      return Inf;
    }

    return std::nullopt;
  }

  // Checks a required assignment operation, but don't check the LHS or RHS,
  // callers have to do that here.
  std::optional<BinaryOpInfo> CheckAssignment(const Expr *E) {
    std::optional<BinaryOpInfo> Inf = GetBinaryOperatorInfo(E);

    if (!Inf) {
      DiagnoseInvalidAtomic(E->getExprLoc(),
                            SemaRef.PDiag(diag::note_acc_atomic_expr_must_be)
                                << diag::OACCAtomicExpr::Assign);
      return std::nullopt;
    }

    if (Inf->Operator != BO_Assign) {
      DiagnoseInvalidAtomic(Inf->FoundExpr->getExprLoc(),
                            SemaRef.PDiag(diag::note_acc_atomic_expr_must_be)
                                << diag::OACCAtomicExpr::Assign);
      return std::nullopt;
    }

    // Assignment always requires an lvalue/scalar on the LHS.
    if (CheckOperandVariable(
            Inf->LHS, SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
                          << /*left=*/0 << diag::OACCAtomicOpKind::Assign))
      return std::nullopt;

    return Inf;
  }

  struct IDACInfo {
    bool Failed = false;
    enum ExprKindTy {
      Invalid,
      // increment/decrement ops.
      Unary,
      // v = x
      SimpleAssign,
      // x = expr
      ExprAssign,
      // x binop= expr
      CompoundAssign,
      // x = x binop expr
      // x = expr binop x
      AssignBinOp
    } ExprKind;

    // The variable referred to as 'x' in all of the grammar, such that it is
    // needed in compound statement checking of capture to check between the two
    // expressions.
    const Expr *X_Var = nullptr;

    static IDACInfo Fail() { return IDACInfo{true, Invalid, nullptr}; };
  };

  // Helper for CheckIncDecAssignCompoundAssign, does checks for inc/dec.
  IDACInfo CheckIncDec(UnaryOpInfo Inf) {

    if (!UnaryOperator::isIncrementDecrementOp(Inf.Operator)) {
      DiagnoseInvalidAtomic(
          Inf.FoundExpr->getExprLoc(),
          SemaRef.PDiag(diag::note_acc_atomic_unsupported_unary_operator));
      return IDACInfo::Fail();
    }
    bool Failed = CheckOperandVariable(
        Inf.SubExpr,
        SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
            << /*none=*/2
            << (Inf.IsIncrementOp() ? diag::OACCAtomicOpKind::Inc
                                    : diag::OACCAtomicOpKind::Dec));
    // For increment/decrements, the subexpr is the 'x' (x++, ++x, etc).
    return IDACInfo{Failed, IDACInfo::Unary, Inf.SubExpr};
  }

  enum class SimpleAssignKind { None, Var, Expr };

  // Check an assignment, and ensure the RHS is either x binop expr or expr
  // binop x.
  // If AllowSimpleAssign, also allows v = x;
  IDACInfo CheckAssignmentWithBinOpOnRHS(BinaryOpInfo AssignInf,
                                         SimpleAssignKind SAK) {
    PartialDiagnostic PD =
        SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
        << /*left=*/0 << diag::OACCAtomicOpKind::Assign;
    if (CheckOperandVariable(AssignInf.LHS, PD))
      return IDACInfo::Fail();

    std::optional<BinaryOpInfo> BinInf = GetBinaryOperatorInfo(AssignInf.RHS);

    if (!BinInf) {

      // Capture in a compound statement allows v = x assignment.  So make sure
      // we permit that here.
      if (SAK != SimpleAssignKind::None) {
        PartialDiagnostic PD =
            SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
            << /*right=*/1 << diag::OACCAtomicOpKind::Assign;
        if (SAK == SimpleAssignKind::Var) {
          // In the var version, everywhere we allow v = x;, X is the RHS.
          return IDACInfo{CheckOperandVariable(AssignInf.RHS, PD),
                          IDACInfo::SimpleAssign, AssignInf.RHS};
        }
        assert(SAK == SimpleAssignKind::Expr);
        // In the expression version, supported by v=x; x = expr;, we need to
        // set to the LHS here.
        return IDACInfo{CheckOperandExpr(AssignInf.RHS, PD),
                        IDACInfo::ExprAssign, AssignInf.LHS};
      }

      DiagnoseInvalidAtomic(
          AssignInf.RHS->getExprLoc(),
          SemaRef.PDiag(diag::note_acc_atomic_expected_binop));

      return IDACInfo::Fail();
    }
    switch (BinInf->Operator) {
    default:
      DiagnoseInvalidAtomic(
          BinInf->FoundExpr->getExprLoc(),
          SemaRef.PDiag(diag::note_acc_atomic_unsupported_binary_operator));
      return IDACInfo::Fail();
      // binop is one of +, *, -, /, &, ^, |, <<, or >>
    case BO_Add:
    case BO_Mul:
    case BO_Sub:
    case BO_Div:
    case BO_And:
    case BO_Xor:
    case BO_Or:
    case BO_Shl:
    case BO_Shr:
      // Handle these outside of the switch.
      break;
    }

    llvm::FoldingSetNodeID LHS_ID, InnerLHS_ID, InnerRHS_ID;
    AssignInf.LHS->Profile(LHS_ID, SemaRef.getASTContext(),
                           /*Canonical=*/true);
    BinInf->LHS->Profile(InnerLHS_ID, SemaRef.getASTContext(),
                         /*Canonical=*/true);

    // This is X = X binop expr;
    // Check the RHS is an expression.
    if (LHS_ID == InnerLHS_ID)
      return IDACInfo{
          CheckOperandExpr(
              BinInf->RHS,
              SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar
                            << /*right=*/1
                            << diag::OACCAtomicOpKind::CompoundAssign)),
          IDACInfo::AssignBinOp, AssignInf.LHS};

    BinInf->RHS->Profile(InnerRHS_ID, SemaRef.getASTContext(),
                         /*Canonical=*/true);
    // This is X = expr binop X;
    // Check the LHS is an expression
    if (LHS_ID == InnerRHS_ID)
      return IDACInfo{
          CheckOperandExpr(
              BinInf->LHS,
              SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
                  << /*left=*/0 << diag::OACCAtomicOpKind::CompoundAssign),
          IDACInfo::AssignBinOp, AssignInf.LHS};

    // If nothing matches, error out.
    DiagnoseInvalidAtomic(BinInf->FoundExpr->getExprLoc(),
                          SemaRef.PDiag(diag::note_acc_atomic_mismatch_operand)
                              << const_cast<Expr *>(AssignInf.LHS)
                              << const_cast<Expr *>(BinInf->LHS)
                              << const_cast<Expr *>(BinInf->RHS));
    return IDACInfo::Fail();
  }

  // Ensures that the expression is an increment/decrement, an assignment, or a
  // compound assignment. If its an assignment, allows the x binop expr/x binop
  // expr syntax. If it is a compound-assignment, allows any expr on the RHS.
  IDACInfo CheckIncDecAssignCompoundAssign(const Expr *E,
                                           SimpleAssignKind SAK) {
    std::optional<UnaryOpInfo> UInf = GetUnaryOperatorInfo(E);

    // If this is a unary operator, only increment/decrement are allowed, so get
    // unary operator, then check everything we can.
    if (UInf)
      return CheckIncDec(*UInf);

    std::optional<BinaryOpInfo> BinInf = GetBinaryOperatorInfo(E);

    // Unary or binary operator were the only choices, so error here.
    if (!BinInf) {
      DiagnoseInvalidAtomic(E->getExprLoc(),
                            SemaRef.PDiag(diag::note_acc_atomic_expr_must_be)
                                << diag::OACCAtomicExpr::UnaryCompAssign);
      return IDACInfo::Fail();
    }

    switch (BinInf->Operator) {
    default:
      DiagnoseInvalidAtomic(
          BinInf->FoundExpr->getExprLoc(),
          SemaRef.PDiag(
              diag::note_acc_atomic_unsupported_compound_binary_operator));
      return IDACInfo::Fail();
    case BO_Assign:
      return CheckAssignmentWithBinOpOnRHS(*BinInf, SAK);
    case BO_AddAssign:
    case BO_MulAssign:
    case BO_SubAssign:
    case BO_DivAssign:
    case BO_AndAssign:
    case BO_XorAssign:
    case BO_OrAssign:
    case BO_ShlAssign:
    case BO_ShrAssign: {
      PartialDiagnostic LPD =
          SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
          << /*left=*/0 << diag::OACCAtomicOpKind::CompoundAssign;
      PartialDiagnostic RPD =
          SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
          << /*right=*/1 << diag::OACCAtomicOpKind::CompoundAssign;
      // nothing to do other than check the variable expressions.
      // success or failure
      bool Failed = CheckOperandVariable(BinInf->LHS, LPD) ||
                    CheckOperandExpr(BinInf->RHS, RPD);

      return IDACInfo{Failed, IDACInfo::CompoundAssign, BinInf->LHS};
    }
    }
    llvm_unreachable("all binary operator kinds should be checked above");
  }

  StmtResult CheckRead() {
    Expr *AssocExpr = RequireExpr(
        AssocStmt.get(), SemaRef.PDiag(diag::note_acc_atomic_expr_must_be)
                             << diag::OACCAtomicExpr::Assign);

    if (!AssocExpr)
      return getRecoveryExpr();

    std::optional<BinaryOpInfo> AssignRes = CheckAssignment(AssocExpr);
    if (!AssignRes)
      return getRecoveryExpr();

    PartialDiagnostic PD =
        SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
        << /*right=*/1 << diag::OACCAtomicOpKind::Assign;

    // Finally, check the RHS.
    if (CheckOperandVariable(AssignRes->RHS, PD))
      return getRecoveryExpr();

    return AssocStmt;
  }

  StmtResult CheckWrite() {
    Expr *AssocExpr = RequireExpr(
        AssocStmt.get(), SemaRef.PDiag(diag::note_acc_atomic_expr_must_be)
                             << diag::OACCAtomicExpr::Assign);

    if (!AssocExpr)
      return getRecoveryExpr();

    std::optional<BinaryOpInfo> AssignRes = CheckAssignment(AssocExpr);
    if (!AssignRes)
      return getRecoveryExpr();

    PartialDiagnostic PD =
        SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
        << /*right=*/1 << diag::OACCAtomicOpKind::Assign;

    // Finally, check the RHS.
    if (CheckOperandExpr(AssignRes->RHS, PD))
      return getRecoveryExpr();

    return AssocStmt;
  }

  StmtResult CheckUpdate() {
    Expr *AssocExpr = RequireExpr(
        AssocStmt.get(), SemaRef.PDiag(diag::note_acc_atomic_expr_must_be)
                             << diag::OACCAtomicExpr::UnaryCompAssign);

    if (!AssocExpr ||
        CheckIncDecAssignCompoundAssign(AssocExpr, SimpleAssignKind::None)
            .Failed)
      return getRecoveryExpr();

    return AssocStmt;
  }

  bool CheckVarRefsSame(IDACInfo::ExprKindTy FirstKind, const Expr *FirstX,
                        IDACInfo::ExprKindTy SecondKind, const Expr *SecondX) {
    llvm::FoldingSetNodeID First_ID, Second_ID;
    FirstX->Profile(First_ID, SemaRef.getASTContext(), /*Canonical=*/true);
    SecondX->Profile(Second_ID, SemaRef.getASTContext(), /*Canonical=*/true);

    if (First_ID == Second_ID)
      return false;

    PartialDiagnostic PD =
        SemaRef.PDiag(diag::note_acc_atomic_mismatch_compound_operand)
        << FirstKind << const_cast<Expr *>(FirstX) << SecondKind
        << const_cast<Expr *>(SecondX);

    return DiagnoseInvalidAtomic(SecondX->getExprLoc(), PD);
  }

  StmtResult CheckCapture() {
    if (const auto *CmpdStmt = dyn_cast<CompoundStmt>(AssocStmt.get())) {
      auto *const *BodyItr = CmpdStmt->body().begin();
      PartialDiagnostic PD = SemaRef.PDiag(diag::note_acc_atomic_expr_must_be)
                             << diag::OACCAtomicExpr::UnaryCompAssign;
      // If we don't have at least 1 statement, error.
      if (BodyItr == CmpdStmt->body().end()) {
        DiagnoseInvalidAtomic(CmpdStmt->getBeginLoc(), PD);
        return getRecoveryExpr();
      }

      // First Expr can be inc/dec, assign, or compound assign.
      Expr *FirstExpr = RequireExpr(*BodyItr, PD);
      if (!FirstExpr)
        return getRecoveryExpr();

      IDACInfo FirstExprResults =
          CheckIncDecAssignCompoundAssign(FirstExpr, SimpleAssignKind::Var);
      if (FirstExprResults.Failed)
        return getRecoveryExpr();

      ++BodyItr;

      // If we don't have second statement, error.
      if (BodyItr == CmpdStmt->body().end()) {
        DiagnoseInvalidAtomic(CmpdStmt->getEndLoc(), PD);
        return getRecoveryExpr();
      }

      Expr *SecondExpr = RequireExpr(*BodyItr, PD);
      if (!SecondExpr)
        return getRecoveryExpr();

      assert(FirstExprResults.ExprKind != IDACInfo::Invalid);

      switch (FirstExprResults.ExprKind) {
      case IDACInfo::Invalid:
      case IDACInfo::ExprAssign:
        llvm_unreachable("Should have error'ed out by now");
      case IDACInfo::Unary:
      case IDACInfo::CompoundAssign:
      case IDACInfo::AssignBinOp: {
        // Everything but simple-assign can only be followed by a simple
        // assignment.
        std::optional<BinaryOpInfo> AssignRes = CheckAssignment(SecondExpr);
        if (!AssignRes)
          return getRecoveryExpr();

        PartialDiagnostic PD =
            SemaRef.PDiag(diag::note_acc_atomic_operand_lvalue_scalar)
            << /*right=*/1 << diag::OACCAtomicOpKind::Assign;

        if (CheckOperandVariable(AssignRes->RHS, PD))
          return getRecoveryExpr();

        if (CheckVarRefsSame(FirstExprResults.ExprKind, FirstExprResults.X_Var,
                             IDACInfo::SimpleAssign, AssignRes->RHS))
          return getRecoveryExpr();
        break;
      }
      case IDACInfo::SimpleAssign: {
        // If the first was v = x, anything but simple expression is allowed.
        IDACInfo SecondExprResults =
            CheckIncDecAssignCompoundAssign(SecondExpr, SimpleAssignKind::Expr);
        if (SecondExprResults.Failed)
          return getRecoveryExpr();

        if (CheckVarRefsSame(FirstExprResults.ExprKind, FirstExprResults.X_Var,
                             SecondExprResults.ExprKind,
                             SecondExprResults.X_Var))
          return getRecoveryExpr();
        break;
      }
      }
      ++BodyItr;
      if (BodyItr != CmpdStmt->body().end()) {
        DiagnoseInvalidAtomic(
            (*BodyItr)->getBeginLoc(),
            SemaRef.PDiag(diag::note_acc_atomic_too_many_stmts));
        return getRecoveryExpr();
      }
    } else {
      // This check doesn't need to happen if it is a compound stmt.
      Expr *AssocExpr = RequireExpr(
          AssocStmt.get(), SemaRef.PDiag(diag::note_acc_atomic_expr_must_be)
                               << diag::OACCAtomicExpr::Assign);
      if (!AssocExpr)
        return getRecoveryExpr();

      // First, we require an assignment.
      std::optional<BinaryOpInfo> AssignRes = CheckAssignment(AssocExpr);

      if (!AssignRes)
        return getRecoveryExpr();

      if (CheckIncDecAssignCompoundAssign(AssignRes->RHS,
                                          SimpleAssignKind::None)
              .Failed)
        return getRecoveryExpr();
    }

    return AssocStmt;
  }

public:
  AtomicOperandChecker(SemaOpenACC &S, OpenACCAtomicKind AtKind,
                       SourceLocation DirLoc, StmtResult AssocStmt)
      : SemaRef(S), AtKind(AtKind), AtomicDirLoc(DirLoc), AssocStmt(AssocStmt) {
  }

  StmtResult Check() {

    switch (AtKind) {
    case OpenACCAtomicKind::Read:
      return CheckRead();
    case OpenACCAtomicKind::Write:
      return CheckWrite();
    case OpenACCAtomicKind::None:
    case OpenACCAtomicKind::Update:
      return CheckUpdate();
    case OpenACCAtomicKind::Capture:
      return CheckCapture();
    }
    llvm_unreachable("Unhandled atomic kind?");
  }
};
} // namespace

StmtResult SemaOpenACC::CheckAtomicAssociatedStmt(SourceLocation AtomicDirLoc,
                                                  OpenACCAtomicKind AtKind,
                                                  StmtResult AssocStmt) {
  if (!AssocStmt.isUsable())
    return AssocStmt;

  if (isa<RecoveryExpr>(AssocStmt.get()))
    return AssocStmt;

  AtomicOperandChecker Checker{*this, AtKind, AtomicDirLoc, AssocStmt};
  return Checker.Check();
}
